Alex Rivera | Logout

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

Asked 2009-04-23T08:42:19.907
17

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

Edit
Report

1 Answer

22

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>
answered 2009-04-23T13:38:00.850

Your Answer