Search code examples
xmlxsdlibxml2dtd

Libxml2 won't validate a document with XSD, only with DTD. Why? What do the standards say?


Note, validation is a different thing than well-formedness. Well-formedness means a syntactically correct XML document.

Validity is a narrower thing: it also requires the document to pass a criteria specific the format of the document.

My research has shown that there are two standards for the XML validation: DTD and XSD. While DTD belongs to an XML document, XSD belongs to an XML tag. Obviously, it can be set up also on the root tag of an XML document, like so:

<?xml version="1.0" encoding="utf-8"?>
<RootTag xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:noNamespaceSchemaLocation="./example.xsd">
   <!-- ... -->
</RootTag>

Logic would dictate that the following C++ code, reading and validating the document, should work:

int main(int argc, char* argv[]) {
  try {
    xmlpp::DomParser parser;
    parser.set_validate();
    parser.set_substitute_entities(); //We just want the text to be resolved/unescaped automatically.
    parser.parse_file("example.xml");
    ...
  }
  catch(const std::exception& ex) {
    std::cout << "Exception caught: " << ex.what() << std::endl;
  }
  return 0;
}

However, it doesn't happen. The code faults with

Exception caught: 
Validity error:
File example.xml, line 2, column 111 (error):
Validation failed: no DTD found !

It looks to me, that libxml++ wants to somehow validate exclusively by DTD. An analog XML file, but using a DTD validator, works without any problem.

Why? Can I validate whole XML documents by XSD? This is a limitation of the libxml2, I missed something in the libxml2 documentation, or simply it is the standard?

For validating documents, I would prefer XSD, but also DTD validation is okay, if that is the standard (on some reason).


Solution

  • In order to validate using a schema (XSD), you need to prepare a xmlpp::XsdValidator object and use that to validate your XML.

    Example preparation of validator:

    xmlpp::DomParser schema;
    schema.parse_file("example.xsd");
    
    xmlpp::XsdValidator validator;
    validator.parse_document( schema.get_document() );
    

    Example usage of validator:

    try {
      xmlpp::DomParser parser;
      parser.parse_file("example.xml");
      validator.validate( parser.get_document() );
      // Use the validated XML...
    }
    
    catch(const xmlpp::exception &e) {
      std::cerr << "Went wrong: " << e.what() << std::endl;
    }