Search code examples
c++xsdxerces-ccodesynthesis

sample XSD fails with "error: no declaration found for element X"


In spite of being a total newbie in the xml parsing arena, I was able to xsd to create valid c++ and compile and link successfully, but the compiler optimized(?) away the instantiation. So, starting at step one, I try the hello world xml example at CodeSynthesis. But that fails:

[wally@lenovotower xml]$ make hello
xsdcxx cxx-tree hello.xsd
g++ -c -o helloschema.o hello.cxx
g++ -g -o hello -lxerces-c helloschema.o hello.c++
[wally@lenovotower xml]$ ./hello
hello.xml:2:8 error: no declaration found for element 'hello'
hello.xml:4:13 error: no declaration found for element 'greeting'
hello.xml:6:9 error: no declaration found for element 'name'
hello.xml:7:9 error: no declaration found for element 'name'
hello.xml:8:9 error: no declaration found for element 'name'

hello.c++:

#include <iostream>
#include <stdio.h>
#include "hello.hxx"
using namespace std;
int main (void)
{
        try {
                auto_ptr<hello_t> h (hello ("hello.xml"));

                for (hello_t::name_const_iterator i (h->name ().begin()); 
                        i != h->name().end();
                        ++i)
                        cout << h->greeting () << ", " << *i << "!" << endl;    
        }
        catch (const xml_schema::exception& e)
        {
                cerr << e << endl;
                return 1;
        }
        return 0;
}

hello.xml:

<?xml version="1.0"?>
<hello>

  <greeting>Hello</greeting>

  <name>sun</name>
  <name>moon</name>
  <name>world</name>

</hello>

hello.xsd:

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

 <xs:complexType name="hello_t">
  <xs:sequence> 
   <xs:element name="greeting" type="xs:string"/>
   <xs:element name="name" type="xs:string" maxOccurs="unbounded"/>
  </xs:sequence>
 </xs:complexType>

 <xs:element name="hello" type="hello_t"/> 

</xs:schema> 

I think this is exactly what it says to do, but the commands don't work exactly as documented. I discovered xsdcxx seems to do the right thing (unlike xsd which generates C# or vb.net output).

[wally@lenovotower xml]$ xsdcxx --version
CodeSynthesis XSD XML Schema to C++ compiler 3.3.0
Copyright (C) 2005-2010 Code Synthesis Tools CC

Also, I don't include an -I(dir) and it compiles happily. Could it be using the wrong include file somehow?

What am I doing wrong? Maybe xsd isn't the right tool?


Solution

  • Personally I find the combination of Python and lxml to be pretty invaluable. Your XML document and the corresponding XML schema work just fine:

    from lxml import etree
    
    xsddoc = etree.parse('hello.xsd')
    xsd = etree.XMLSchema(xsddoc)
    xml_parser = etree.XMLParser(schema=xsd)
    xmldoc = etree.parse('hello.xml', parser=xml_parser)
    

    I didn't get any errors from that. I will say, however, that even though lxml doesn't require you to use xsi:noNamespaceSchemaLocation since it loads the schema you specify, you should still use it as long as you're not using namespaces. Just because one XML parser is flexible, others might not be, a fact that it seems you might have figured out the hard way. If you do use namespaces, use xsi:schemaLocation instead of xsi:noNamespaceSchemaLocation. Also note that you MUST declare the xsi namespace via the xmlns:xsi attribute to be able to use the xsi:* attributes.

    An example using xsi:noNamespaceSchemaLocation:

    <hello xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:noNamespaceSchemaLocation="hello.xsd">
      ...
    </hello>