xsd: force attribute in element iff child-element is present

176 Views Asked by At

suppose I have two elements, where the first (register) may contain several of the second (scale). The @unit attribute of the scale element is a xs:key (hence unique inside the first element). It can be named as a xs:keyref in a "defaultScale" attribute of the register element. Like this:

<xs:element name="register">
  <xs:key name="scaleKey">
    <xs:selector xpath="scale" />
    <xs:field xpath="@unit" />
  </xs:key>
  <xs:keyref name="chooseDefaultScale" refer="scaleKey">
    <xs:selector xpath="."/>
    <xs:field xpath="@defaultScale"/>
  </xs:keyref>
  <xs:complexType>
    <xs:sequence>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="scale"/>
      </xs:choice>
    <xs:attribute name="defaultScale" type="xs:string" />
  </xs:complexType>
</xs:element>

<xs:element name="scale">
  <xs:complexType>
    <xs:attribute name="scale" type="xs:float" use="required"/>
    <xs:attribute name="unit" type="xs:string" use="required"/>
  </xs:complexType>
</xs:element>

How can I force the @defaultScale attribute to be present and valid iff at least one scale child is present?

My first try was to add another xs:key into the base-element of register, like in try1 and try2. Both don't compile...

<xs:element name="body">
  <xs:key name="try1">
    <xs:selector xpath=".//register/defaultScale" />
    <xs:field xpath="../@defaultScale" />             <!-- not allowed -->
  </xs:key>
  <xs:key name="try2">
    <xs:selector xpath=".//register[defaultScale]" /> <!-- not allowed -->
    <xs:field xpath="@defaultScale" /> 
  </xs:key>
  <xs:sequence>
    <xs:element ref="register"/>
  <xs:sequence>
</xs:element>

I am only allowed to use the child-axis in the xs:selector and xs:field elements. So my best guess in the moment: It's not possible?

1

There are 1 best solutions below

0
user3520187 On

To answer my own question: not possible out-of-the-box, have to use XSD 1.1. See here for example.

Note that this is not trivial from a debian shell using foss software...