Needs choice inside all

From W3C Wiki

Needs choice inside all (a co-constraint use case)

source: Kevin Burges [1]


Other use cases: Co-constraint Use Cases

Description

   What I would like is:


                      __ name (minOccurs=0)
                     /
                    /                         __ field (minOccurs=1)
    column --[ALL]-----[CHOICE minOccurs=1]--|__ formula (minOccurs=1)
                    \
                     \__ width (minOccurs=0)
    


   But it appears I cannot have a `choice` section inside the `all`.

Analysis

FV

This is is an UNCONDITIONED RELAXATION on an <all> structure in an ELEMENT

CoConstraintDimensionSource:
CoConstraintDimensionDestination:
CoConstraintDimensionType:
CoConstraintDimensionEffect:
CoConstraintDimensionAxis:

MSM

While it's clear that the original poster's idea could be expressed in an SGML all group, it's not clear to me that the sample solutions below for SchemaPath and conditional types are correct in saying that this could be handled by the recently agreed extensions to all: we agreed to allow maxOccurs to exceed 1, and to specify interleave semantics. Did we agree to allow choices inside all-groups?

Of course, an unextended all-group could handle the substantive requirement today, either using a wrapper element:

 <xsd:complexType name="column">
  <xsd:all>
   <xsd:element ref="name"    minOccurs="0"/>
   <xsd:element ref="payload" minOccurs="1"/>
   <xsd:element ref="width"   minOccurs="0"/>
  </xsd:all>
 </xsd:complexType>

 <xsd:element name="payload">
  <xsd:complexType>
   <xsd:choice>
    <xsd:element ref="field"/>
    <xsd:element ref="formula"/>
   </xsd:choice>
  </xsd:complexType>
 </xsd:element>


or using a substitution group:

 <xsd:complexType name="column">
  <xsd:all>
   <xsd:element ref="name"    minOccurs="0"/>
   <xsd:element ref="payload" minOccurs="1"/>
   <xsd:element ref="width"   minOccurs="0"/>
  </xsd:all>
 </xsd:complexType>
 <xsd:element name="payload" abstract="true"/>
 <xsd:element name="field" substitutionGroup="payload"> ... </xsd:element>
 <xsd:element name="formula" substitutionGroup="payload"> ... </xsd:element>


Possible solutions

Relax NG

Schematron

Check clause

A check-clause solution might be:

 <xsd:complexType name="choice_inside_all">
  <xsd:annotation><xsd:appinfo><sch:pattern><sch:rule>
      <sch:assert test="count(my:name) < 2
       and count(my:width) < 2
       and count(my:field or my:formula) = 1">
       One of field or formula must occur, not more, not fewer.
      </sch:report>
     </sch:rule></sch:pattern></xsd:appinfo></xsd:annotation>
  <xsd:choice minOccurs="0" maxOccurs="3">
   <xsd:element name="my:name"/>
   <xsd:element name="my:field"/>
   <xsd:element name="my:formula"/>
   <xsd:element name="my:width"/>
  </xsd:choice>
 </xsd:complexType>

This illustrates one danger of a powerful predicate language in check clauses: that constraints which can be expressed in a relatively simple way in the content model will instead be expressed in a less direct way in a predicate. (Of course, directness may be in the eye of the beholder. It's quite possible that the schema author might feel that the predicate approach allowed a simpler, clearer, and more direct expression of what was really desired.)

SchemaPath

This appears to be solvable with current extension of <all>. But, if you want to have it using co-constraints, one of the possible solutions is:



<xsd:element name="column">
  <xsd:alt cond="./field and ./formula"           type="xsd:error"/>
  <xsd:alt cond="not(./field) and not(./formula)" type="xsd:error"/>
  <xsd:alt>
     <xsd:complexType>
        <xsd:all>
           <xsd:element ref="name"    minOccurs="0"/>
           <xsd:element ref="field"   minOccurs="0"/>
           <xsd:element ref="formula" minOccurs="0"/>
           <xsd:element ref="width"   minOccurs="0"/>
        </xsd:all>
     </xsd:complexType>
  </xsd:alt>
</xsd:element>


Conditional Type

This appears to be solvable with current extension of <all>. But, if you want to have it using co-constraints, one of the possible solutions is:



<xsd:element name="column" type="tColumn"/>

<xsd:complexType name="tColumn">
  <xsd:alt cond="./field or ./formula and not(./field and ./formula)">
     <xsd:all>
        <xsd:element ref="name"    minOccurs="0"/>
        <xsd:element ref="field"   minOccurs="0"/>
        <xsd:element ref="formula" minOccurs="0"/>
        <xsd:element ref="width"   minOccurs="0"/>
     </xsd:all>
  </xsd:alt>
</xsd:complexType>