How do I write this Schematron validation test for

2019-07-27 09:33发布

问题:

I have an XML snippet as such:

<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>

I need rule such that if the User tag exists, it should check to see if the Attribute values of id and id2 exist under the name Attribute of a Field.

So in the first AAA tag, it will validate and give 2 errors because "f" doesn't exist as a field name and neither does "y".

The AAA tags don't always have User tags, and the User tags don't always have both id and id2.

I've been messing around with some XPath expressions but to no avail.

回答1:

If you cannot use XPath 2.0, then you could write the following Schematron rules:

ISO Schematron

<?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>

I am assuming an input XML document that does not have a namespace. The assertion does not fail if a User element does not have one of those attributes in the first place or if an AAA element does not have a User element.

You did not say very clearly why Martin Honnen's suggestion did not work for you, so I list it here anyway. The rule would look like:

<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>