Как создать XML-схему с ключом /keyrefs для вложенных элементов одного типа
Я работаю с некоторыми XML-файлами на регулярной основе и хочу иметь лучшую проверку, чем может обеспечить DTD. Поэтому я начал читать о схемах, чтобы посмотреть, поможет ли это мне. До сих пор я был в состоянии создать что-то, что работает почти так, как мне нужно, за исключением одного куска. Я хочу иметь возможность ограничить атрибут элемента значениями другого атрибута родственных или родственных элементов одного типа. Возможно ли это даже с помощью ограничений схемы ключей / ключей XML-схемы?
У меня есть документ, который выглядит примерно так:
<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 может "расширить" таблицу, что не имеет смысла, но я согласен с этим.
Также важно то, что оба домашних узла должны иметь свои собственные узлы с именем 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 не является допустимым ключом, который можно назначить для "extends", поскольку он не является частью первого уровня узлов в nodeContainer. Но есть ли в любом случае написать ключи / keyrefs, чтобы сделать их действительными ключами? Имеет ли место определение ключей / определений ключей разницу? Являются ли мои xpath слишком конкретными (как они могут быть менее конкретными)?
1 ответ
Что произойдет, если вы измените селектор XPath для уникальных узлов на
<xs:selector xpath="nodeContainer//node"/>
Другими словами - любой элемент узла под nodeContainer. Разве это не позволило бы достичь того, чего вы хотите достичь?