xmllxmlxsd-validationxmllintxmlspy

Who is right and who does the faulty validation (Me, XMLSpy, lxml.etree or xmllint)


I have tried to validate the following XML with the afterwards following xsd file in the same folder. According to Altova XMLSpy this is completely valid but to help some collegues without licenses to find out about basic faults I have tried to validate the files with python and 'lxml.etree' and also with xmllint. These two say the xml is invalid with the same message:

machineDB.xml:20: Schemas validity error : Element 'canframe': No match found for key-sequence ['remotebus'] of keyref 'busRef'. machineDB.xml fails to validate

Could someone help to find anyones fault?


Versions:

Altova XMLSpy Professional Edition version 2016 rel. 2 sp1 (x64)

lxml.etree versions

Python : sys.version_info(major=2, minor=7, micro=11, releaselevel='final', serial=0) lxml.etree : (3, 7, 2, 0) libxml used : (2, 9, 4) libxml compiled : (2, 9, 4) libxslt used : (1, 1, 29) libxslt compiled : (1, 1, 29)

xmllint (using libxml version 20708)

machineDB.xml file:

<machinedb xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="machinedb.xsd">
    <busdefinition>
        <bus name="displaybus"></bus>
        <bus name="remotebus"></bus>
    </busdefinition>
    <cdefinition>
        <c>
            <canbus bus_ref="remotebus"></canbus>
            <canbus bus_ref="displaybus"></canbus>
        </c>
        <c>
            <canbus bus_ref="displaybus"></canbus>
        </c>
        <c>
            <canbus bus_ref="remotebus"></canbus>
        </c>
    </cdefinition>
    <sdefinition>
        <s>
            <canframe bus_ref="remotebus"></canframe>
        </s>
    </sdefinition>
</machinedb>

machinedb.xsd file:

<xs:schema xmlns:altova="http://www.altova.com/xml-schema-extensions" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" elementFormDefault="qualified" attributeFormDefault="unqualified" vc:minVersion="1.1">
    <xs:element name="machinedb">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="busdefinition" minOccurs="0">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="bus" minOccurs="0" maxOccurs="unbounded">
                                <xs:complexType>
                                    <xs:attribute name="name" type="NameType" use="required"/>
                                </xs:complexType>
                            </xs:element>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
                <xs:element name="cdefinition" minOccurs="0">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="c" minOccurs="0" maxOccurs="unbounded">
                                <xs:complexType>
                                    <xs:sequence minOccurs="0" maxOccurs="unbounded">
                                        <xs:choice>
                                            <xs:element name="canbus" minOccurs="0" maxOccurs="unbounded">
                                                <xs:complexType>
                                                    <xs:attribute name="bus_ref" type="NameType" use="required"/>
                                                </xs:complexType>
                                            </xs:element>
                                        </xs:choice>
                                    </xs:sequence>
                                </xs:complexType>
                            </xs:element>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
                <xs:element name="sdefinition" minOccurs="0">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="s" minOccurs="0" maxOccurs="unbounded">
                                <xs:complexType>
                                    <xs:sequence minOccurs="0" maxOccurs="unbounded">
                                        <xs:choice>
                                            <xs:element name="canframe" minOccurs="0" maxOccurs="unbounded">
                                                <xs:complexType>
                                                    <xs:attribute name="bus_ref" use="required"/>
                                                </xs:complexType>
                                            </xs:element>
                                        </xs:choice>
                                    </xs:sequence>
                                </xs:complexType>
                            </xs:element>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
        <xs:key name="busKey">
            <xs:selector xpath="busdefinition/bus"/>
            <xs:field xpath="@name"/>
        </xs:key>
        <xs:keyref name="busRef" refer="busKey">
            <xs:selector xpath="cdefinition/c/canbus |sdefinition/s/canframe"/>
            <xs:field xpath="@bus_ref"/>
        </xs:keyref>
    </xs:element>
    <xs:simpleType name="NameType">
        <xs:restriction base="xs:string">
            <xs:pattern value="[\w_]+"/>
        </xs:restriction>
    </xs:simpleType>
</xs:schema>

Solution

  • Interesting question. The problem goes away if you set the type of bus_ref and canbus to xs:string without a custom restriction (see this question):

    <xs:attribute name="bus_ref" type="xs:string" use="required"/>
    <!--...-->
    <xs:attribute name="bus_ref" use="required" type="xs:string"/>
    

    I think (wild conjecture) that this is a specific shortcoming of tools that use libxml and that Xerces and Saxon are behaving correctly.