Page 1 of 1

Schematron - using variables in XPATH

Posted: Fri Apr 15, 2016 1:10 am
by Richard_Wood
Hello,
I am trying to create a variable ($refValue) using XPATH to capture a value from an XML file that I ultimately want to validate.
Then I want to use that variable along with a variable created using the document() function (which references an external XML file), apended with an XPATH to capture a value from an external XML file to create another variable($qualifierValue) .
I then want to use the second variable ($qualifierValue) in validations in my report element.
I set all of the variables inside of the rule element, prior to the assert element.

When I display the contents of $qualifierValue in a report element, it apears empty
But if I display the documet()//XPATH used to set $qualifierValue, the expected value is present, namely "MY"

I saw one post, that appeared to say I can't use variables in XPATH to test attribute values, but I am not sure of that.

I will include my Schematron schema, the XML file that I am trying to validate, and the external XML files that I am trying to reference.
I use a report element to show the values of my variables. I will include that output too.

The assertion should be true, but it reports indicating that the test fails.
I've tried a lot of different approaches. There must be something about setting variables using XPATH and variables that I don't know.

Help please, what am I doing that is wrong?

First, here is the output of using the schema against the XML in OxygenXML 17.1

context = AMM;
registryItemValue = AMM;
refValue = MY-SHOP;
refPath = http://docs.my.company.com:8180/DDMFReg ... aProviders;
refXmlFilename = ;
qualifierValue1 = ; <== This is the value-of the $qualifierValue
qualifierValue2 = MY; <== This is the value of the "value" attribute that is supposed to set the $qualifierValue
path = http://docs.my.company.com:8180/DDMFReg ... umentTypes;
registryXmlFilename = ;

Here is the output of the assert that also comes out when I run the schema:
This DDMF XML references a / Document/ documentType of: AMM which does not exist in the registry.

Here is the Schematron schema:

Code: Select all


<?xml version="1.0" encoding="UTF-8"?>
<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2">
<sch:ns uri="http://www.w3.org/2001/XMLSchema-instance" prefix="isx"/>
<sch:pattern id="validateDocumentType">
<sch:rule context="//Document/documentType">
<sch:let name="registryItemValue" value="normalize-space(.)"/>
<sch:let name="refValue" value="//Document/dataProvider"/>
<sch:let name="refPath" value="'http://docs.my.company.com:8180/DDMFRegistryService/registry/XML/dataProviders'"/>
<sch:let name="refXmlFilename" value="document($refPath)"/>
<sch:let name="qualifierValue" value="$refXmlFilename//registry/entry/item[@key='dataProvider' and @value='$refValue']/../item[@key='ns']/@value"/>
<sch:let name="path" value="'http://docs.my.company.com:8180/DDMFRegistryService/registry/XML/documentTypes'"/>
<sch:let name="registryXmlFilename" value="document($path)"/>
<!-- debugging test -->
<sch:report role="warn" test="true()">
<!-- change this to true() for debugging -->
context = <sch:value-of select="//Document/documentType"/>;
registryItemValue = <sch:value-of select="$registryItemValue"/>;
refValue = <sch:value-of select="$refValue"/>;
refPath = <sch:value-of select="$refPath"/>;
refXmlFilename = <sch:value-of select="$refXmlFilename"/>;
qualifierValue1 = <sch:value-of select="$qualifierValue"/>;
qualifierValue2 = <sch:value-of select="$refXmlFilename//registry/entry/item[@key='dataProvider' and @value='MY-SHOP']/../item[@key='ns']/@value"/>;
path = <sch:value-of select="$path"/>;
registryXmlFilename = <sch:value-of select="$refXmlFilename"/>;
</sch:report>
<sch:assert role="error"
test="$registryXmlFilename//registry/entry/item[
@key=documentType
and @value = $registryItemValue]
/../item[@key='ns']
/@value=$qualifierValue" >
This DDMF XML references a
<sch:value-of select="name(../..)"/>/
<sch:value-of select="name(..)"/>/
<sch:value-of select="name()"/> of:
<sch:value-of select="."/> which does
not exist in the registry.
</sch:assert>
</sch:rule>
</sch:pattern>
</sch:schema>
Here is one external XML file (associated with the $refPath variable):
http://docs.my.company.com:8180/DDMFReg ... aProviders

Code: Select all


<?xml version="1.0" encoding="utf-8"?>
<registry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://dast.my.company.com/assets/registry/schema/1-0/registry.xsd"
schemaVersion="1.0" identity="dataProviders"
modified="2016-02-05T21:19:00Z">
<entry status="stable" modified="2016-02-04T21:36:00Z" >
<item key="ns" value="MY" />
<item key="dataProvider" value="MY-SHOP" />
</entry>
<entry status="stable" modified="2016-02-04T21:36:00Z" >
<item key="ns" value="YOUR" />
<item key="dataProvider" value="YOUR-SHOP" />
</entry>
</registry>
Here is the second external XML file (associated with the $path variable):
http://docs.my.Company.com:8180/DDMFReg ... umentTypes

Code: Select all


<?xml version="1.0" encoding="utf-8"?>
<registry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://dast.my.company.com/assets/registry/schema/1-0/registry.xsd"
schemaVersion="1.0" identity="documentTypes"
modified="2016-04-13T20:35:42Z">
<entry status="unstable" modified="2015-07-07T17:30:00Z" >
<item key="ns" value="YOUR" />
<item key="documentType" value="AMM" />
</entry>
<entry status="stable" modified="2015-07-07T17:30:00Z" >
<item key="ns" value="MY" />
<item key="documentType" value="AMM" />
</entry>
</registry>
Here is the XML file that I am trying to validate:

Code: Select all


<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.my.company.com/ddmf/ddmf.xsd"
schemaVersion="3.0">
<status>TEST</status>
<packageTimestamp>2015-03-11T12:00:00Z</packageTimestamp>
<dataProvider>MY-SHOP</dataProvider>
<documentType>AMM</documentType>
</Document>

Re: Schematron - using variables in XPATH

Posted: Fri Apr 15, 2016 10:42 am
by tavy
Hello,

I corrected your Schematron schema, you can find it below. You made some small mistakes:
- in the 'qualifierValue' variable the $refValue should not be in apostrophes, instead of @value='$refValue' use @value=$refValue.
- in the assert you need to use apostrophes for documentType, instead of @key=documentType use @key='documentType'.

Code: Select all


<?xml version="1.0" encoding="UTF-8"?>
<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2">
<sch:ns uri="http://www.w3.org/2001/XMLSchema-instance" prefix="isx"/>
<sch:pattern id="validateDocumentType">
<sch:rule context="//Document/documentType">
<sch:let name="registryItemValue" value="normalize-space(.)"/>
<sch:let name="refValue" value="//Document/dataProvider"/>
<sch:let name="refPath" value="'http://docs.my.company.com:8180/DDMFRegistryService/registry/XML/dataProviders'"/>
<sch:let name="refXmlFilename" value="document($refPath)"/>
<sch:let name="qualifierValue" value="$refXmlFilename//registry/entry/item[@key='dataProvider' and @value=$refValue]/../item[@key='ns']/@value"/>
<sch:let name="path" value="'http://docs.my.company.com:8180/DDMFRegistryService/registry/XML/documentTypes'"/>
<sch:let name="registryXmlFilename" value="document($path)"/>
<!-- debugging test -->
<sch:report role="warn" test="true()">
<!-- change this to true() for debugging -->
context = <sch:value-of select="//Document/documentType"/>;
registryItemValue = <sch:value-of select="$registryItemValue"/>;
refValue = <sch:value-of select="$refValue"/>;
refPath = <sch:value-of select="$refPath"/>;
refXmlFilename = <sch:value-of select="$refXmlFilename"/>;
qualifierValue1 = <sch:value-of select="$qualifierValue"/>;
qualifierValue2 = <sch:value-of select="$refXmlFilename//registry/entry/item[@key='dataProvider' and @value='MY-SHOP']/../item[@key='ns']/@value"/>;
path = <sch:value-of select="$path"/>;
registryXmlFilename = <sch:value-of select="$refXmlFilename"/>;
</sch:report>
<sch:assert role="error"
test="$registryXmlFilename//registry/entry/item[
@key='documentType'
and @value = $registryItemValue]
/../item[@key='ns']
/@value=$qualifierValue" >
This DDMF XML references a
<sch:value-of select="name(../..)"/>/
<sch:value-of select="name(..)"/>/
<sch:value-of select="name()"/> of:
<sch:value-of select="."/> which does
not exist in the registry.
</sch:assert>
</sch:rule>
</sch:pattern>
</sch:schema>
Best Regards,
Octavian

Re: Schematron - using variables in XPATH

Posted: Mon Apr 18, 2016 8:17 pm
by Richard_Wood
Thank-you Octavian,

I have now resolved all of my issues (I only documented one) based on your corrections and confidence that what I was trying to do was in fact possible.

I am particularly pleased to have this schema working. We have many complex validations which will involve multiple elements and multiple registry table look-up values. Thanks for the confidence to persevere!

Regards,

Rich Wood