Как написать этот проверочный тест Schematron для фрагмента XML?

У меня есть фрагмент XML как таковой:

<AAA>
    <Field name="a"/>
    <Field name="b"/>
    <Field name="x"/>
    <User id="x" id2="f"/>
    <User id="y"/>
</AAA>
<AAA>
    <Field name="r"/>
    <Field name="z"/>
</AAA>

Мне нужно правило, чтобы, если тег пользователя существует, он должен проверять, существуют ли значения атрибута id и id2 под именем атрибута поля.

Таким образом, в первом теге AAA он будет проверен и выдаст 2 ошибки, потому что "f" не существует в качестве имени поля, равно как и "y".

Теги AAA не всегда содержат пользовательские теги, а пользовательские теги не всегда содержат как id, так и id2.

Я возился с некоторыми выражениями XPath, но безрезультатно.


person user3418847    schedule 27.01.2017    source источник
comment
Вы используете Schematron с XPath 2.0 или 1.0? В XPath 2.0 вы можете легко написать some $user in User satisfies not($user/(@id, @id2) = Field/@name.   -  person Martin Honnen    schedule 28.01.2017
comment
Это не совсем так.   -  person user3418847    schedule 28.01.2017
comment
Покажите полный входной XML-документ. Спасибо! Кроме того, это не совсем так, это не очень точное сообщение об ошибке. Что именно не получилось?   -  person Mathias Müller    schedule 28.01.2017


Ответы (1)


Если вы не можете использовать XPath 2.0, вы можете написать следующие правила Schematron:

Схематрон ISO

<?xml version="1.0" encoding="UTF-8"?>
<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2">

    <sch:pattern>
        <sch:rule context="User[@id]">
            <sch:assert test="@id = ../Field/@name">User ID does not exist as a field!</sch:assert>
        </sch:rule>

        <sch:rule context="User[@id2]">
            <sch:assert test="@id2 = ../Field/@name">User ID2 does not exist as a field!</sch:assert>
        </sch:rule>
    </sch:pattern>

</sch:schema>

Я предполагаю, что входной XML-документ не имеет пространства имен. Утверждение не будет ошибочным, если элемент User изначально не имеет ни одного из этих атрибутов или если элемент AAA не имеет элемента User.

Вы не очень четко сказали, почему предложение Мартина Хоннена не сработало для вас, поэтому я все равно перечисляю его здесь. Правило будет выглядеть так:

<sch:pattern>
    <sch:rule context="AAA">
        <sch:report test="some $user in User satisfies not($user/(@id, @id2) = Field/@name)">User ID does not exist as a field!</sch:report>
    </sch:rule>
</sch:pattern>
person Mathias Müller    schedule 28.01.2017
comment
Большое тебе спасибо! Это сделало это. Я не смог показать трассировку стека или что-то более конкретное, потому что у меня нет способа отладить мои утверждения схемы. Я не знал, что я получаю обратно, но я знал, что то, что я возвращаю, было неправильным. - person user3418847; 31.01.2017