Search code examples
xmlxsdxsd-validationxml-validation

XML Validation for config file


I am trying to get an XML Schema for a config file type XML working.

Here's what I have got:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="https://www.w3schools.com" 
    xmlns="https://www.w3schools.com" elementFormDefault="qualified">

    <xs:element name="config" type="config">
        <xs:complexType mixed="true">
            <xs:sequence>
                <xs:element name="module" maxOccurs="unbounded">
                    <xs:complexType mixed="true">
                        <xs:sequence>
                            <xs:element name="parameter" maxOccurs="unbounded">
                                <xs:complexType mixed="true">
                                    <xs:attribute name="name" type="xs:string" use="required"/>
                                    <xs:attribute name="description" type="xs:string" />
                                    <xs:attribute name="type" type="xs:string" use="required"/>
                                    <xs:attribute name="value" type="xs:string" use="required"/>
                                </xs:complexType>
                            </xs:element>
                        </xs:sequence>
                        <xs:attribute name="name" type="xs:string" use="required" />
                        <xs:attribute name="description" type="xs:string" />
                        <xs:attribute name="version" type="xs:string" />
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

Example file that should be legal:

<config>
    <module name="module1">
        <parameter name="param1" value="1.234" type="float"/>
    </module>
    <module name="module2">
        <parameter name="param1" value="Hello there!" type="string"/>
        <parameter name="param2" value="3.1415" type="float"/>
    </module>
</config>

But I get the error Cvc-elt.1.a: Cannot Find The Declaration Of Element config. What did I do wrong here? I have found this answer and at least to me it seems I correctly adopted it for my purpose but somehow my root object config isn't defined.


Solution

  • There is an error in your XML Schema, since xs:element cannot have both a name and type attribute.

    After fixing this: because of how you defined namespaces in your XML Schema, a document that is valid would need to be in the namespace https://www.w3schools.com. The solution is to a) either fix your XML document to include this namespace (see above), or b) change your XSD to not expect a namespace.

    Fixing the XML document (no change to the XML Schema)

    This would be a valid document:

    <?xml version="1.0" encoding="UTF-8"?>
    <config xmlns="https://www.w3schools.com">
        <module name="module1">
            <parameter name="param1" value="1.234" type="float"/>
        </module>
        <module name="module2">
            <parameter name="param1" value="Hello there!" type="string"/>
            <parameter name="param2" value="3.1415" type="float"/>
        </module>
    </config>
    

    XML Schema that does not expect a namespace (no change to the XML document)

    <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="unqualified">
    
        <xs:element name="config">
            <xs:complexType mixed="true">
                <xs:sequence>
                    <xs:element name="module" maxOccurs="unbounded">
                        <xs:complexType mixed="true">
                            <xs:sequence>
                                <xs:element name="parameter" maxOccurs="unbounded">
                                    <xs:complexType mixed="true">
                                        <xs:attribute name="name" type="xs:string" use="required"/>
                                        <xs:attribute name="description" type="xs:string" />
                                        <xs:attribute name="type" type="xs:string" use="required"/>
                                        <xs:attribute name="value" type="xs:string" use="required"/>
                                    </xs:complexType>
                                </xs:element>
                            </xs:sequence>
                            <xs:attribute name="name" type="xs:string" use="required" />
                            <xs:attribute name="description" type="xs:string" />
                            <xs:attribute name="version" type="xs:string" />
                        </xs:complexType>
                    </xs:element>
                </xs:sequence>
            </xs:complexType>
        </xs:element>
    </xs:schema>
    

    Other improvements to your XML Schema

    Your schema is a bit hard to read, because of the heavy nesting. Here is an alternative version that defines named complex types. Also, your types are "mixed", whereas, looking at your XML document, I do not think they should be.

    <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="unqualified">
    
        <xs:element name="config" type="configType" />
    
        <xs:complexType name="configType">
            <xs:sequence>
                <xs:element name="module" type="moduleType" maxOccurs="unbounded" />
            </xs:sequence>
        </xs:complexType>
    
        <xs:complexType name="moduleType">
            <xs:sequence>
                <xs:element name="parameter" type="parameterType" maxOccurs="unbounded" />
            </xs:sequence>
            <xs:attribute name="name" type="xs:string" use="required" />
            <xs:attribute name="description" type="xs:string" />
            <xs:attribute name="version" type="xs:string" />
        </xs:complexType>
    
        <xs:complexType name="parameterType">
            <xs:attribute name="name" type="xs:string" use="required"/>
            <xs:attribute name="description" type="xs:string" />
            <xs:attribute name="type" type="xs:string" use="required"/>
            <xs:attribute name="value" type="xs:string" use="required"/>
        </xs:complexType>
    
    </xs:schema>
    

    Edit: introducing a different custom namespace

    XML Document

    <?xml version="1.0" encoding="UTF-8"?>
    <config xmlns="https://www.myowndomain.com">
        <module name="module1">
            <parameter name="param1" value="1.234" type="float"/>
        </module>
        <module name="module2">
            <parameter name="param1" value="Hello there!" type="string"/>
            <parameter name="param2" value="3.1415" type="float"/>
        </module>
    </config>
    

    XML Schema

    In the schema, you would remove all references to w3schools.com and replace with your own namespace URI.

    <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
        targetNamespace="https://www.myowndomain.com" xmlns="https://www.myowndomain.com">
    
        <xs:element name="config" type="configType" />
    
        <xs:complexType name="configType">
            <xs:sequence>
                <xs:element name="module" type="moduleType" maxOccurs="unbounded" />
            </xs:sequence>
        </xs:complexType>
    
        <xs:complexType name="moduleType">
            <xs:sequence>
                <xs:element name="parameter" type="parameterType" maxOccurs="unbounded" />
            </xs:sequence>
            <xs:attribute name="name" type="xs:string" use="required" />
            <xs:attribute name="description" type="xs:string" />
            <xs:attribute name="version" type="xs:string" />
        </xs:complexType>
    
        <xs:complexType name="parameterType">
            <xs:attribute name="name" type="xs:string" use="required"/>
            <xs:attribute name="description" type="xs:string" />
            <xs:attribute name="type" type="xs:string" use="required"/>
            <xs:attribute name="value" type="xs:string" use="required"/>
        </xs:complexType>
    
    </xs:schema>