Handle conditional tags in Schema

This should cover W3C XML Schema, Relax NG and DTD related problems.
psridhar3
Posts: 4
Joined: Fri Jan 06, 2006 7:53 pm

Handle conditional tags in Schema

Post by psridhar3 » Fri Jan 06, 2006 7:55 pm

Hi

I am new to XML Schema and new to this forum.

I have the following requirement.

I have to validate tags present in an XML instance conditionally using a Schema.

Example is given below.

Say I have tags NAME, STATUS, SPOUSE_NAME, CHILDREN

My Schema should work as follows.

1. NAME must be present.

2. STATUS must be present and it can take values MARRIED, UNMARRIED

3. If STATUS is MARRIED then

* SPOUSE_NAME must be present

* CHILDREN is optional

4. If CHILDREN is present then

* SPOUSE_NAME must be present

* STATUS must be present and it must be MARRIED

5. SPOUSE_NAME and CHILDREN can occur in any sequence

6. If STATUS is UNMARRIED then

* SPOUSE_NAME must be absent

* CHILDREN must be absent

Can anybody help me in preparing a schema which validates all the above rules.

Thanks in advance
Sridhar P

george
Site Admin
Posts: 2102
Joined: Thu Jan 09, 2003 2:58 pm

Post by george » Mon Jan 09, 2006 2:02 pm

Hi,

You cannot do that with XML schema alone. This works however if you combine XSD with Schematron. You can have the Schematron rules embedded in your XSD schema like in the example below. If you do not want Schematron then you should enforce your rules at the application level.
Here it is a full working example.

Stidhar.xsd

Code: Select all


<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:sch="http://www.ascc.net/xml/schematron"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:annotation>
<xsd:appinfo>
<sch:title>Schematron sample validation schema</sch:title>
</xsd:appinfo>
</xsd:annotation>
<xsd:element name="document">
<xsd:annotation>
<xsd:appinfo>
<sch:pattern name="Check rules">
<!--
3. If STATUS is MARRIED then

* SPOUSE_NAME must be present

* CHILDREN is optional
-->
<sch:rule context="STATUS[text() = 'MARRIED']">
<sch:assert test="../SPOUSE_NAME">If STATUS is MARRIED then SPOUSE_NAME must
be present</sch:assert>
</sch:rule>
<!--
4. If CHILDREN is present then

* SPOUSE_NAME must be present

* STATUS must be present and it must be MARRIED
-->
<sch:rule context="CHILDREN">
<sch:assert test="../SPOUSE_NAME">If CHILDREN is present then SPOUSE_NAME
must be present</sch:assert>
<sch:assert test="../STATUS='MARRIED'">If CHILDREN is present then STATUS
must be present and it must be MARRIED</sch:assert>
</sch:rule>
<!--
6. If STATUS is UNMARRIED then

* SPOUSE_NAME must be absent

* CHILDREN must be absent
-->
<sch:rule context="STATUS[text() = 'UNMARRIED']">
<sch:assert test="not(../SPOUSE_NAME)">If STATUS is UNMARRIED then
SPOUSE_NAME must be absent</sch:assert>
<sch:assert test="not(../CHILDREN)">If STATUS is UNMARRIED then CHILDREN
must be absent</sch:assert>
</sch:rule>
</sch:pattern>
</xsd:appinfo>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<!-- 1. NAME must be present. -->
<xsd:element ref="NAME"/>
<!-- 2. STATUS must be present [and it can take values MARRIED, UNMARRIED] -->
<xsd:element ref="STATUS"/>
<!-- 5. SPOUSE_NAME and CHILDREN can occur in any sequence -->
<!-- 6. If STATUS is UNMARRIED then
* SPOUSE_NAME must be absent
* CHILDREN must be absent -->
<xsd:choice minOccurs="0">
<xsd:sequence>
<xsd:element ref="SPOUSE_NAME"/>
<xsd:element ref="CHILDREN" minOccurs="0"/>
</xsd:sequence>
<xsd:sequence>
<xsd:element ref="CHILDREN"/>
<xsd:element ref="SPOUSE_NAME" minOccurs="0"/>
</xsd:sequence>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="NAME"/>
<xsd:element name="STATUS">
<xsd:simpleType>
<!-- 2. [STATUS must be present] and it can take values MARRIED, UNMARRIED -->
<xsd:restriction base="xsd:string">
<xsd:enumeration value="MARRIED"/>
<xsd:enumeration value="UNMARRIED"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="SPOUSE_NAME"/>
<xsd:element name="CHILDREN"/>
</xsd:schema>
Note the comments in the schema, they show where the specific requirements from your message were addressed.

sample file Sridhar.xml:

Code: Select all


<?xml version="1.0" encoding="UTF-8"?>
<?oxygen SCHSchema="Sridhar.xsd"?>
<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="Sridhar.xsd">
<NAME>Joe Doe</NAME>
<STATUS>MARRIED</STATUS>
</document>
Note both schema associations, the schematron schema with an oXygen PI and the standard XML schema association. This allows you to validate in a single validate action against both schema files.

Best Regards,
George

psridhar3
Posts: 4
Joined: Fri Jan 06, 2006 7:53 pm

Post by psridhar3 » Mon Jan 09, 2006 2:10 pm

Hi George

I am really not getting words to thank you for your information.

I have been posting this doubt in so many other schema forums and none of them could answer it.

I came to know about this forum through google search and I tried in this site also. I really don't bother whether your answer truns my new proposal I am presenting to my client Signoff or Drop but I am thankful for your answer.

Regards
Sridhar P

Post Reply