8

是否可以创建一个对属性/元素对施加共现约束的 XML 模式?

<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>

架构应该暗示:

  • 如果在原始列表元素中指定了原始元素,则它应该包含name属性和嵌入的定义元素,但不包含ref属性。
  • 如果在复合元素中指定了原始元素,则它应该包含ref属性或定义元素。在这两种情况下都不允许使用该名称。

我很确定这是可能的,因为 XML Schema 中的元素元素本身的行为就是这样。所以任何拥有这种神圣知识的人请分享:-)

先感谢您。

4

3 回答 3

10

在互联网上搜索并挖掘了一些书籍后,我想出了如何实现它。

首先,我们需要定义一个泛型类型,它可以容纳来自两种原始元素的所有属性和元素。假设定义元素是在其他地方定义的。

<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>

然后我们定义两个原始子类型分别用于原始列表复合

<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>

现在我们可以根据这些复杂类型定义原始列表复合元素,如下所示:

<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>

让我们看一下原始模式要求,看看它们是如何执行的:

  • 如果在原始列表元素中指定了原始元素,则它应该包含name属性和嵌入的定义元素,但不包含ref属性。

此要求仅由public-primitive类型的定义强制执行。

  • 如果在复合元素中指定了原始元素,则它应该包含ref属性或定义元素。在这两种情况下都不允许使用该名称。

此要求由私有原始类型的定义和在复合元素内部定义的原始元素中指定的xs:key元素强制执行。xs:key保证ref定义都存在,但不能同时存在。

于 2008-12-03T08:22:32.207 回答
0

是的,这是可能的。创建 XML Schema 时,您将为每个场景创建一个复杂类型,具体取决于元素在 XML 树中的定义位置。

如果稍后我有时间,我可以尝试在这里为您实际提供一个示例,我只是没有时间将其全部格式化以在此处发布。

我个人强烈建议您查看这个w3schools 教程,因为它应该可以满足您的需求。

于 2008-11-26T13:47:21.083 回答
0

好的,这是一个示例,这可以让您接近,唯一没有处理的是复合材料上的原语和 ref 属性。看看我能找到什么,通过模式来做到这一点似乎几乎是不可能的。虽然我不是 100% 确定,但在我看到的所有情况下,这样的模式都用于高级验证,然后使用流程代码来验证各个项目。

<?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>
于 2008-11-27T07:54:49.190 回答