Validating XML: No matching global declaration available for the validation root

Matt picture Matt · Jun 17, 2009 · Viewed 16.2k times · Source

I'm trying to validate the following XML against a XSD schema using Ruby. It simply won't work, stops with an error message telling me

Error: Element 'request': No matching global declaration available for the validation root.

Maybe it's the namespace? Any ideas?

XML

<?xml version="1.0" encoding="UTF-8"?>
<request type="test" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <channel name="channel">
    <username>user</username>
    <password>pass</password>
  </channel>

  <hotel id="1">
    <date from="2009-07-07" to="2009-07-17"/>
    <room id="1">
      <allocation>10</allocation>
    </room>
  </hotel>
</request>   

XSD

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

  <!-- channel -->
  <xsd:element name="channel">
    <xsd:attribute name="name" use="required" type="xsd:string" />
    <xsd:sequence>
      <xsd:element username="name" use="required" type="xsd:string"/>
      <xsd:element password="country" use="required" type="xsd:string"/>
    </xsd:sequence>
  </xsd:element>

  <!-- hotel -->
  <xsd:element name="hotel">
    <xsd:attribute name="id" use="required" type="xsd:string" />
    <xsd:sequence>
      <xsd:element name="hotel">
        <xsd:attribute name="from" use="required" type="xsd:string" />
        <xsd:attribute name="to" use="required" type="xsd:string" />
      </xsd:element>
      <xsd:element ref="room" minOccurs="1"/>
    </xsd:sequence>
  </xsd:element>


  <!-- room -->
  <xsd:element name="room">
    <xsd:sequence>
      <xsd:element name="allocation" type="xsd:string"></xsd:element>
      <xsd:element ref="hotel" minOccurs="1"/>
    </xsd:sequence>
    <xsd:attribute name="id" use="required" type="xsd:string" />
  </xsd:element>

  <!-- building all together -->
  <xsd:element name="request">
    <xsd:attribute name="type" use="required" type="xsd:string" />
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element ref="channel" maxOccurs="1"/>
        <xsd:element ref="hotel" maxOccurs="1"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>

Ruby code

require "xml"

document = LibXML::XML::Document.file("/tmp/test.xml")
schema = LibXML::XML::Document.file("/tmp/request.xsd")

result = document.validate_schema(schema) do |message,flag|
  log.debug(message)
  puts message
end

Answer

Pesto picture Pesto · Jun 17, 2009

It's a cryptic error, but it's probably because your XSD is malformed. For example, the contents of the channel, hotel (both the inner and outer elements), room, and request xsd:element tags should all be wrapped in xsd:complexType tags. Also, use is only valid on xsd:attribute, not xsd:element. For elements, use minOccurs and maxOccurs (although both default to 1, so they aren't actually necessary in this case). In addition, your outer hotel element contains a room element, which must contain a hotel element, creating an infinite loop. Further, you don't name your username and password elements properly. Finally, that inner hotel element should probably be date. Here's what I think you're looking for:

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

  <!-- channel -->
  <xsd:element name="channel">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="username" type="xsd:string"/>
        <xsd:element name="password" type="xsd:string"/>
      </xsd:sequence>
      <xsd:attribute name="name" use="required" type="xsd:string" />
    </xsd:complexType>
  </xsd:element>

  <!-- hotel -->
  <xsd:element name="hotel">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="date">
          <xsd:complexType>
            <xsd:attribute name="from" use="required" type="xsd:string" />
            <xsd:attribute name="to" use="required" type="xsd:string" />
          </xsd:complexType>
        </xsd:element>
        <xsd:element ref="room" minOccurs="1"/>
      </xsd:sequence>
      <xsd:attribute name="id" use="required" type="xsd:string" />
    </xsd:complexType>
  </xsd:element>


  <!-- room -->
  <xsd:element name="room">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="allocation" type="xsd:string"></xsd:element>
      </xsd:sequence>
      <xsd:attribute name="id" use="required" type="xsd:string" />
    </xsd:complexType>
  </xsd:element>

  <!-- building all together -->
  <xsd:element name="request">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element ref="channel" maxOccurs="1"/>
        <xsd:element ref="hotel" maxOccurs="1"/>
      </xsd:sequence>
    <xsd:attribute name="type" use="required" type="xsd:string" />
    </xsd:complexType>
  </xsd:element>
</xsd:schema>