开发者

Defining XSD to validate groups of permitted XML attributes for the same element

I would like to define an XSD that would validate the following XML.

<parameters>
    <param name="Maximum Error Threshold" type="integer">10</param>
    <param name="Auto Shutdown Timeout Duration" type="integer" unit="seconds">300</param>
    <param name="Flow Rate Adjusment" type="integer" unit="litrePerSec">0.5</param>
    <param name="Configuration Download Time" type="timeofday" format="timestring">03:20</param>
    <param name="Maximum Issue Value" type="integer" unit="cents" format="numericfloat">145.50</param> 
</parameters>

I currently have a schema which looks something like:

  <xs:element name="parameters">
    <xs:complexType>
      <xs:sequence>
        <xs:element maxOccurs="5" minOccurs="5" ref="param"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="param">
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="xs:NMTOKEN">
          <xs:attribute name="name" use="required" type="AttributeNames"/>
          <xs:attribute name="type" use="required" type="AttributeTypes"/>
          <xs:attribute name="format" use="optional" type="AttributeFormats"/>
          <xs:attribute name="unit" use="optional" type="AttributeUnits"/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
  <xs:simpleType name="AttributeNames">
    <xs:restriction base="xs:token">
      <xs:enumeration value="Maximum Error Threshold"/>
      <xs:enumeration value="Auto Shutdown Timeout Duration"/>
      <xs:enumeration value="Flow Rate Adjusment"/>
      <xs:enumeration value="Configuration Download Time"/>
      <xs:enumeration value="Maximum Issue Value"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="AttributeTypes">
    <xs:restriction base="xs:NCName">
      <xs:enumeration value="integer"/>
      <xs:enumeration value="timeofday"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="AttributeFormats">
    <xs:restriction base="xs:NCName">
      <xs:enumeration value="timestring"/>
      <xs:enumeration value="numericfloat"/>
    </xs:restriction>
  </xs:simpl开发者_JAVA百科eType>

  <xs:simpleType name="AttributeUnits">
    <xs:restriction base="xs:NCName">
      <xs:enumeration value="seconds"/>
      <xs:enumeration value="litrePerSec"/>
      <xs:enumeration value="cents"/>
    </xs:restriction>
  </xs:simpleType>

This works. But it does not give me complete validation. I would like to ensure that the appropriate attributes are present in the 'param' element (and that these attributes contain the appropriate values), depending on what the 'name' attribute contains.

For example;

If the 'name' attribute = "Auto Shutdown Timeout Duration", then the 'type' is required and can only be "integer" and the 'unit' is required and can be "hours", "minutes" or "seconds".

But if 'name' attribute = "Maximum Error Threshold", then the 'type' is required and can only be "integer" but 'unit' is not permitted.

So I decided to describe each parameter separately; i.e. something like:

  <xs:complexType name="MaxErrorParam">
    <xs:simpleContent>
      <xs:extension base="xs:NMTOKEN">
        <xs:attribute name="name" fixed="Maximum Error Threshold"/>
        <xs:attributeGroup ref="CounterParameterAttributes"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>

  <xs:complexType name="AutoShutdownParam">
    <xs:simpleContent>
      <xs:extension base="xs:NMTOKEN">
        <xs:attribute name="name" fixed="Auto Shutdown Timeout Duration"/>
        <xs:attributeGroup ref="TimeOutParameterAttributes"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>

  <xs:attributeGroup name="CounterParameterAttributes">
    <xs:attribute name="type" use="required" fixed="integer"/>
  </xs:attributeGroup>

  <xs:attributeGroup name="TimeOutParameterAttributes">
    <xs:attribute name="type" use="required" fixed="integer"/>
    <xs:attribute name="format" use="required" type="TimeUnitsType"/>
  </xs:attributeGroup>

  <xs:simpleType name="TimeUnitsType">
    <xs:restriction base="xs:NCName">
      <xs:enumeration value="minutes"/>
      <xs:enumeration value="seconds"/>
      <xs:enumeration value="hours"/>
    </xs:restriction>
  </xs:simpleType>

But this meant that i needed to define the 'param' element as follows; this causes an error because the element 'param' is defined twice with different type.

  <xs:element name="parameters">
    <xs:complexType>
      <xs:all>
        <xs:element name="param" type="MaxErrorParam"/>
        <xs:element name="param" type="AutoShutdownParam"/>
        etc...
      </xs:>
    </xs:complexType>
  </xs:element>

Can anyone please suggest a solution or point me in the right direction?


Nobody has answered this, I hope it's still interesting to you. The approaches you outlined do not work: XML Schema cannot validate constraints of the form "if element X contains something then check Y". Also, you cannot have two elements with the same name but different types in the same container, as you said.

However, you what you can do is to 1) create a child element in param with a name of value and a type of xs:anySimpleType and 2) use the native XML Schema type override mechanism (xsi:type):

<parameters xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <param name="Maximum Error Threshold">
        <value xsi:type="xs:int">10</value>
    </param>
</parameters>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜