如何使用key/keyrefs为相同类型的嵌套元素创建xml架构

Chu*_*uck 6 xml schema xsd keyref xsd-validation

我定期使用一些XML文件,并希望DTD可以提供更好的验证.所以我开始阅读有关模式的内容,看看是否会帮助我.到目前为止,我已经能够创造出几乎像我需要的东西,除了一件.我希望能够将元素的属性限制为具有相同元素类型的兄弟或祖先元素的不同属性的值.使用XML Schema密钥/ keyref限制是否可以实现这一点?

我有一个看起来像这样的文档:

<nodeContainer>
    <node name="Table">
    </node>

    <node name="MyHouse">
        <node name="RoomWithDoor">
        </node>
        <node name="DiningRoom" extends="RoomWithDoor">
            <node name="DiningTable" extends="Table">
            </node>
        </node>
    </node>

    <node name="MySummerHouse">
        <node name="DiningRoom">
            <node name="DiningTable" extends="Table">
            </node>
        </node>
    </node>
</nodeContainer>
Run Code Online (Sandbox Code Playgroud)

在本文档中,节点可以"扩展"以下其他节点:

  • 兄弟姐妹
  • 父母的兄弟姐妹

但是,节点不应"扩展":

  • 父母
  • 父母兄弟姐妹的子节点

这意味着MyHouse可以"扩展" ,这是没有意义的,但我没关系.

同样重要的是,两个房屋节点都应该能够拥有自己的名为DiningRoom的节点.

我目前的架构与此类似:

<xs:complexType name="node">
    <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="node"/> <!-- node can have other nodes inside it -->
        <xs:element ref="leaf"/>
    </xs:choice>
    <xs:attribute name="name"       type="xs:anySimpleType" use="required"/>
    <xs:attribute name="extends"    type="xs:anySimpleType"/>
</xs:complexType>

<!-- document root -->
<xs:element name="root">
    <xs:complexType>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
            <xs:element name="nodeContainer">
                <xs:complexType>
                    <xs:choice minOccurs="0" maxOccurs="unbounded">
                        <xs:element ref="node"/>    
                    </xs:choice>
                </xs:complexType>
            </xs:element>
            <xs:element ref="otherType"/>
        </xs:choice>
    </xs:complexType>

    <!-- create constrictions -->
    <xs:unique name="UniqueNodes">
        <xs:selector xpath="nodeContainer/node"/>
        <xs:field xpath="@name"/>
    </xs:unique>
    <xs:keyref refer="UniqueNodes" name="ValidNodeExtends">
        <xs:selector xpath=".//node"></xs:selector>
        <xs:field xpath="@extends"></xs:field>
    </xs:keyref>
</xs:element>
Run Code Online (Sandbox Code Playgroud)

这个架构是我正在寻找的部分内容.它将键设置为nodeContainer中第一级节点的名称,这些键可用于"扩展" nodeContainer或其下任何级别的任何节点.只要我不想在较低级别"延伸"兄弟姐妹,那就有效.上面的示例文档因为以下行而无法验证:

<node name="DiningRoom" extends="RoomWithDoor">
Run Code Online (Sandbox Code Playgroud)

在我创建的模式中,RoomWithDoor不是分配给"extends"的有效密钥,因为它不是nodeContainer中第一级节点的一部分.但是,无论如何都要写密钥/ keyrefs来使它们成为有效密钥吗?键/ keyref定义的位置是否有所不同?我的xpaths是否过于具体(它们如何不那么具体)?

Zla*_*tev 0

如果将 UniqueNodes 的 XPath 选择器更改为

<xs:selector xpath="nodeContainer//node"/>
Run Code Online (Sandbox Code Playgroud)

换句话说 - nodeContainer 下的任何节点元素。这难道不会让你实现你想要实现的目标吗?