2016-02-24 4 views
0

У меня есть 2 основных раздела в файле XML Sequence и StateRelations. Секция Последовательность определяется как. Элемент Transition должен быть unqiue на основе его 4 свойств, как определено ниже.XSD 1.1 Проверьте, существует ли атрибут в другом элементе

<xs:element name="Transition"> 
    <xs:complexType> 
     <xs:sequence> 
      <xs:element ref="Element1" minOccurs="0" maxOccurs="1"/> 
      <xs:element ref="Element2" minOccurs="0" maxOccurs="1"/> 
      <xs:element ref="Element3" minOccurs="0" maxOccurs="unbounded"/> 
     </xs:sequence> 
     <xs:attribute name="stateName" type="xs:string" use="required"/> 
     <xs:attribute name="A" type="xs:string" use="required"/> 
     <xs:attribute name="B" type="xs:string" use="required"/> 
     <xs:attribute name="C" type="xs:string" use="optional"/> 
    </xs:complexType> 
</xs:element> 
<xs:element name="Sequence"> 
    <xs:complexType> 
     <xs:sequence> 
      <xs:element ref="Transition" minOccurs="0" maxOccurs="unbounded"/> 
     </xs:sequence> 
     <xs:attribute name="name" type="xs:string" use="optional"/> 
     <xs:attribute ref="xml:base"/> 
    </xs:complexType> 
    <xs:unique name="uniqueTransition"> 
     <xs:selector xpath=".//Transition"/> 
     <xs:field xpath="@stateName"/> 
     <xs:field xpath="@A"/> 
     <xs:field xpath="@B"/> 
     <xs:field xpath="@C"/> 
    </xs:unique> 
</xs:element> 

и раздел StateRelations определяется следующим образом. «stateName1» на самом деле является внешним ключом (keyref), который связан с «stateName» (ключ) перехода. Примечание: элемент отношения фактически рекурсивный.

<xs:element name="Relation"> 
    <xs:complexType> 
     <xs:sequence> 
      <xs:element ref="Relation" minOccurs="0" maxOccurs="unbounded"/> 
     </xs:sequence> 
     <xs:attribute name="stateName1" type="xs:string" use="required"/> 
    </xs:complexType> 
</xs:element> 
<xs:element name="StateRelations"> 
    <xs:complexType> 
     <xs:sequence> 
      <xs:element ref="Relation" minOccurs="0" maxOccurs="unbounded"/> 
     </xs:sequence> 
     <xs:attribute name="name" type="xs:string" use="optional"/> 
     <xs:attribute ref="xml:base"/> 
    </xs:complexType> 
</xs:element> 

Проблема возникает в следующем сценарии. Поскольку Transition имеет уникальное ограничение, основанное на 4 атрибутах, так что справедлив следующий XML.

<Transition stateName="S3" A="a1" B="b1" C="c"/> 
<Transition stateName="S3" A="a" B="b" C="c"/> 

Как вы можете видеть, что StateName = S3 можно повторить несколько раз. Но это повторение нарушает первично-иностранную ключевую связь между «Переход и отношения». Причина: stateName может повторяться в Transitions. Теперь у нас есть конфликт. Моя конечная цель будет иметь

  1. уникальных последовательностей на основе 4 атрибутов

  2. и каждый stateName1 в StateRelations должен быть действительным StateName определены в переходах.

До сих пор, я знаю, что ключ-KeyRef не будет работать в моем сценарии, так что я начал смотреть в утверждают, но я не могу заставить его работать. Я пробовал следующее, но ничего не работает.

<xs:element name="Relation"> 
    <xs:complexType> 
     <xs:sequence> 
      <xs:element ref="Relation" minOccurs="0" maxOccurs="unbounded"/> 
     </xs:sequence> 
     <xs:attribute name="stateName1" type="xs:string" use="required"/> 

     <xs:assert test="matches(.//Transition/@stateName , @stateName1)"/> 
     <xs:assert test="/Replay/Sequence/Transition[contains(@stateName, @stateName1)]" /> 
     <xs:assert test="/Replay/Sequence/Transition[contains(@stateName, string(@stateName1))]/@stateName = string(@stateName1) "/> 

    </xs:complexType> 
</xs:element> 

EDIT: Вот XSD (я опустил некоторые детали). Теперь я хочу как-то убедиться, что /Replay/StateRelations/Relation/@stateName1 существует в /Replay/Sequence/Transition/@stateName. Я не могу использовать key/keyref, потому что /Replay/Sequence/Transition/@stateName не будет уникальным.

<Replay> 
    <xs:element name="Relation"> 
    <xs:complexType> 
     <xs:sequence> 
      <xs:element ref="Relation" minOccurs="0" maxOccurs="unbounded"/> 
     </xs:sequence> 
     <xs:attribute name="stateName1" type="xs:string" use="required"/> 
     <xs:assert test="matches(.//Transition/@stateName , @stateName1)"/> 
     <xs:assert test="/Replay/Sequence/Transition[contains(@stateName, @stateName1)]" /> 
     <xs:assert test="/Replay/Sequence/Transition[contains(@stateName, string(@stateName1))]/@stateName = string(@stateName1) "/> 
    </xs:complexType> 
</xs:element> 
<xs:element name="StateRelations"> 
    <xs:complexType> 
     <xs:sequence> 
      <xs:element ref="Relation" minOccurs="0" maxOccurs="unbounded"/> 
     </xs:sequence> 
     <xs:attribute name="name" type="xs:string" use="optional"/> 
     <xs:attribute ref="xml:base"/> 
    </xs:complexType> 
</xs:element> 

<xs:element name="Transition"> 
    <xs:complexType> 
     <xs:sequence> 
      <xs:element ref="Element1" minOccurs="0" maxOccurs="1"/> 
      <xs:element ref="Element2" minOccurs="0" maxOccurs="1"/> 
      <xs:element ref="Element3" minOccurs="0" maxOccurs="unbounded"/> 
     </xs:sequence> 
     <xs:attribute name="stateName" type="xs:string" use="required"/> 
     <xs:attribute name="A" type="xs:string" use="required"/> 
     <xs:attribute name="B" type="xs:string" use="required"/> 
     <xs:attribute name="C" type="xs:string" use="optional"/> 
    </xs:complexType> 
</xs:element> 
<xs:element name="Sequence"> 
    <xs:complexType> 
     <xs:sequence> 
      <xs:element ref="Transition" minOccurs="0" maxOccurs="unbounded"/> 
     </xs:sequence> 
     <xs:attribute name="name" type="xs:string" use="optional"/> 
     <xs:attribute ref="xml:base"/> 
    </xs:complexType> 
    <xs:unique name="uniqueTransition"> 
     <xs:selector xpath=".//Transition"/> 
     <xs:field xpath="@stateName"/> 
     <xs:field xpath="@A"/> 
     <xs:field xpath="@B"/> 
     <xs:field xpath="@C"/> 
    </xs:unique> 
</xs:element> 
</Replay> 

ответ

0

У меня возникли проблемы с разработкой структуры вашего документа на верхнем уровне. Угадывая с пути в ваших неработающих утверждениях, я думаю, что ваш элемент верхнего уровня - Replay, и у него есть одна ветвь /Replay/Sequence/Transition и, возможно, другая отдельная ветвь /Replay/StateRelations/Relation?

Если это так, то ограничение, которое определяет отношения между Transition и Relation должна быть определена на уровне общего предка, который является Replay. Вы можете определить его, используя либо key/keyref на этом уровне, либо используя утверждения, но в любом случае ограничения, влияющие на два разных элемента, всегда должны быть определены на уровне общего предка: поскольку это дерево, укорененное на этом предке, является самым маленьким - недопустимая часть документа.

В частности, обратите внимание, что утверждения не могут смотреть на данные вне поддерева, внедренные в элемент, на котором определено утверждение.Это утверждение об этом элементе и его содержании, а не утверждение о окружающем контексте этого элемента.

+0

Да, мой элемент верхнего уровня - Replay. Вы совершенно правы. Благодарю. Однажды я переместил свое утверждение на уровень Replay, и он работал нормально. Единственная проблема заключается в том, что я не могу использовать key/keyref, потому что stateName в переходах не уникален. Итак, поскольку утверждение является моим единственным вариантом, и я должен определить его вне тега Relation, я использую какой-то цикл for в XPath, чтобы проверить, существуют ли в Transition имена состояний, определенные в Relation? –

+0

Извините, я не думаю, что понимаю вашу структуру достаточно хорошо, чтобы понять, почему использование ключа/keyRef является проблемой. Когда вы говорите о циклах в XPath, это для key/keyRef или для утверждений? XPath, конечно, не имеет циклов, он полностью декларативный и работает над наборами узлов. –

+0

Простите за то, что не ясны. Я обновил свой вопрос. –

Смежные вопросы