tags:

views:

2007

answers:

2

Hi

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? I'm desperate. Please help. Thanks!

XML:

<?xml version="1.0" encoding="UTF-8"?>
<request type="test" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
  <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"&gt;

  <!-- 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>

And the ruby piece I use:

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
A: 

Just shooting from the hip here, but have you tried converting the XML::Document holding the schema into an XML::Schema?

http://libxml.rubyforge.org/rdoc/classes/LibXML/XML/Schema.html

I don't know that it would make a difference, but it's worth a shot.

Ben Hughes
+3  A: 

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"&gt;

  <!-- 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>
Pesto
That's it. Guess I was too tired when I wrote the XSD. Thanks for you help!
Matt
Pesto - Thank you very much for your response. I received the same error as Matt and had trouble diagnosing the root cause. Your post made a great deal of sense and got me past this issue. Thank you.
Elliot