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