背景:我正在尝试找到一种方法来针对 XSD 验证 XSD 和 XML,这种方法可以自动集成到软件构建过程中。输入是文件,对于输出,退出代码或可靠的正则表达式控制台输出就足够了。我在 Windows 环境中操作。
作为 XML 和 XSD 输入,我从 Wikipedia(文章“XML Schema (W3C)”)中获取了一个示例。
问题是,XMLLint 和 Xerces 给出了不同的结果。
这引出了我的问题:我还有哪些其他选择来评估这些工具?我应该如何决定选择哪种工具?
来自维基百科的 XML 数据示例 SimpleAddress.xml:
<?xml version="1.0" encoding="utf-8"?>
<Address xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="SimpleAddress.xsd">
<Recipient>Mr. Walter C. Brown</Recipient>
<House>49</House>
<Street>Featherstone Street</Street>
<Town>LONDON</Town>
<PostCode>EC1Y 8SY</PostCode>
<Country>UK</Country>
</Address>
来自维基百科的 XSD 模式示例 SimpleAddress.xsd:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Address">
<xs:complexType>
<xs:sequence>
<xs:element name="Recipient" type="xs:string" />
<xs:element name="House" type="xs:string" />
<xs:element name="Street" type="xs:string" />
<xs:element name="Town" type="xs:string" />
<xs:element name="County" type="xs:string" minOccurs="0" />
<xs:element name="PostCode" type="xs:string" />
<xs:element name="Country" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="IN" />
<xs:enumeration value="DE" />
<xs:enumeration value="ES" />
<xs:enumeration value="UK" />
<xs:enumeration value="US" />
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
首先我使用 XMLLint 进行测试:
$ xmllint.exe --noout --schema SimpleAddress.xsd SimpleAddress.xml
SimpleAddress.xml validates
$ xmllint.exe --noout --schema http://www.w3.org/2001/XMLSchema.xsd SimpleAddress.xsd
SimpleAddress.xsd validates
当我故意在要验证的文件中放置一个额外的属性或标签时,XMLLint 也会给我带来有意义的错误结果。
使用 XMLLint,我还尝试针对自身验证 W3C 的 XML 模式定义:
$ xmllint.exe --noout --schema http://www.w3.org/2001/XMLSchema.xsd http://www.w3.org/2001/XMLSchema.xsd
http://www.w3.org/2001/XMLSchema.xsd validates
其次,我使用 Xerces 进行的测试会产生很多警告和错误:
$ StdInParse.exe -n -s -f -v=always < SimpleAddress.xml
stdin: 1 ms (7 elems, 2 attrs, 19 spaces, 56 chars)
$ StdInParse.exe -n -s -f -v=always < SimpleAddress.xsd
Error at (file stdin, line 2, char 87): no declaration found for element 'xs:schema'
Error at (file stdin, line 2, char 87): attribute 'elementFormDefault' is not declared for element 'xs:schema'
Error at (file stdin, line 2, char 87): attribute '{http://www.w3.org/2000/xmlns/}xs' is not declared for element 'xs:schema'
Error at (file stdin, line 3, char 30): no declaration found for element 'xs:element'
(…)
对于以下测试,我在 SimpleAddress.xsd 的开始标记中添加了“xmlns:xsi”和“xsi:schemaLocation”属性:
<xs:schema
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3.org/2001/XMLSchema http://www.w3.org/2001/XMLSchema.xsd"
>
XMLLint 产生相同的结果:
$ xmllint.exe --noout --schema http://www.w3.org/2001/XMLSchema.xsd SimpleAddress.xsd
SimpleAddress.xsd validates
Xerces 产生了更多的警告和错误,现在也涉及 W3C 的文档:
$ StdInParse.exe -n -s -f -v=always < SimpleAddress.xsd
Warning at (file http://www.w3.org/2001/datatypes.dtd, line 99, char 7): attribute 'id' has already been declared for element 'xs:simpleType'
Warning at (file http://www.w3.org/2001/datatypes.dtd, line 122, char 7): attribute 'id' has already been declared for element 'xs:list'
Warning at (file http://www.w3.org/2001/datatypes.dtd, line 130, char 7): attribute 'id' has already been declared for element 'xs:union'
Warning at (file http://www.w3.org/2001/datatypes.dtd, line 140, char 20): attribute 'id' has already been declared for element 'xs:maxExclusive'
(…)
Error at (file stdin, line 15, char 68): unable to find validator for simple type of attribute 'maxOccurs'
Error at (file stdin, line 16, char 56): unable to find validator for simple type of attribute 'maxOccurs'
Error at (file stdin, line 17, char 50): unable to find validator for simple type of attribute 'maxOccurs'
总之,XMLLint 似乎可以满足我的需要,但是它有一个主要缺点。它要求我将要验证的 XSD 文件指定为单独的参数,因为它似乎无法从 XML 输入文件中读取相应的 xmlns 属性。
另一方面是Xerces。它似乎被广泛使用并声称忠实于此类文档中使用的相同标准,但即使关于 W3C 的文档也会产生很多错误和警告。所以,我问自己,我用对了吗?我想让它工作,因为它不需要我为 XMLLint 的必要额外参数找到解决方法。