ZVON > Tutorials > XML Schema and Relax NG Tutorial
Index | >> Example 3 / 6 << | Prev | Next |
Contents > Unique and key > Uniqueness - comparison of numbers

Uniqueness - comparison of numbers

  1. XML Schema
  2. Relax NG + Schematron
XML Schema keys: unique

1. XML Schema

In all checkings of "key", "unique", and "keyref" the values are compared, not string-values.

Valid document


<root xsi:noNamespaceSchemaLocation="correct_0.xsd" xmlns="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
  <a val="1.0"/>
  <a val="2"/>
  <a val="3.5"/>
</root>

Invalid document
Because the "val" attribute is "decimal", there is duplicate value (1 = 1.0), which is not allowed.


<root xsi:noNamespaceSchemaLocation="correct_0.xsd" xmlns="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
  <a val="1"/>
  <a val="1.0"/>
  <a val="2"/>
</root>

Correct XML Schema (correct_0.xsd)
The "xpath" attribute of "selector" and "field" elements is a restricted XPath relative to the element in which it is declared (here it is relative to the "root" element).


<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" >

  <xsd:element name="root" type="myList">
    <xsd:unique name="myId">
      <xsd:selector xpath="./a"/>
      <xsd:field xpath="@val"/>
    </xsd:unique>
  </xsd:element>

  <xsd:complexType name="myList">
    <xsd:sequence minOccurs="1">
      <xsd:element name="a" minOccurs="1" maxOccurs="unbounded">
        <xsd:complexType>
          <xsd:attribute name="val" type="xsd:decimal"/>
        </xsd:complexType>
      </xsd:element>
    </xsd:sequence>
  </xsd:complexType>
</xsd:schema>

2. Relax NG + Schematron

Schematron uses XPath functions, so we can force the conversion to a number.

Valid document


<root xmlns="">
  <a val="1.0"/>
  <a val="2"/>
  <a val="3.5"/>
</root>

Invalid document
Because the "val" attribute is "decimal", there is duplicate value (1 = 1.0), which is not allowed.


<root xmlns="">
  <a val="1"/>
  <a val="1.0"/>
  <a val="2"/>
</root>

Correct Relax NG schema (correctRelax_0.rng)
This Relax NG will check tree structure, and verify the datatypes.


<grammar datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes" ns="" xmlns="http://relaxng.org/ns/structure/1.0" >

  <start>
    <element name="root">
      <oneOrMore>
        <element name="a">
          <optional>
            <attribute name="val">
              <data type="decimal"/>
            </attribute>
          </optional>
          <empty/>
        </element>
      </oneOrMore>
    </element>
  </start>
</grammar>

Correct Schematron schema
The Schematron rule below will check the uniqueness of the "a/@val" attribute. We convert the string value to number and then perform the comparison. Warning - not all Schematron implementations might support function "current()" (it's XSLT, not XPath function).


<schema xmlns="http://www.ascc.net/xml/schematron" >
  <pattern name="Element 'a' must have unique 'id' attribute">
    <rule context="root/a/@val">
      <assert test="count(//@val[number(.) = number(current())]) = 1"> Id not unique! </assert>
    </rule>
  </pattern>
</schema>