In an XSD schema, you cannot declare an element as the only valid root node for your document.
It's a PITA, but I'm aware about it.
For ages I would simply do what is suggested in the linked answer -- only define <simpleType>s and <complexType>s, with the only <element> defined at the global level being my desired root node.
However, I'm currently up to a nice refactoring of my XSD/XSLT code base. One of the things I want to do is to restrict a certain element to only elements derived from a desired type, provided these derivatives can have different node names:
<xs:complexType name="parentType">
<xs:sequence>
<xs:element ref="AChild" minOccurs="1" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
where AChild is an abstract base type from which other types will derive using substitutionGroup:
<xs:complexType name="child_base" abstract="true">
...
</xs:complexType>
<xs:element name="AChild" type="child_base" abstract="true" />
<xs:element name="AConcreteChild" substitutionGroup="AChild" >
<xs:complexType>
<xs:complexContent>
<xs:extension base="child_base">
...
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element name="AnotherPossibleConcreteChild" substitutionGroup="AChild" >
<xs:complexType>
<xs:complexContent>
<xs:extension base="child_base">
...
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
The problem here is that the substitutionGroup thing only works for elements declared at the global level. So now I have a bunch of previously internal types declared as global level elements, and while that perfectly restricts the possible children for parentType, it also means the validation will succeed if any of the now-global children is provided as a root element, which I don't want.
Options I have considered included:
- Ditch the
substitutionGroupinheritance, move all the possible children to a separate namespace, and use<xsd:any namespace="that namespace" />. Feels sort of okay, but I don't like the additional namespace and the worse-defined constraint. - Ignore the problem at the XSD level and check the root node name and namespace in the code that uses the XSD template. What I did not like here was breaking the separation of concerns, as in my design the XSD file was a black box for the calling code, and I would rather not introduce a hardcoded dependency on a node QName.
Introduce a principle according to which there are always going to be two "main" XSD schemas. One will validate the nodes in the usual way (the validation I currently have), another one will only contain a definition of the top-level node in the most laxed form:
<xs:complexType name="parentType"> <xs:sequence> <xs:any namespace="##any" processContents="skip" /> </xs:sequence> <xs:anyAttribute namespace="##any" processContents="skip" /> </xs:complexType> <xs:element name="TheRootNode" type="parentType" />And then my document will be correct if and only if both schemas validate.
What I don't like here is that I'm not sure how deeply that violates best practices.Quit refactoring and keep what I had before (and before I had all possible children manually listed in an
<xs:choice>).
My question is, is there any other way to make the any-derived-element constraint work without declaring multiple global-level <element>s (so that the only-root-node constraint works again)? Also please leave an answer if you believe I better choose one of the listed options.