如何为相同类型的嵌套元素创建带有 key/keyrefs 的 xml 模式

Posted

技术标签:

【中文标题】如何为相同类型的嵌套元素创建带有 key/keyrefs 的 xml 模式【英文标题】:How to create an xml schema with key/keyrefs for nested elements of the same type 【发布时间】:2011-02-21 14:29:53 【问题描述】:

我定期处理一些 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>

在本文档中,节点可以“扩展”其他节点:

兄弟姐妹 父母的兄弟姐妹

但是,节点不应该“扩展”:

父母 父兄弟姐妹的子节点

这意味着 MyHouse 可以“扩展”Table,这没有意义,但我可以接受。

同样重要的是,两个房屋节点都应该能够拥有自己的名为 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>

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

<node name="DiningRoom" extends="RoomWithDoor">

在我创建的架构中,RoomWithDoor 不是分配给“扩展”的有效键,因为它不是 nodeContainer 中第一级节点的一部分。但是无论如何要编写密钥/密钥引用以使它们成为有效密钥?键/keyref 定义的放置是否有所不同?我的 xpath 是否过于具体(它们怎么可能不那么具体)?

【问题讨论】:

【参考方案1】:

如果将 UniqueNodes 的 XPath 选择器更改为会发生什么

<xs:selector xpath="nodeContainer//node"/>

换句话说 - nodeContainer 下的任何节点元素。 这不会允许您想要实现的目标吗?

【讨论】:

以上是关于如何为相同类型的嵌套元素创建带有 key/keyrefs 的 xml 模式的主要内容,如果未能解决你的问题,请参考以下文章

如何为 React Native 嵌套组件创建 Typescript 定义

如何为 iOS 应用动态设计或创建带有动态 ui 控件的视图

如何为排除的元素生成带有零的向量组合矩阵?

如何为 c++ 的不同变量类型的结构元素创建动态数组?

如何为解构对象中的嵌套函数编写类型?

通用 DAO 如何为所有不同的 DAO 实现返回相同的类型?