0

我正在根据其他人的 XSD 规范创建一个 XML 文件,但我就是不知道为什么它不验证。

这是规则:

<xs:simpleType name="NonEmptyStringType">
    <xs:restriction base="xs:string">
        <xs:minLength value="1" />
        <xs:pattern value="[^\t\n\r]*[^\s][^\t\n\r]*" />
    </xs:restriction>
</xs:simpleType>

我在其中阅读模式如下:

  • [^\t\n\r]*匹配任何不是制表符、换行符或空格的内容返回 0 次或更多次
  • [^\s]匹配任何不是空格的东西
  • [^\t\n\r]*匹配任何不是制表符、换行符或空格的内容返回 0 次或更多次

以下是许多不匹配的 xml 之一的示例:

        <Zipcode>3506 RT</Zipcode>

根据 xmllint,它不匹配3506 RT(或者3506RT就此而言,以及我希望匹配的许多其他内容),并出现以下错误:

element Zipcode: Schemas validity error : Element '{http://www.reeleezee.nl/taxonomy/1.23}Zipcode': [facet 'pattern'] The value '3506 RT' is not accepted by the pattern '[^\t\n\r]*[^\s][^\t\n\r]*'.

关于我没有正确解释的任何提示?(顺便说一句,我不明白他们 NonEmptyStringType 的严格性,我只会使用 .+)


根据要求,这是邮政编码声明:

<xs:element name="Zipcode" minOccurs="0" nillable="true" rse:CanIgnore="true">
    <xs:annotation>
        <xs:documentation>Postcode</xs:documentation>
    </xs:annotation>
    <xs:simpleType>
        <xs:restriction base="NonEmptyStringType">
            <xs:maxLength value="10" />
        </xs:restriction>
    </xs:simpleType>
</xs:element>

如您所见,这链接回 NonEmptyStringType 中的模式(上面发布的第一条规则)

4

3 回答 3

3

这个正则表达式对我来说看起来不错。我认为这是您的验证工具中的一个错误……它们在极端情况下通常是错误的。

好的,刚刚检查:xerces 接受它;xmllint 失败(我看到您使用的是 xmllint)。我过去多次发现 xerces 是正确的,而 xmllint 在不寻常的情况下会出现问题。这个正则表达式很不寻常。(我不得不说,我真的很喜欢 xmllint,它真的很快,但是 xsd 规范是巨大的、复杂的和令人困惑的,而且 xmllint 的人还没有确定所有的边缘情况)。

我试过的两个在线验证器也接受它:http ://www.utilities-online.info/xsdvalidation和http://www.freeformatter.com/xml-validator-xsd.html

顺便说一句:对于 xerces,我下载了他们的 java 版本,并发现他们的类jaxp.SourceValidator是验证的最佳工具。但我相信它已经在 java 中使用了相同的代码。


编辑我在 xerces 中做了更多测试,以确保正则表达式可以失败(即它是活动的)。如果有\n任何地方,它就会失败。(同样的\t,虽然我没有测试\r)。

检查规范,\s定义为[#x20\t\n\r] (在此表中)。这清楚地表明正则表达式是说你不能拥有\t\n\r 任何地方。但是您可以拥有任意数量的文字空格字符 ( #x20),前提是它们不都是空格字符(即至少有一个非空格字符来匹配[^\s]- 顺便说一句,可以将其表示为\S)。Xerces 证实了这一点:所有空格都会出错。

Maybe they want to allow space literals (both padding and interspersing), provided there is some value in there (i.e. not all spaces).

于 2013-01-28T11:46:40.633 回答
1

[^\s] match anything that is not a space

但是您的输入字符串3506 RT有空格!

我认为这就是它失败的原因:) 因为在它[^\t\n\r]通过3506之后你不会期望一个空格字符[^\s]但它会出现!并且[^\t\n\r]也通过了,因为下一组字符是RT

所以你应该声明的是:

<xs:pattern value="[^\t\n\r\s]*[\s][^\t\n\r\s]*" />

现在这将允许

  1. 任何NOT \t, \n, \r and \s对模式更严格的东西,您都想添加 + ,它仅在字符串开头至少有一个非空白字符时才允许字符串。
  2. 一个空格字符:我们可以通过像这样声明它作为可选字符[\s]?.. where ? 允许一次或根本不允许。所以空格字符不能重复。
  3. 再说一遍 NOT \t, \n, \r and \s

<xs:pattern value="[^\t\n\r\s]+[\s]?[^\t\n\r\s]*" />

实际上,可以通过验证数字和字母字符而不是[^\t\n\r\s]声明来使其更加严格。

希望能帮助到你!如果有任何问题困扰您,请告诉我。

于 2013-01-28T06:32:33.603 回答
0

我不相信 \r 是一个空格,它是一个回车(类似于 \n 换行符)。您可能想用 \s 或只是实际的文字“”替换它。

于 2013-01-27T19:12:35.143 回答