简体   繁体   中英

Build XML schema that requires element or attribute, but not both

I would like to create an XML schema with the following constraints:

  • The root element shall be list .
  • list contains a set of node elements.
  • a node element can have a value attribute.
  • a node element can contain a value element.
  • a node element can have only (and exactly ) one value attribute or value element.

Here is an example of a valid XML that verify above constraints:

<?xml version="1.0" ?>
<list>
    <node id="1" value="A" />
    <node id="2">
        <value>B</value>
    </node>
</list>

I tried the following XSD Schema:

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="list">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="node" maxOccurs="unbounded" minOccurs="0">
          <xs:complexType mixed="true">
            <xs:sequence>
              <xs:element type="xs:string" name="value" minOccurs="0"/>
            </xs:sequence>
            <xs:attribute type="xs:byte" name="id" use="optional"/>
            <xs:attribute type="xs:string" name="value" use="optional"/>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

This XSD schema verify my first and the second constraint, but not the third one.

The following XML example is not valid according to my constraints, however, it is valid against my previous XSD schema.

<?xml version="1.0" ?>
<list>
    <node id="2" value="A" /> <!-- valid -->
    <node id="4">
        <value>D</value>
    </node><!-- valid -->
    <node id="1" /><!-- not valid, missing value -->
    <node id="3" value="B">
        <value>C</value>
    </node><!-- not valid, both attribute and element are declared -->
</list>

How can I change my schema to verify all my constraints?

Thanks in advance.

This is not possible using XSD 1.0.

It should be possible with XSD 1.1 using assertions:

<xs:assert test="not(@value and value)"/>

that fails if @value and value are both present. To check that there is exactly one attribute or sub-element use:

<xs:assert test="count((value, @value))=1"/>

as suggested by Michael Kay in the comments.

It might be possible using some other XML validation technology like Schematron.

You can create first type with required attribute and second type with required element. Then use choice compositor containing both types.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM