我定期处理一些 XML 文件,并希望获得比 DTD 所能提供的更好的验证。所以我开始阅读模式,看看是否能帮到我。到目前为止,除了一件之外,我已经能够创造出几乎可以像我需要的那样工作的东西。我希望能够将元素的属性限制为具有相同元素类型的兄弟元素或祖先元素的不同属性值。这甚至可以通过 XML 模式键/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>
在本文档中,节点可以“扩展”其他节点:
- sibling
- parent 的 sibling
但是,节点不应该“扩展”:
- parent
- 父节点的兄弟节点
这意味着 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 或以下任何级别的任何节点.只要我不想在较低级别“扩展” sibling ,这就有效。由于这一行,上面的示例文档无法验证:
<node name="DiningRoom" extends="RoomWithDoor">
在我创建的模式中,RoomWithDoor 不是分配给“扩展”的有效键,因为它不是 nodeContainer 中第一级节点的一部分。但是无论如何要编写 key / key 引用以使它们成为有效 key 吗?键/keyref 定义的放置是否有所不同?我的 xpath 是否过于具体(它们怎么可能不那么具体)?
最佳答案
如果将 UniqueNodes 的 XPath 选择器更改为
<xs:selector xpath="nodeContainer//node"/>
换句话说 - nodeContainer 下的任何节点元素。 这不会让你想要达到的目的吗?
关于xml - 如何为相同类型的嵌套元素创建带有键/键引用的 xml 模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2869448/