Как создать XML-схему с ключом / keyrefs для вложенных элементов одного типа - PullRequest
6 голосов
/ 20 мая 2010

Я работаю с некоторыми 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>

В этом документе узлы могут «расширять» другие узлы, которые:

  • 1009 * братья *
  • братьев и сестер родителей

однако узлы не должны «расширяться»:

  • Родители
  • дочерние узлы родных братьев и сестер

Это означает, что 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, чтобы сделать их действительными ключами? Имеет ли место определение ключей / keyref определений? Являются ли мои xpath слишком конкретными (как они могут быть менее конкретными)?

1 Ответ

0 голосов
/ 28 марта 2014

Что произойдет, если вы измените селектор XPath для уникальных узлов на

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

Другими словами - любой элемент узла под nodeContainer. Разве это не позволило бы достичь того, чего вы хотите достичь?

...