XSD and Schematron - Problem using variables
This should cover W3C XML Schema, Relax NG and DTD related problems.
-
- Posts: 3
- Joined: Thu Aug 10, 2006 6:43 pm
XSD and Schematron - Problem using variables
I am new to XSD and Schematron and would like to know if anybody has successfully implemented variable using the new ISO Schematron element 'let' (vaiables).
I have a simple XSD and XML example below. When validating the XML I receive the following error:
Description: Failed to compile stylesheet. 1 error detected.
Description: XPath syntax error at char 8 on line 18 in {$theuser='B'}:
Variable $theuser has not been declared
The XSD file:
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:sch="http://www.ascc.net/xml/schematron">
<xs:annotation>
<xs:appinfo>
<sch:title>Schematron validation schema for Portal Client</sch:title>
<sch:ns prefix="C" uri="http://example.com/po-schematron" />
</xs:appinfo>
</xs:annotation>
<xs:element name="Client" >
<xs:complexType>
<xs:sequence>
<xs:element name="UserId" type="xs:string" minOccurs="0" >
<xs:annotation>
<xs:appinfo>
<sch:pattern name="UserId Required Fields\">
<sch:rule context="C:UserId ">
<sch:let name="theuser" value="text()"/>
<sch:assert test="$theuser='B'">User is invalid</sch:assert>
<sch:assert test="../C:clientId[text()]">Client Id is required </sch:assert>
<sch:assert test="../C:CompanyName[text()]">CompanyName is required</sch:assert>
</sch:rule>
</sch:pattern>
</xs:appinfo>
</xs:annotation>
</xs:element>
<xs:element name="clientId" type="xs:string" minOccurs="0" />
<xs:element name="CompanyName" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
XML content:
<?xml version="1.0" encoding="UTF-8"?>
<?oxygen SCHSchema="client.xsd"?>
<Client xmlns="http://example.com/po-schematron"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<UserId></UserId>
<clientId></clientId>
<CompanyName></CompanyName>
</Client>
I have a simple XSD and XML example below. When validating the XML I receive the following error:
Description: Failed to compile stylesheet. 1 error detected.
Description: XPath syntax error at char 8 on line 18 in {$theuser='B'}:
Variable $theuser has not been declared
The XSD file:
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:sch="http://www.ascc.net/xml/schematron">
<xs:annotation>
<xs:appinfo>
<sch:title>Schematron validation schema for Portal Client</sch:title>
<sch:ns prefix="C" uri="http://example.com/po-schematron" />
</xs:appinfo>
</xs:annotation>
<xs:element name="Client" >
<xs:complexType>
<xs:sequence>
<xs:element name="UserId" type="xs:string" minOccurs="0" >
<xs:annotation>
<xs:appinfo>
<sch:pattern name="UserId Required Fields\">
<sch:rule context="C:UserId ">
<sch:let name="theuser" value="text()"/>
<sch:assert test="$theuser='B'">User is invalid</sch:assert>
<sch:assert test="../C:clientId[text()]">Client Id is required </sch:assert>
<sch:assert test="../C:CompanyName[text()]">CompanyName is required</sch:assert>
</sch:rule>
</sch:pattern>
</xs:appinfo>
</xs:annotation>
</xs:element>
<xs:element name="clientId" type="xs:string" minOccurs="0" />
<xs:element name="CompanyName" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
XML content:
<?xml version="1.0" encoding="UTF-8"?>
<?oxygen SCHSchema="client.xsd"?>
<Client xmlns="http://example.com/po-schematron"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<UserId></UserId>
<clientId></clientId>
<CompanyName></CompanyName>
</Client>
-
- Posts: 3
- Joined: Thu Aug 10, 2006 6:43 pm
Do you know if there is any customization that can be done that would address this issue?
Maybe you would give me another suggestion in how to solve the problem we are trying to address: We need to create a rule that contain 'n' number of assertions. The asserts contains similar constraints. We are trying to avoid repetion in the assert expressions. For example:
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:sch="http://www.ascc.net/xml/schematron">
<xs:annotation>
<xs:appinfo>
<sch:title>Schematron validation schema for Portal Client</sch:title>
<sch:ns prefix="C" uri="http://example.com/po-schematron" />
</xs:appinfo>
</xs:annotation>
<xs:element name="Client" >
<xs:complexType>
<xs:sequence>
<xs:element name="UserId" type="xs:string" minOccurs="0" >
<xs:annotation>
<xs:appinfo>
<sch:pattern name="UserId Required Fields\">
<sch:rule context="C:UserId ">
<sch:assert test="../C:CompanyName[text()]">CompanyName is required</sch:assert>
<sch:assert test="../C:clientId[text()] and ../C:CompanyName[text()] and ../C:abc[text()]">abc is required </sch:assert>
<sch:assert test="../C:clientId[text()] and ../C:CompanyName[text()] and ../C:def[text()]">def is required </sch:assert>
<sch:assert test="../C:clientId[text()] and ../C:CompanyName[text()] and ../C:xyz[text()]">xyz is required </sch:assert>
</sch:rule>
</sch:pattern>
</xs:appinfo>
</xs:annotation>
</xs:element>
<xs:element name="clientId" type="xs:string" minOccurs="0" />
<xs:element name="CompanyName" type="xs:string" minOccurs="0" />
<xs:element name="abc" type="xs:string" minOccurs="0" />
<xs:element name="def" type="xs:string" minOccurs="0" />
<xs:element name="xyz" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
How can we rewrite this rule so we do not repeat
../C:clientId[text()] and ../C:CompanyName[text()] in each assertion?
In our application we usually have 10(ten) asserts for each rule.
Your help is appreciated.
Maybe you would give me another suggestion in how to solve the problem we are trying to address: We need to create a rule that contain 'n' number of assertions. The asserts contains similar constraints. We are trying to avoid repetion in the assert expressions. For example:
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:sch="http://www.ascc.net/xml/schematron">
<xs:annotation>
<xs:appinfo>
<sch:title>Schematron validation schema for Portal Client</sch:title>
<sch:ns prefix="C" uri="http://example.com/po-schematron" />
</xs:appinfo>
</xs:annotation>
<xs:element name="Client" >
<xs:complexType>
<xs:sequence>
<xs:element name="UserId" type="xs:string" minOccurs="0" >
<xs:annotation>
<xs:appinfo>
<sch:pattern name="UserId Required Fields\">
<sch:rule context="C:UserId ">
<sch:assert test="../C:CompanyName[text()]">CompanyName is required</sch:assert>
<sch:assert test="../C:clientId[text()] and ../C:CompanyName[text()] and ../C:abc[text()]">abc is required </sch:assert>
<sch:assert test="../C:clientId[text()] and ../C:CompanyName[text()] and ../C:def[text()]">def is required </sch:assert>
<sch:assert test="../C:clientId[text()] and ../C:CompanyName[text()] and ../C:xyz[text()]">xyz is required </sch:assert>
</sch:rule>
</sch:pattern>
</xs:appinfo>
</xs:annotation>
</xs:element>
<xs:element name="clientId" type="xs:string" minOccurs="0" />
<xs:element name="CompanyName" type="xs:string" minOccurs="0" />
<xs:element name="abc" type="xs:string" minOccurs="0" />
<xs:element name="def" type="xs:string" minOccurs="0" />
<xs:element name="xyz" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
How can we rewrite this rule so we do not repeat
../C:clientId[text()] and ../C:CompanyName[text()] in each assertion?
In our application we usually have 10(ten) asserts for each rule.
Your help is appreciated.
-
- Site Admin
- Posts: 2095
- Joined: Thu Jan 09, 2003 2:58 pm
Hi,
You can very well use something like:
There is no need for repeating an already checked condition.
For a more compact check you can set the XPath level to XSLT 2.0 from Options->Preferences -- XML -- XML Parser -- Schematron XPath Version and then write the conditions like:
So basically we iterate the sequence with the fields we require and return a field if it has text content, otherwise not, then we check that we get the same number of fields as the required fields number.
Best Regards,
George
You can very well use something like:
Code: Select all
<sch:pattern name="UserId Required Fields\">
<sch:rule context="C:UserId ">
<sch:assert test="../C:CompanyName[text()]">CompanyName is required</sch:assert>
<sch:assert test="../C:clientId[text()]">clientId is required </sch:assert>
<sch:assert test="../C:abc[text()]">abc is required </sch:assert>
<sch:assert test="../C:def[text()]">def is required </sch:assert>
<sch:assert test="../C:xyz[text()]">xyz is required </sch:assert>
</sch:rule>
</sch:pattern>
For a more compact check you can set the XPath level to XSLT 2.0 from Options->Preferences -- XML -- XML Parser -- Schematron XPath Version and then write the conditions like:
Code: Select all
<sch:pattern name="UserId Required Fields">
<sch:rule context="C:UserId ">
<sch:assert test="count(for $i in (../C:UserId, ../C:CompanyName, ../C:clientId) return $i[text()])=3">
UserId, CompanyName and ClientId inside Client are required if the UserId element is specified.</sch:assert>
</sch:rule>
</sch:pattern>
Best Regards,
George
-
- Posts: 3
- Joined: Thu Aug 10, 2006 6:43 pm
Thank you for your help.
What is your opinion on the following solution:
Create a pattern with two rules. The first rule will contain the main condition that would be required to add to each assert. If the first rule fails then the second rule will not be executed. The only problem here is how do I create rules with the same context in the same pattern? Just a remainder that those rules are very simple realted to what the real scenario would be.
<sch:pattern name="UserId Required Fields">
<sch:rule context="C:UserId ">
<sch:assert test="../C:CompanyName[text()] and ../C:clientId[text()]">Main rule failed </sch:assert>
</sch:rule>
<sch:rule context="C:UserId ">
<sch:assert test="../C:CompanyName[text()]">b CompanyName is required</sch:assert>
<sch:assert test="../C:clientId[text()]">b clientId is required </sch:assert>
<sch:assert test="../C:abc[text()]">b abc is required </sch:assert>
<sch:assert test="../C:def[text()]">b def is required </sch:assert>
<sch:assert test="../C:xyz[text()]">b xyz is required </sch:assert>
</sch:rule>
</sch:pattern>
What is your opinion on the following solution:
Create a pattern with two rules. The first rule will contain the main condition that would be required to add to each assert. If the first rule fails then the second rule will not be executed. The only problem here is how do I create rules with the same context in the same pattern? Just a remainder that those rules are very simple realted to what the real scenario would be.
<sch:pattern name="UserId Required Fields">
<sch:rule context="C:UserId ">
<sch:assert test="../C:CompanyName[text()] and ../C:clientId[text()]">Main rule failed </sch:assert>
</sch:rule>
<sch:rule context="C:UserId ">
<sch:assert test="../C:CompanyName[text()]">b CompanyName is required</sch:assert>
<sch:assert test="../C:clientId[text()]">b clientId is required </sch:assert>
<sch:assert test="../C:abc[text()]">b abc is required </sch:assert>
<sch:assert test="../C:def[text()]">b def is required </sch:assert>
<sch:assert test="../C:xyz[text()]">b xyz is required </sch:assert>
</sch:rule>
</sch:pattern>
-
- Site Admin
- Posts: 2095
- Joined: Thu Jan 09, 2003 2:58 pm
If what you want is to apply a set of asserts when some condition is met then move that condition in the rule context like below
Best Regards,
George
Code: Select all
<sch:pattern name="UserId Required Fields">
<sch:rule context="C:UserId[../C:CompanyName[text()] and ../C:clientId[text()]]">
<sch:assert test="../C:CompanyName[text()]">b CompanyName is required</sch:assert>
<sch:assert test="../C:clientId[text()]">b clientId is required </sch:assert>
<sch:assert test="../C:abc[text()]">b abc is required </sch:assert>
<sch:assert test="../C:def[text()]">b def is required </sch:assert>
<sch:assert test="../C:xyz[text()]">b xyz is required </sch:assert>
</sch:rule>
</sch:pattern>
George
Jump to
- Oxygen XML Editor/Author/Developer
- ↳ Feature Request
- ↳ Common Problems
- ↳ DITA (Editing and Publishing DITA Content)
- ↳ SDK-API, Frameworks - Document Types
- ↳ DocBook
- ↳ TEI
- ↳ XHTML
- ↳ Other Issues
- Oxygen XML Web Author
- ↳ Feature Request
- ↳ Common Problems
- Oxygen Content Fusion
- ↳ Feature Request
- ↳ Common Problems
- Oxygen JSON Editor
- ↳ Feature Request
- ↳ Common Problems
- Oxygen PDF Chemistry
- ↳ Feature Request
- ↳ Common Problems
- Oxygen Feedback
- ↳ Feature Request
- ↳ Common Problems
- Oxygen XML WebHelp
- ↳ Feature Request
- ↳ Common Problems
- XML
- ↳ General XML Questions
- ↳ XSLT and FOP
- ↳ XML Schemas
- ↳ XQuery
- NVDL
- ↳ General NVDL Issues
- ↳ oNVDL Related Issues
- XML Services Market
- ↳ Offer a Service