Checking structure for alternative elements

This should cover W3C XML Schema, Relax NG and DTD related problems.
Frank
Posts: 1
Joined: Fri Apr 06, 2007 8:44 am
Location: Netherlands

Checking structure for alternative elements

Post by Frank »

Hi,

I'm developing a solution to provide alternative content in XML documents for certain situations. For that I created a small language that can be added to XML documents. Now I want to check the validity of this added language and the original content without manually combining both schema's because I want to create a generic solution.
I have tried this using a NVDL schema but it's not working. If anybody has any idea how I could solve this problem it will be very welcome.

Let me explain what I did:

I started with this instance document. It contains some elements with name value pairs.

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="urn:elements">
<element>
<name>Param1</name>
<value>4</value>
</element>
<element>
<name>Param2</name>
<value>5</value>
</element>
<element>
<name>Param3</name>
<value>12</value>
</element>
</root>

The xml schema for this is given by a third party. I cannot modify it. It looks like this:

elements.xsd:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="urn:elements" xmlns:elements="urn:elements">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="elements:element"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="element">
<xs:complexType>
<xs:sequence>
<xs:element ref="elements:name"/>
<xs:element ref="elements:value"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="name" type="xs:string"/>
<xs:element name="value" type="xs:integer"/>
</xs:schema>

The value for the second element in the instance document is not always "5". I want to give some alternatives (6 and 7,4) and give those alternatives some scoping information. I do that by surrounding the alternatives with special elements indicating to fact that the element is an alternative and give some dimensions with a name and value. These dimensions determine the scope for which the alternative is valid.:

elementrel.xml:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<?oxygen NVDLSchema="elementrel.nvdl"?>
<root xmlns:d="urn:relevance" xmlns="urn:elements">
<element>
<name>Param1</name>
<value>4</value>
</element>
<element>
<name>Param2</name>
<d:altlist>
<d:alt>
<d:dimValue name="type" value="17"/>
<d:dimValue name="color" value="yellow"/>
<!-- should have error on double <value> -->
<value>5</value>
<value>6</value>
</d:alt>
<d:alt>
<d:dimValue name="type" value="19"/>
<value>6</value>
</d:alt>
<d:alt>
<d:dimValue name="type" value="17"/>
<d:dimValue name="goal" value="test"/>
<!-- should have error on integer -->
<value>7,4</value>
</d:alt>
<d:alt>
<d:dimIntegerRange name="power" lowInt="110" highInt="220"/>
<!-- should have error on integer -->
<value>7,4</value>
</d:alt>
</d:altlist>
<!-- should have error on incomplete altlist -->
<d:altlist/>
<!-- should not have error on missing <value> -->
</element>
<element>
<name>Param3</name>
<value>12</value>
</element>
</root>

I will now be able to create an XML instance with the right alternative selected based on a certain situation(let's say where type='19').
The schema for this scoping/relevance information is:

rel.xsd:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="urn:relevance"
xmlns:rel="urn:relevance">
<xs:element name="altlist">
<xs:complexType>
<xs:sequence>
<xs:element ref="rel:alt" maxOccurs="unbounded" minOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="alt">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element ref="rel:dimValue"/>
<xs:element ref="rel:dimIntegerRange"/>
</xs:choice>
</xs:complexType>
</xs:element>
<xs:element name="dimValue">
<xs:complexType>
<xs:attribute name="name" use="required" type="xs:NCName"/>
<xs:attribute name="value" use="required" type="xs:NMTOKEN"/>
</xs:complexType>
</xs:element>
<xs:element name="dimIntegerRange">
<xs:complexType>
<xs:attribute name="name" use="required" type="xs:NCName"/>
<xs:attribute name="lowInt" use="required" type="xs:integer"/>
<xs:attribute name="highInt" use="required" type="xs:integer"/>
</xs:complexType>
</xs:element>
</xs:schema>

I created the following NVDL schema to relate both schema's and use them for validation.

elementrel.nvdl:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<rules xmlns="http://purl.oclc.org/dsdl/nvdl/ns/structure/1.0"
xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0" startMode="doc">
<mode name="doc">
<namespace ns="urn:elements">
<validate schema="elements.xsd" useMode="doc"/>
</namespace>
<namespace ns="urn:relevance">
<unwrap/>
<validate schema="rel.xsd"/>
</namespace>
</mode>
</rules>

It works to some extent but not all errors are caught. Also, I have to provide the "urn:elements" namespace and XML schema location in the NVDL schema and I do not want that.
I would really like a schema, NVDL or otherwise, that is capable of checking the validity of the modified XML instance without supplying this information. I shouldn't have to because the schema needs to be supplied in the instance itself.

A complicating factor is the functionality of the alternatives. An optimal solution would check every alternative with the reminder of the instance attached. So the given instance could be transformed in these three instances who then need to be validated:

for alternative 1:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:elements elements.xsd"
xmlns="urn:elements">
<element>
<name>Param1</name>
<value>4</value>
</element>
<element>
<name>Param2</name>
<value>5</value>
</element>
<element>
<name>Param3</name>
<value>12</value>
</element>
</root>
for alternative 2:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:elements elements.xsd"
xmlns="urn:elements">
<element>
<name>Param1</name>
<value>4</value>
</element>
<element>
<name>Param2</name>
<value>6</value>
</element>
<element>
<name>Param3</name>
<value>12</value>
</element>
</root>

for alternative 3:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:elements elements.xsd"
xmlns="urn:elements">
<element>
<name>Param1</name>
<value>4</value>
</element>
<element>
<name>Param2</name>
<value>7,4</value>
</element>
<element>
<name>Param3</name>
<value>12</value>
</element>
</root>
george
Site Admin
Posts: 2095
Joined: Thu Jan 09, 2003 2:58 pm

Post by george »

Hi,

You cannot trigger the multiple validations dynamically on the root element in NVDL therefore you cannot accomplish what you want.

XSLT 2.0 provides support for validation if the processor is schema aware. Therefore you should be able to use Saxon 8 SA for instance (oXygen has support for that, including debugging but you need a license from Saxonica). You can write a stylesheet that extracts all the variants you want to validate and invoke validation on each of them.

Best Regards,
George
George Cristian Bina
Post Reply