Volodymyr
Volodymyr

Reputation: 1

How to define 2 elements with different values in their attributes?

Is it possible to define an xsd scheme which could validate such xml:

<test>
  <name Type="1" SomeAttr="value" >
    <info a="1" b="2"/>
  </name>
  <name Type="3" SomeAttr="value" />
</test>

In this xml can be 1 or 2 elements "name".

In first element "name" in attribute "Type" can be only 2 values - 1 or 2

In second element "name" in attribute "Type" can be only 1 value - 3

In xml can be only 1 child element "info" and it must treated to parent element "name" with attributes value 1 or 2 (not to "name" with Type="3")

Please help. Thank you.

Upvotes: 0

Views: 394

Answers (2)

David L.
David L.

Reputation: 3290

In Xml Schema 1.1 it is possible using the xs:alternative that allows an element to have different types based on provided condition.

<xs:element name="name">
    <xs:alternative test="@Type=1" type="name_type_1"/>
    <xs:alternative test="@Type=3" type="name_type_3"/>
</xs:element>

The full schema for the XML in the question could look like:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
        elementFormDefault="qualified"
        attributeFormDefault="unqualified"
        vc:minVersion="1.1">
    <xs:element name="test">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="name" minOccurs="0" maxOccurs="unbounded">
                    <xs:alternative test="@Type=1" type="name_type_1"/>
                    <xs:alternative test="@Type=3" type="name_type_3"/>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:complexType name="name_type_1">
        <xs:sequence>
            <xs:element name="info">
                <xs:complexType>
                    <xs:attribute name="a"/>
                    <xs:attribute name="b"/>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
        <xs:attribute name="Type" type="xs:integer"/>
        <xs:attribute name="SomeAttr"/>
    </xs:complexType>
    <xs:complexType name="name_type_3">
        <xs:attribute name="Type" type="xs:integer"/>
        <xs:attribute name="SomeAttr"/>
    </xs:complexType>
</xs:schema>

Upvotes: 0

C. M. Sperberg-McQueen
C. M. Sperberg-McQueen

Reputation: 25054

In XSD, any two elements of the same name appearing as children of the same parent must have the same type. (I am omitting some complications here; readers who need full information will have to consult the spec.) It is a consequence of this that in a typical document validation the type associated with an element is fully determined by the path from the root of the validation episode to the element itself, and does not depend upon its position among the children of its parent.

So: no, you cannot give two sibling elements the same name and different types.

If the two elements occur in different contexts, they can have different types. So XML like the following would work:

<test>
  <context-1>
    <name Type="1" SomeAttr="value" >
      <info a="1" b="2"/>
    </name>
  </context-1>
  <context-2>
    <name Type="3" SomeAttr="value" />
  </context-2>
</test>

But the simplest way to have your two 'name' elements have different types is to give them different names, reflecting the difference in their natures.

<test>
  <red-name Type="1" SomeAttr="value" >
    <info a="1" b="2"/>
  </red-name>
  <green-name Type="3" SomeAttr="value" />
</test>

If you want the schema to reflect, somehow, that the two forms of name are somehow different forms of the same thing, XSD provides two obvious mechanisms:

  • You can define a name type, from which the red and green flavors of the type are derived. The relation between the two types is thus reflected in the type hierarchy.

  • You can define an abstract (or a concrete!) name element and declare the two specific variants (here called red-name and green-name) as being substitutable for it. The relation between the red and green name elements is thus reflected in the substitution-group relations.

Upvotes: 1

Related Questions