xmllint:针对两个XSD架构验证XML文件(包络/有效负载)

时间:2013-06-08 18:02:34

标签: xml xsd xmllint

我正在使用xmllint进行一些验证,我有一个XML实例文档需要针对两个模式进行验证:一个用于外部“信封”(包括任何元素)和一个特定的有效载荷。说 A.xsd 是信封模式, B.xsd 有效负载模式(有不同的可能有效负载)和 ab.xml 是有效的XML实例文档(我在帖子的末尾提供了一个例子)。

我在同一目录中本地提供了所有三个文件,并使用xmllint执行验证,提供外部(信封)模式的位置作为模式参数:< / p>

xmllint -schema A.xsd ab.xml

...但是,虽然我在实例文档中提供了A.xsd和B.xsd的位置(使用 xsi:schemaLocation 元素) xmllint 失败找到并抱怨:

ab.xml:8: element person: Schemas validity error : Element '{http://www.example.org/B}person': No matching global element declaration available, but demanded by the strict wildcard.
ab.xml fails to validate

显然 xmllint 没有读取 xsi:schemaLocation 元素。我了解 xmllint 可以使用目录进行配置,但我无法获得 xmllint 来查找两个模式。我应该如何让 xmllint 在验证实例文档时考虑这两种模式,或者是否可以使用其他命令行实用程序或图形工具?

SSCCE

A.xsd - 信封架构

<?xml version="1.0" encoding="UTF-8"?>
<schema elementFormDefault="qualified" 
        xmlns               ="http://www.w3.org/2001/XMLSchema"
        xmlns:a             ="http://www.example.org/A"
        targetNamespace ="http://www.example.org/A">

       <element name="someType" type="a:SomeType"></element>

        <complexType name="SomeType">
            <sequence>
                <any namespace="##other" processContents="strict"/>
            </sequence>
        </complexType>
</schema>

B.xsd - 有效负载模式

<?xml version="1.0" encoding="UTF-8"?>
<schema elementFormDefault="qualified"
    xmlns          ="http://www.w3.org/2001/XMLSchema"
    xmlns:b        ="http://www.example.org/B"
    targetNamespace="http://www.example.org/B"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <element name="person" type="b:PersonType"></element>
    <complexType name="PersonType">
        <sequence>
                <element name="firstName" type="string"/>
                <element name="lastName"  type="string"/>
        </sequence>
    </complexType>
  </schema>

ab.xml - 实例文档

<?xml version="1.0" encoding="UTF-8"?>
<a:someType xmlns:a="http://www.example.org/A"
        xmlns:b="http://www.example.org/B"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.example.org/A A.xsd
                            http://www.example.org/B B.xsd">

            <b:person>
                <b:firstName>Mary</b:firstName>
                <b:lastName>Bones</b:lastName>
            </b:person>

</a:someType>

3 个答案:

答案 0 :(得分:12)

我退出 xmllint 并使用 Xerces 代替。

我下载了Xerces tarball,在将其爆炸到某个本地文件夹后,我根据this suggestion创建了以下验证脚本(来自网络存档 - 原始链接现已死亡) :

#!/bin/bash
XERCES_HOME=~/software-downloads/xerces-2_11_0/
echo $XERCES_HOME
java -classpath $XERCES_HOME/xercesImpl.jar:$XERCES_HOME/xml-apis.jar:$XERCES_HOME/xercesSamples.jar sax.Counter $*

然后使用以下命令对两个模式验证 ab.xml 文件:

 validate -v -n -np -s -f ab.xml

Xerces正在从 ab.xml 中的 xsi:schemaLocation 元素读取架构位置,因此不需要在命令行调用中提供它们。

答案 1 :(得分:9)

您可以创建包装器架构并导入两个命名空间。 AB.xsd:

<?xml version="1.0" encoding="UTF-8"?>
<schema elementFormDefault="qualified" xmlns="http://www.w3.org/2001/XMLSchema">
    <import namespace="http://www.example.org/A" schemaLocation="A.xsd"/>
    <import namespace="http://www.example.org/B" schemaLocation="B.xsd"/>
</schema>

然后:

xmllint --schema AB.xsd ab.xml
<?xml version="1.0" encoding="UTF-8"?>
<a:someType xmlns:a="http://www.example.org/A" xmlns:b="http://www.example.org/B" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/A A.xsd                             http://www.example.org/B B.xsd">

            <b:person>
                <b:firstName>Mary</b:firstName>
                <b:lastName>Bones</b:lastName>
            </b:person>

</a:someType>
ab.xml validates

答案 2 :(得分:5)

如果您的import中有A.xsd元素,则在打开schema标记后

<xsd:import namespace="http://www.example.org/B" schemaLocation="B.xsd"/>

然后您可以将A.xsd传递给xmllint,它可以用于:

xmllint -schema A.xsd ab.xml