When testing a patch for Gerbera I wanted to validate my configuration file, saw that the config2.xsd file was broken and decided to fix it.
The Gerbera configuration XML has two <container> tags with different meanings, attributes and children. The XML schema definition had two top-level <element name="container"> entries which was criticised by xmllint:
$ xmllint --noout --schema test.xsd data.xml test.xsd:17: element element: Schemas parser error : Element '{http://www.w3.org/2001/XMLSchema}element': A global element declaration '{http://example.org/cw}container' does already exist. WXS schema test.xsd failed to compile
This happened because the Gerbera config XSD does not use nested declarations but a long list of top-level elements, just like we know it from DTDs.
A solution to the problem is not to declare the second "container" tag but to only define its type, and reference that:
<?xml version="1.0"?> <container xmlns="http://example.org/cw"> <resources> <order direction="asc"/> <container name="foo"/> </resources> </container>
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://example.org/cw" targetNamespace="http://example.org/cw"> <xs:element name="container"> <xs:complexType> <xs:sequence> <xs:element ref="resources" minOccurs="1"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="resources"> <xs:complexType> <xs:sequence> <xs:element ref="order" minOccurs="1"/> <xs:element name="container" type="resContainer" minOccurs="1"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="order"> <xs:complexType> <xs:attribute name="direction" type="xs:string"/> </xs:complexType> </xs:element> <xs:complexType name="resContainer"> <xs:attribute name="name"/> </xs:complexType> </xs:schema>
Now xmllint gave a strange error:
$ xmllint --noout --schema test.xsd data.xml data.xml:4: element container: Schemas validity error : Element '{http://example.org/cw}container': This element is not expected. Expected is ( container ). data.xml fails to validate
It gets a namespaced <container> tag but wants a non-namespaced container! This problem does not happen with the <order> tag which is loaded into the <resources> tag with a ref="" - it only happens when the nested xsd:element uses a name="" attribute.
I did not find any solutions when searching for "xsd" "This element is not expected. Expected is one of" element "ref" "name" in DuckDuckGo and Google and already started to write a question on StackOverflow when its "Similar Questions" list showed Sub-elements and namespaces in XSD. One tiny but important comment told the solution:
Add elementFormDefault="qualified" to your schema element (<xsd:schema ...>) and you should be good to go.
mechanical_meat, Jun 22, 2009 at 21:22
And indeed this was it:
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://example.org/cw" targetNamespace="http://example.org/cw" elementFormDefault="qualified"> ...
$ xmllint --noout --schema test.xsd data.xml data.xml validates
elementFormDefault?
The elementFormDefault attribute is documented in XSD primer: 3.2 Qualified Locals and "documented" in XSD Structures: 3.15.2 XML Representations of Schemas, but I would never have guessed that this is related to my problem. Which proves what is written in the criticism section of the XML Schema wikipedia page:
It is too complicated (the spec is several hundred pages in a very technical language), so it is hard to use by non-experts — but many non-experts need schemas to describe data formats. The W3C Recommendation itself is extremely difficult to read.