barbara.post
barbara.post

Reputation: 1661

xsd unique constraint not working

I have a root Inserts tag, a sequence of Inserts tags, each with a "name" attribute.

I cannot get online validator to find out that there are duplicate "name" values.

We've been struggling for... days. Thanks for finding out.

XSD:

   <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.osames.org/osamesorm"
  targetNamespace="http://www.osames.org/osamesorm" elementFormDefault="qualified">

  <xs:element name="Inserts">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="Insert" maxOccurs="unbounded">
              <xs:complexType>
               <xs:simpleContent>
                  <xs:extension base="xs:string">
                    <xs:attribute name="name" type="xs:string" use="required"/>
                  </xs:extension>
                </xs:simpleContent>
              </xs:complexType>
            </xs:element>
          </xs:sequence>
        </xs:complexType>
        <xs:unique name="unique-isbn">
          <xs:selector xpath="Inserts/Insert"/>
          <xs:field xpath="@name"/>
        </xs:unique>
      </xs:element>

</xs:schema>

XML :

<?xml version="1.0" encoding="UTF-8"?>
<Inserts xmlns="http://www.osames.org/osamesorm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.osames.org/osamesorm ./xml_schemas/verysimple.xsd">
<Insert name="BaseInsert">INSERT INTO {0} ({1}) values ({2});</Insert>
<Insert name="BaseInsert">INSERT INTO {0} ({1}) values ({2});</Insert>
</Inserts>

Upvotes: 5

Views: 3194

Answers (1)

O. R. Mapper
O. R. Mapper

Reputation: 20710

There are two problems in your schema:

The first one is that your selector XPath is incorrect, based on the location where you define it. The <xs:unique> element is within an <Inserts> element, yet your XPath reads Inserts/Insert, meaning that within that <Inserts> element, another <Inserts> element is expected, and only therein an <Insert> element.

The <xs:unique> constraint is, however, already within the <Inserts> element, which is why you just need to find the <Insert> element:

<xs:unique name="unique-isbn">
  <xs:selector xpath="Insert"/>
  <xs:field xpath="@name"/>
</xs:unique>

The second issue is that XPath has no notion of the default namespace defined in Xml with the xmlns attribute. The Insert element you refer to in your XPath is not the Insert element from your XSD's default namespace, but an Insert element without a namespace URI.

To deal with that, add a namespace prefix for your namespace (as an alternative to the default namespace) to your XSD file:

  <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.osames.org/osamesorm" targetNamespace="http://www.osames.org/osamesorm" xmlns:o="http://www.osames.org/osamesorm" elementFormDefault="qualified">

Then, use that namespace prefix in your XPath:

<xs:unique name="unique-isbn">
  <xs:selector xpath="o:Insert"/>
  <xs:field xpath="@name"/>
</xs:unique>

With these changes, this validator outputs

There is a duplicate key sequence 'BaseInsert' for the 'http://www.osames.org/osamesorm:unique-isbn' key or unique identity constraint. Line: 1 Column:357

Upvotes: 18

Related Questions