I'm trying to create a schema for a <property>
element which must have a <key>
sub-element, and one of <val>
, <shell>
or <perl>
and an optional <os>
or <condition>
, and the order of the sub-elements doesn't matter.
Here are some sample for valid <property>
elements:
<property>
<key>A</key>
<val>b</val>
</property>
<property>
<key>A</key>
<val>b</val>
<os>Windows</os>
</property>
<property>
<condition>a == 1</condition>
<key>A</key>
<perl>1+1</perl>
<os>unix</os>
</property>
Ideally, I thought of using <xs:all>
for this:
<xs:element name="property">
<xs:complexType>
<xs:all>
<xs:element name="key" type="xs:string" />
<xs:choice>
<xs:element name="val" type="xs:string" />
<xs:element name="perl" type="xs:string" />
<xs:element name="shell" type="xs:string" />
</xs:choice>
<xs:element name="os" type="xs:string" minOccurs="0" />
<xs:element name="condition" type="xs:string" minOccurs="0" />
</xs:all>
</xs:complexType>
</xs:element>
But I found out that <xs:all>
can contain only <xs:element>
and not <xs:choice>
. Can someone explain why is it?
More importantly, can someone provide a way to validate such a <property>
element?
I can put the three elements - <val>
, <perl>
and <shell>
- as optional elements in the <xs:all>
, but I want the schema to validate that one and only one of the three exists in the element. Can this be done?
Among the many constraints, note in particular that xs:ID s cannot have : characters anywhere in the name and cannot have a digit as the first character of the name.
1.1 The Schema Namespace ( xs ) The XML representation of schema components uses a vocabulary identified by the namespace name http://www.w3.org/2001/XMLSchema . For brevity, the text and examples in this specification use the prefix xs: to stand for this namespace; in practice, any prefix can be used.
The elementFormDefault Attribute It is normally easier to set it to qualified. This is considerably different from the previous XML document. These general rules now apply: Only root elements defined within a schema need qualifying with a namespace.
The purpose of an XML Schema is to define the legal building blocks of an XML document: the elements and attributes that can appear in a document. the number of (and order of) child elements. data types for elements and attributes.
I think this is a bit better, as the "choice" is now it's own element (typeFacet), but cannot be used directly as it is abstract.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="property">
<xs:complexType>
<xs:all>
<xs:element name="key" type="xs:string" />
<xs:element ref="typeFacet" />
<xs:element name="os" type="xs:string" minOccurs="0" />
<xs:element name="condition" type="xs:string" minOccurs="0" />
</xs:all>
</xs:complexType>
</xs:element>
<xs:element name="typeFacet" abstract="true" />
<xs:element name="val" type="xs:string" substitutionGroup="typeFacet" />
<xs:element name="perl" type="xs:string" substitutionGroup="typeFacet" />
<xs:element name="shell" type="xs:string" substitutionGroup="typeFacet" />
</xs:schema>
Based on newt's comment about using substitution groups for the choice (tested with xmllint):
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="property">
<xs:complexType>
<xs:all>
<xs:element name="key" type="xs:string" />
<xs:element ref="val"/>
<xs:element name="os" type="xs:string" minOccurs="0" />
<xs:element name="condition" type="xs:string" minOccurs="0" />
</xs:all>
</xs:complexType>
</xs:element>
<xs:element name="val" type="xs:string"/>
<xs:element name="perl" type="xs:string" substitutionGroup="val" />
<xs:element name="shell" type="xs:string" substitutionGroup="val" />
</xs:schema>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With