Ключ XML Schema /keyref - как их использовать?
Короче говоря: я хотел бы знать, как использовать ключ /keyref из XSD, чтобы элементы имели ссылки друг на друга. он должен иметь форму примера с использованием простого xsd и XML.
Длинная история: я знаком с использованием ID/IDREF. Я использую их для подключения элементов для JAXB. Мне неоднократно говорили, что конструкция key/keyref в XSD предлагает повышенную гибкость для межэлементных ссылок. Я проконсультировался с книгой OReilly XML Schema, которая, кажется, учит всему правильному определению key/keyref и тому, как он похож на ID/IDREF (но лучше), и не дает простого примера его использования. Похоже, что это не похоже, потому что вы определяете ID как атрибут в одном элементе и IDREF в другом элементе и вуаля. Но ключ /keyref должны быть определены в общем предке ссылки и ссылочного элемента (AFAIK)...
Я использую файлы XSD для генерации связанных с JAXB классов Java с помощью XJC
Я искал инструкции, учебники и примеры, но Google дает мне записки. То же самое для поисков на SO (также с Google и включенным поиском с '+').
Чтобы облегчить жизнь всем, я подготовил XSD с уже определенной парой ключ / ключ, как я ее понял.
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="referenced">
<xs:complexType>
<xs:attribute name="id" type="xs:string" />
</xs:complexType>
</xs:element>
<xs:element name="owner">
<xs:complexType>
<xs:attribute name="id" type="xs:string" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:key name="aKey">
<xs:selector xpath="owner" />
<xs:field xpath="@id" />
</xs:key>
<xs:keyref name="aKeyRef" refer="aKey">
<xs:selector xpath="referenced" />
<xs:field xpath="@id" />
</xs:keyref>
</xs:element>
Как будет выглядеть фрагмент XML с элементом "owner", ссылающимся на элемент "referenced"?
РЕДАКТИРОВАТЬ: применил изменение, предложенное Томом W, изменив атрибут xpath ключевого элемента на "владелец". JAXB (XJC) все еще все равно.
Спасибо
5 ответов
Я обнаружил, что этот поток ищет то же самое, что искал OP - простой пример использования <xs:key>
элемент. Все вещи JAXB были греческими для меня и отвлекающими. Для других, кто найдет эту ветку позже, вот простой пример, опубликованный на MSDN через пару лет после того, как OP задал вопрос здесь на SO:
https://msdn.microsoft.com/en-us/library/ms256101%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
В случае изменения ссылки MSDN путь крошки был:
https://msdn.microsoft.com/library затем нажмите "Переключиться на представление оглавления библиотеки" и просмотрите:
Библиотека MSDN> Разработка.NET> .NET Framework 4.6 и 4.5 > Руководство по разработке> Данные и моделирование> Справочник по стандартам XML> Справочник по схемам XML (XSD)> Элементы схемы XML> Элемент
В экземпляре документа нет специального синтаксиса. Просто требуется, чтобы узел keyref соответствовал существующему узлу ключа. Валидация покажет вам, удовлетворено ли ключевое ограничение.
RE ваш код:
Я только что начал баловаться с ключами сам, но я думаю, что я заметил ошибку в вашем - aKey
должен выглядеть так:
<xs:key name="aKey">
<xs:selector xpath="owner" />
<xs:field xpath="@id" />
</xs:key>
Кроме того, это - проблема с ключом - ключи не распознают пространство имен по умолчанию. Вы должны всегда ставить префикс каждой части selector
xpath с префиксом пространства имен элемента, который вы ищете. Если у вас нет префикса пространства имен - жесткий, вам нужно добавить его. Это ограничение стандарта.
Спецификация JAXB явно не охватывает key/keyref. Однако реализации JAXB, такие как EclipseLink MOXy (я технический руководитель), имеют расширения для этого. В нашем следующем выпуске 2.2 предусмотрены средства для определения такого рода отношений с помощью аннотаций (я приведу пример). Ниже приведена ссылка на то, как это можно сделать с помощью текущей версии.
Для получения дополнительной информации см.:
ОБНОВИТЬ
Я надеялся получить пример с ответом, но у меня заканчивается время, прежде чем я уезжаю в отпуск. Ниже приведен пример из нашей проектной документации, которая демонстрирует концепцию:
Пожалуйста, попробуйте посмотреть этот учебник по ключам / ключам.
Цветной текст очень полезен.
JAXB не поддерживает ссылки с помощью xs:key
или же xs:keyref
, В спецификации говорится, что эти ограничения могут быть проверены во время проверки, но они не влияют на данные.
Тем не менее, вы можете достичь этого (более или менее) с помощью xs:ID
а также xs:IDREF
вместо. Для ознакомления см. Главы 2.2.15. Обращение к другому элементу XML и 4.3. Сборка данных с помощью ссылок (ID, IDREF) в Учебном пособии по J AXB, разработанном Вольфгангом Лауном.
Для вашего образца XSD это будет означать изменение определения элемента на
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="referenced">
<xs:complexType>
<xs:attribute name="id" type="xs:ID" />
</xs:complexType>
</xs:element>
<xs:element name="owner">
<xs:complexType>
<xs:attribute name="id" type="xs:IDREF" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
Обратите внимание, что идентификаторы с xs:ID
тип должен быть глобально уникальным в документе XML. Другими словами, вы не можете иметь один и тот же идентификатор для двух разных элементов в одном и том же XML-файле, даже если элементы имеют разные типы.
По умолчанию элемент или атрибут типа xs:IDREF
привязывается к java.lang.Object
, Если вы заранее знаете, каким будет тип ссылочного объекта, вы можете настроить отображение, добавив аннотации JAXB в схему или с помощью внешнего объявления привязки (например, xjc -b bindings.xjb
).
Пример использования аннотаций схемы JAXB (не тестировался):
<xs:element name="owner">
<xs:complexType>
<xs:attribute name="id" type="xs:IDREF">
<xs:annotation>
<xs:appinfo>
<jaxb:property>
<jaxb:baseType name=”SomeType”/>
</jaxb:property>
</xs:appinfo>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
Пример использования объявления внешних привязок (не проверено):
<jaxb:bindings node="//xs:element[@name=’owner’]//xs:attribute[@name='id']”>
<jaxb:property>
<jaxb:basetype name="SomeType"/>
</jaxb:property>
</jaxb:bindings>