Simple vs. complex content

From W3C Wiki

Simple vs. complex content (a co-constraint use case)

source: Kieran Dolan[1]


Other use cases: Co-constraint Use Cases

Description

   Is there any way in XML schema to specify that an element contains either
   simple content or complex content but not both? For example:
   `<X>23</X>` is valid and `<X><Y>45</Y></X>` is also valid but  not
   `<X>23<Y>45</Y></X>`
   Use of a `mixed` content model permits the first two
   cases but does not exclude the last one. 

Analysis

HT

slightly off-topic

FV

This is an UNCONDITIONED CHOICE OF TYPE on an ELEMENT

CoConstraintDimensionSource:
CoConstraintDimensionDestination:
CoConstraintDimensionType:
CoConstraintDimensionEffect:
CoConstraintDimensionAxis:

Possible solutions

Relax NG

Schematron

Check clause

A partial solution to this use case is to declare the type with mixed content (as suggested by the original poster) and then add this constraint:

  <xsd:annotation><xsd:appinfo><sch:pattern><sch:rule>
      <sch:assert test="count(./Y) = 0 or count(./text()[normalize-space(.) != '']) = 0">
       Content must either be character data (only) or child elements 
      and whitespace (only).
      </sch:report>
     </sch:rule></sch:pattern></xsd:appinfo></xsd:annotation>

(assuming that the only possible child is the Y element seen in the example).

The solution is only partial, since when Y is not present, the content is not really simple, but mixed. So in particular, '42' will be a sequence of characters, not the lexical representation of an integer or decimal or ...

(Solution provided by MSM)

SchemaPath

One of the possible solutions is:



<xsd:element name="X">
   <xsd:alt cond="./Y">
      <xsd:complexType>
         <xsd:sequence>
            <xsd:element name="Y" type="xsd:string"/>
         </xsd:sequence>
      </xsd:complexType>
   </xsd:alt>
   <xsd:alt type="xsd:string"/>
</xsd:element>


Conditional Type


<xsd:element name="X">
   <xsd:complexType>
      <xsd:alt cond="./Y">
         <xsd:sequence>
            <xsd:element name="Y" type="xsd:string"/>
         </xsd:sequence>
      </xsd:alt>
      <xsd:alt>
         <xsd:simpleContent>
            <xsd:extension base="xsd:string">
         </xsd:simpleContent>
      </xsd:alt>
   </xsd:complexType>
</xsd:element>