简体   繁体   中英

Attribute/element co-occurrence constraint in XML Schema

Is it possible to create an XML Schema which imposes a co-occurrence constraint to an attribute/element pair?

<primitive-list>
    <primitive name="P1">
        <definition><!-- primitive specification --></definition>
    </primitive>
    <primitive name="P2">
        <definition><!-- primitive specification --></definition>
    </primitive>

    <!-- other common primitives are specified here-->

<primitive-list>

<composite-list>
    <composite name="C1">
        <primitive ref="P1" />
        <primitive ref="P2" />
        <primitive>
            <definition><!-- inline primitive specification --></definition>
        </primitive>        
    </composite>

    <!-- Other compisites are specified here-->

</composite-list>

The schema should imply that:

  • If a element is specified inside a element, then it should contain the attribute and the embedded element, but not the attribute. 元素中指定了元素,那么它应该包含属性和嵌入式元素,但不是属性。
  • If a element is specified in the element, then it should contain either the attribute or the element. 元素中指定了元素,那么它应该包含属性或元素。 The is allowed in neither cases.

I am pretty sure that it is possible since the element in XML Schema itself behaves just like that. 元素本身就像那样。 So anybody who is in possession of that sacred knowledge please share :-)

Thank you in advance.

After searching on the Internet and digging in some books I figured out how to implement that.

First of all we need to define a generic type which accommodates all attributes and elements from both kinds of the element. 元素的所有属性和元素。 It is assumed that the element is defined somewhere else. 元素在其他地方定义。

<xs:complexType name="primitive" abstract="true">
    <xs:sequence>
        <xs:element ref="definition" minOccurs="0" maxOccurs="unbounded" />
    </xs:sequence>
    <xs:attribute name="name" type="xs:Name" />
    <xs:attribute name="ref" type="xs:Name" />
</xs:complexType>

Then we define two subtypes to be used in the and respectively. 子类型分别用于

<xs:complexType name="public-primitive">
    <xs:complexContent>
        <xs:restriction base="primitive">
            <xs:sequence>
                <xs:element ref="definition" minOccurs="1" maxOccurs="unbounded" />
            </xs:sequence>
            <xs:attribute name="name" type="xs:Name" use="required" />
            <xs:attribute name="ref" use="prohibited" />
        </xs:restriction>
    </xs:complexContent>
</xs:complexType>

<xs:complexType name="private-primitive">
    <xs:complexContent>
        <xs:restriction base="primitive">
            <xs:sequence>
                <xs:element ref="definition" minOccurs="0" maxOccurs="unbounded" />
            </xs:sequence>
            <xs:attribute name="name" use="prohibited" />
        </xs:restriction>
    </xs:complexContent>
</xs:complexType>

Now we can define the and elements in terms of these complex types as follows: 元素,如下所示:

<xs:element name="primitive-list">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="primitive" type="public-primitive" maxOccurs="unbounded" />
        </xs:sequence>
    </xs:complexType>
</xs:element>

<xs:element name="composite">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="primitive" type="private-primitive" maxOccurs="unbounded">
                <xs:key name="definition-ref--co-occurrence--constraint">
                    <xs:selector xpath="." />
                    <xs:field xpath="definition|@ref" />
                </xs:key>
            </xs:element>
        </xs:sequence>
    </xs:complexType>
</xs:element>

Let's take a look at the original schema requirements and see how they are enforced:

  • If a element is specified inside a element, then it should contain the attribute and the embedded element, but not the attribute. 元素中指定了元素,那么它应该包含属性和嵌入式元素,但不是属性。

This requirement is enforced by the definition of the type alone. 类型的定义来强制执行此要求。

  • If a element is specified in the element, then it should contain either the attribute or the element. 元素中指定了元素,那么它应该包含属性或元素。 The is allowed in neither cases.

This requirement is enforced by the definition of the type and by the element specified in the element defined inside of the element. 类型的定义和在元素内定义的元元素中指定的元素强制执行。 The guaranties that either or is present but not both. 保证存在但不同时存在。

Yes, this is possible. When creating your XML Schema, you will be creating a complex type for each scenario, based on where in the XML tree the element is defined.

If I get a moment later on i can try to actually get an example out here for you, I just don't have the time to get it all formatted perfectly for posting here.

I personally highly recommend looking at this w3schools tutorial , as it should get you what you need.

Ok, here is a sample, this gets you close, the only thing not handled is the primitive and ref attribute on the composite. Looking at what I can find, it does almost seem to be impossible to do this via a schema. I'm not 100% sure though, but in all cases where I have seen this done, a schema like this is used for high level validation and process code is then used to validate the individual items.

<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://www.iowacomputergurus.com/stackoverflow/samples/xsdexample"
    elementFormDefault="qualified"
    xmlns="http://www.iowacomputergurus.com/stackoverflow/samples/xsdexample"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
>

  <xs:complexType name="PrimitiveType">
    <xs:sequence>
      <xs:element name="definition" type="xs:string" minOccurs="1" maxOccurs="1" />
    </xs:sequence>
    <xs:attribute name ="name" use="required" type="xs:string" />
  </xs:complexType>

  <xs:element name="root">
    <xs:complexType>
      <xs:sequence>
          <xs:element name="primitive-list" minOccurs="1" maxOccurs="1">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="primitive" type="PrimitiveType" minOccurs="1" maxOccurs="unbounded" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
          <xs:element name="composite-list" minOccurs="1" maxOccurs="1">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="composite">
                  <xs:complexType>
                    <xs:sequence>
                      <xs:element name="primitive" minOccurs="1" maxOccurs="unbounded">
                        <xs:complexType>
                          <xs:sequence>
                            <xs:element name="definition" minOccurs="0" maxOccurs="1" />
                          </xs:sequence>
                          <xs:attribute name="ref" use="optional" type="xs:string" />
                        </xs:complexType>
                      </xs:element>
                    </xs:sequence>
                    <xs:attribute name="name" type="xs:string" use="required" />
                  </xs:complexType>
                </xs:element>
              </xs:sequence>
            </xs:complexType>
          </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>  
</xs:schema>

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