I have this XML:
<record>
<element>
<freeText>There is a big red cow.</freeText>
<terms>
<term>big</term>
<term>red</term>
<term>
</element>
<element>
<freeText>Technically this is irrelevant but I wanted to figure out if this assertion conflicts somehow.</freeText>
<terms>
<term>farm</term>
<term>animal</term>
</terms>
</element>
</record>
What I would like to do is create an assertion that if the freeText field contains "cow", then one of the terms must also be "cow".
The relevant XSD I have is this:
<xs:element name ="terms">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="term"/>
</xs:sequence>
<xs:assert test = "if (contains(../description,'cow') = true()) then (../terms/term = 'cow') else (term = *)"/>
<xs:assert text = "if (term = 'farm') then (term = 'animal') else (term = *)"/>
</xs:complexType>
</xs:element>
No matter how I write my xpath, I can't figure out how to get the first assertion to validate properly. The second assertion works fine, I have a bunch of terms with one-way co-occurrence constraints, and I've never had a problem with that. But with the assertion that checks freeText it doesn't seem to be looking in the right places. Would appreciate some help.
There's an absolute context rule that an assert can only look within the SUBTREE of the element on which it is defined. That's why you cannot use navigation up, i.e. contains(../description,'cow')
Please try the following solution.
Input XML
<record>
<element>
<freeText>There is a big red cow.</freeText>
<terms>
<term>big</term>
<term>small</term>
</terms>
</element>
<element>
<freeText>Technically this is irrelevant but I wanted to figure out if this assertion conflicts somehow.</freeText>
<terms>
<term>farm</term>
<term>animal</term>
</terms>
</element>
</record>
XSD 1.1
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="record">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="element"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="element">
<xs:complexType>
<xs:sequence>
<xs:element ref="freeText"/>
<xs:element ref="terms"/>
</xs:sequence>
<xs:assert test = "if (not(contains(freeText,'cow'))) then true() else
terms/term[. = 'cow']"/>
</xs:complexType>
</xs:element>
<xs:element name="freeText" type="xs:string"/>
<xs:element name="terms">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="term"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="term" type="xs:NCName"/>
</xs:schema>