6

I'm trying to validate the uniquess of an attribute across all elements that exist in an XML document.

Example XML:

<exampleXml>
  <a id="1"/>
  <a id="2">
    <b id="1"/>
  </a>
</exampleXml>

My XSD schema:

<xs:schema elementFormDefault="qualified">
  <xs:element name="exampleXml">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="unbounded" name="a">
          <xs:complexType>
            <xs:complexContent>
              <xs:extension base="baseRuleType">
                <xs:sequence>
                  <xs:element minOccurs="0" maxOccurs="1" name="b">
                    <xs:complexType>
                      <xs:complexContent>
                        <xs:extension base="baseRuleType"/>
                      </xs:complexContent>
                    </xs:complexType>
                  </xs:element>
                </xs:sequence>
              </xs:extension>
            </xs:complexContent>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
    <xs:unique name="duplicateIdsForbidden">
      <xs:selector xpath="//"/>
      <xs:field xpath="@id"/>
    </xs:unique>
  </xs:element>
  <xs:complexType name="baseRuleType">
    <xs:attribute name="id" use="optional"/>
  </xs:complexType>
</xs:schema>

The xpath is the issue here. I want to match every element under root but the selector xpath above returns:

Element '{http://www.w3.org/2001/XMLSchema}selector', attribute 'xpath': 
The XPath expression '//' could not be compiled

I can change the xpath to "*" but that will only validate the id attribute on the elements that are direct decendants of the root.

I am validating this with lib_xml in PHP using DOMDocument::schemaValidate(). Any help greatly appreciated.

Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • 1
    why dont you just set the attribute type to ID or use xml:id for the ID attribute? That would enforce uniqueness automatically. The IDs cannot be numeric then though, but NCNames. – Gordon Jul 15 '11 at 13:04
  • 'I can change the xpath to `*` but that will only validate the id attribute on the elements that are direct decendants of the root.' I think you mean '... that are direct *children* of the top-level element', right? – LarsH Jul 16 '11 at 03:02

1 Answers1

8

Use <xs:selector xpath=".//*"/>.

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
  • 1
    Yes. To elaborate on this, `//` is equivalent to `/descendant-or-self::node()/`. Since it ends with a slash, it is not a complete XPath expression. (The exception is `/` itself.) – LarsH Jul 16 '11 at 03:06
  • 1
    @Gordon @LarsH thanks guys, learnt a couple of things there that I didn't know. – Peter Chapman Jul 17 '11 at 13:18