Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XML Schema: Why can't <xs:all> have <choice> children? and how can this be bypassed?

Tags:

xml

xsd

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?

like image 362
splintor Avatar asked Apr 23 '09 08:04

splintor


People also ask

What is the limitation of using XS ID in XML Schema?

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.

What is Xs in XML Schema?

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.

Which attribute for the root element xs schema is necessary if you want to place the elements in a namespace?

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.

What is the purpose of schema select one to avoid duplication in XML?

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.


2 Answers

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>
like image 158
Adam Hawkes Avatar answered Nov 15 '22 18:11

Adam Hawkes


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>
like image 43
13ren Avatar answered Nov 15 '22 18:11

13ren