XSD验证疑问:totalDigits与fractionDigits规则下处理器行为合规吗?
结论:这个处理器的行为是正确的,但背后的逻辑和你对XSD facet限制的理解存在偏差,下面具体拆解:
核心知识点:XSD Facet 作用于「值空间」而非「词法空间」
XSD 中的 totalDigits 和 fractionDigits 限制,是针对 XML 元素解析后的数值本身(值空间),而不是原始的字符串书写形式(词法空间)。也就是说,处理器会先把你的 XML 字符串转换成对应的 decimal 数值,再基于这个数值检查限制,而不是直接数字符串里的数字个数。
你的两个案例具体分析
被判定为有效的案例:
<MySum>123456789012345.00</MySum>
这个字符串解析后等价于整数123456789012345,它的总有效数字是 15 位(没有小数部分),完全满足totalDigits="15"的要求;同时小数位数为 0,小于fractionDigits="2"的最大限制,因此被判定为有效。这里不存在「舍入处理」,只是这个带尾随零的字符串和整数在数值上完全等价。被判定为无效的案例:
<MySum>123456789012345.01</MySum>
这个字符串解析后的数值是123456789012345.01,总有效数字是 17 位(15 位整数 + 2 位小数),超过了totalDigits="15"的上限,因此被判定为无效。
如果需要严格限制字符串格式(不忽略尾随零)
如果你希望基于原始字符串的数字个数进行限制(比如必须保留两位小数,且包括尾随零在内的总数字数不超过 15),那应该改用 xs:string 类型配合正则表达式,而不是依赖 xs:decimal 的 facet:
<xs:restriction base="xs:string"> <!-- 匹配两种情况:1-15位整数;或1-13位整数 + 1-2位小数(总数字数不超过15) --> <xs:pattern value="\d{1,15}|\d{1,13}\.\d{1,2}"/> </xs:restriction>
这样就能精准匹配你想要的字符串格式,不会因为数值等价性跳过对尾随零的检查。
内容的提问来源于stack exchange,提问作者gisly

