Xmllint : validate an XML file against two XSD schemas (envelope / payload)

xmlxmllintxsd

I am using xmllint to do some validations and I have an XML instance document which needs to validate against two schemas: one for the outer "envelope" (which includes an any element) and one for the particular payload. Say A.xsd is the envelope schema, B.xsd a payload schema (there are different possible payloads) and ab.xml a valid XML instance document (I provide an example at the end of the post).

I have all three files locally available in the same directory and am using xmllint to perform the validation, providing as the schema argument the location of the outer (envelope) schema:

xmllint -schema A.xsd ab.xml

… yet, although I provide the location of both A.xsd and B.xsd in the instance document (using the xsi:schemaLocation element) xmllint fails to find it and complains:

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

So apparently xmllint is not reading the xsi:schemaLocation element. I understand that xmllint can be configured with catalogs but I failed to get xmllint to find both schemas. How should I get xmllint to take into account both schemas when validating the instance document or is there another command line utility or graphical tool I could use instead?

SSCCE

A.xsd – envelope schema

<?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 – payload schema

<?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 – instance document

<?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>

Best Answer

You can create a wrapper schema and import both namespaces. 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>

Then:

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
Related Topic