2017-01-17 2 views
1

Моя XML структура выглядит следующим образом:XML Schema: KeyRef иерархически нижний элемент

ROOT 
    |_ SetOfBandC (*) 
    |    |_ SetOfB (1) 
    |    |   |_ ElementB (*) 
    |    |   |_ ElementB__Key 
    |    |_ SetOfC (1) 
    |       |_ ElementC (*) 
    |       |_ ElementC__Key 
    |_ ElementD (*) 
    | 
    |_ SetOfBandC__Key 
    |_ ElementD__Key 
    | 
    |_ ElementD->SetOfBandC__Keyref 
    |_ ElementD->ElementB__Keyref 

В этой структуре я могу иметь несколько SetOfBandC, а также нескольких ElementB и ElementC, но только 1 SetofB и SetOfC для каждого SetOfBandC ,

Проблема заключается в том, что ElementD имеет KeyRef ссылающегося конкретный SetOfBandC и еще один ссылающиеся на ElementB этого набора, но валидатор XML при проверке СИЛЫ ElementD->ElementB__Keyref «s он ищет только в последногоSetOfBandC, а не во всех них или, лучше, в том, что указано ElementD->SetOfBandC__Keyref. Итак, когда ElementD->ElementB__Keyref ссылается на ElementB, который не находится в последних SetOfBandC, валидация не будет работать.

Вот мой ElementD->ElementB__Keyref:

<xs:keyref name="ElementD->ElementB__Keyref" refer="tns:ElementB__Key "> 
    <xs:selector xpath="tns:ElementD" /> 
    <xs:field xpath="@elementD_ref" /> 
</xs:keyref> 

И мой ElementB__Key:

<xs:key name="ElementB__Key"> 
    <xs:selector xpath="tns:ElementB" /> 
    <xs:field xpath="@elemB_name" /> 
</xs:key> 

Где ТНС это мое пространство имен. Что мне не хватает?

PS: имена в моем коде разные, и в них нет ->.

+0

сообщение вся схема – Sprotty

+0

@Sprotty я предпочел бы не делать этого, но я отправил его. – RVKS

ответ

1

Я думаю, что проблема связана с объемом ключей.

Насколько я понимаю, узел глобально идентифицируется не только по имени узла, но и имя nffg является принадлежит. Таким образом, глобально является составной ключ: политика относится к узлу с именем nffg, а также к имени узла. В текущей схеме keyRef s в политике, однако, относятся только к этим двум ключам независимо друг от друга, поэтому XML Schema не знает, что они идут вместе.

Возможно, выход может состоять в том, чтобы использовать глобально уникальные имена узлов, сделанные из префикса ключа узла ключом nffg, например Nffg1-Node1, и использовать его вместо этого в качестве одного ключа в политике. Если вы также хотите удостовериться, что ссылка ссылается на источник и конечный узел в пределах одного и того же nffg, вам может понадобиться два ключевых определения для node: один глобальный для политики keyRef s (под allNffgsAndPolicies), один локальный для nffg (до nffg) по ссылке keyRef s.

несколько иная альтернатива повторить атрибут nffgName в узлах, и использовать это вместе с неизменным атрибутом nodeName в качестве глобального составного ключа для узлов - с помощью двух xs:field элементов в ключе - что вы можете использовать в политики. Вы должны быть в состоянии убедиться, что локальный атрибут nffgname узла совпадает с атрибутом родительского nffg с key s и keyRef s.

Бонусный вопрос: он по-прежнему не объясняет, почему с исходным экземпляром и схемой отклоняется Node3, но принимаются другие значения. Я бы ожидал, что ошибка будет передана на значение, присутствующее в обоих поддеревах.В specification конфликтующие ключи по дочерним элементам удаляются из таблицы узлов, однако в этом случае такой ключ, как Node2, будет конфликтующим, поскольку он находится в обоих поддеревах, но не Node3, поскольку он появляется только в первом поддереве. Напротив, здесь происходит обратное, и, как представляется, для включения в таблицу узлов верхнего уровня рассматривается только таблица узлов последнего ребенка.

+0

Спасибо за приятные идеи. К сожалению, я не могу изменить большую часть схемы, поскольку она уже используется файлами xml и даже некоторыми приложениями, было бы лучше изменить только ключ/keyrefs, чтобы создать проблемные, 'srcNodeRef' и' destNodeRef' , Работа. – RVKS

+0

Благодарим вас за отзыв, RVKS. Я написал еще один ответ, который должен выполнить это дополнительное ограничение. –

1

Если вы можете использовать XML Schema 1.1, следующее должно работать без изменения документов XML или самой структуры схемы.

  • Удалите оба keyRef с для tns:policy

  • Вместо этого используйте утверждение в сложном типе для allNffgsAndPolicies:

    <xs:element name="allNffgsAndPolicies"> 
        <xs:complexType> 
         <xs:sequence> 
          <!-- same content as in original schema --> 
         </xs:sequence> 
         <xs:assert test="every $i in tns:policy satisfies $i/@srcNode = tns:nffg/tns:nodes/tns:node/@nodeName and $i/@destNode = tns:nffg/tns:nodes/tns:node/@nodeName"/> 
        </xs:complexType> 
        <!-- other keys and keyRefs, only keep the first three --> 
    </xs:element> 
    

я мог проверить это успешно в кислороде: он проверяет исходный документ, и не удается выполнить проверку, если использует имена существующих источников или узлов назначения.

Для активации схемы XML 1.1, добавьте эти атрибуты в xs:schema элемента:

xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" vc:minVersion="1.1" 

Чтобы пройти лишнюю милю: если на вершине этого, вы также хотите, чтобы убедиться, что имя узла существует в пределах nffg ссылаются политики с nffgRef, вы можете точно настроить утверждение:

<xs:assert test=" 
    every $i in tns:policy satisfies 
    $i/@srcNode = tns:nffg[@nffgName eq $i/@nffgRef]/tns:nodes/tns:node/@nodeName 
    and 
    $i/@destNode = tns:nffg[@nffgName eq $i/@nffgRef]/tns:nodes/tns:node/@nodeName"/> 
+0

К сожалению, я не могу использовать XML-схему 1.1. Но еще раз спасибо за вашу большую поддержку! Считаете ли вы, что нет никакого способа сделать это с помощью 'keyref's? Даже ваше первое решение, которое ищет узел во всех Nffg, а не в указанном, будет в порядке. – RVKS