Xerces 4 and XML Schema 1.1 validation

Robert Hairgrove <[email protected]>
Newsgroups gmane.text.xml.xerces-c.devel
Message-ID <[email protected]>
The platforms I am using are Linux Ubuntu 18.04 with GCC 7.50 and 
Windows 10. My C++ application (built with Qt libraries 5.15.5 for 
Windows and Linux) links to Xerces-C++ as a library and performs 
validation on a XML file used to configure the importing of CSV text 
files against an embedded XSD schema file. Having used this setup with 
Xerces-C++ version 3.2.3 and the XSD file formatted for XML Schema 1.0, 
it works very well. The import of the data is done using the opensource 
"libcsv" library (located on GitHub: https://github.com/rgamble/libcsv), 
and I am performing validation on a per-field basis in the callback 
function  using the configuration from the XML file which validates, 
among other things, against regular expressions and minimum/maximum 
values, etc.

Now the documentation for Xerces-C++ states that validation with XML 
Schema 1.1 is possible. I downloaded the sources for the latest version 
from GitHub (Xerces version = 4.0.0) and built my application using 
that. It appears that even now, one of the most useful new features of 
XML Schema 1.1 (assertions) is not working quite the way it should.

I have attached a minimal test case of what I am trying to do: CSV files 
can have column headers in their first line, or maybe not. So I have two 
sets of column definitions, one for files with headers, and one for 
headerless files. The <col> elements in the first set have a 'name' 
attribute, which is the column header; the elements in the second set 
have an 'ord' attribute which is basically just a sequential integer 
telling the application in which order the column appears in the file. 
So I cannot define the 'use' attribute in the XSD as "required" for 
either attribute, but I wanted to add '<xs:assert 
test="exists(@name|@ord)/>' after the list of <col> attributes, as you 
can see from the attached example.

I tested this on the site mentioned in the Apache website for Xerces-C++ 
at https://www.softwarebytes.org/xmlvalidation/. It seems to work quite 
well; when I remove one of the "ord" attributes so that neither "name" 
nor "ord" appears, I get a validation error: "Assertion evaluation 
('exists(@name|@ord)') for element 'col' on schema type 
'#AnonType_colcolumnsimportfileroot' did not succeed." When I put it 
back, it says it is valid.

On Xerces-C++ 4.0.0, using the same files, it throws no errors, neither 
with the apparently valid XML nor the faulty one with the missing "ord" 
attribute. I am using the Xerces SAX2XMLReader with both XML and XSD 
passed in a memory buffer. However, I might be setting it up wrong? Here 
is the relevant part of my parsing code (I left out the code for the 
error handler which is correctly implemented; you can refer to the Qt 
documentation for the QByteArray and QIODevice classes which set up the 
buffers from the data in the file):

<snip>

   // fi_xsd and fi_xml are of type QFileInfo:
   bool retval = false;

   QFile schema(fi_xsd.absoluteFilePath());
   QFile xmlfile(fi_xml.absoluteFilePath());
   QByteArray ba_xsd, ba_xml;
   if (schema.open(QIODevice::ReadOnly)) {
     ba_xsd = schema.readAll();
     schema.close();
   }
   if (xmlfile.open(QIODevice::ReadOnly)) {
     ba_xml = xmlfile.readAll();
     xmlfile.close();
   }

   try {
     xercesc::SAX2XMLReader *parser = 
xercesc::XMLReaderFactory::createXMLReader();
     xercesc::ErrorHandler *handler = new CErrorHandler();

     xercesc::MemBufInputSource 
inMemorySchemaSource(reinterpret_cast<const 
XMLByte*>(ba_xsd.constData()), ba_xsd.size(), "/schema.xsd");
     xercesc::MemBufInputSource inMemoryXMLSource(reinterpret_cast<const 
XMLByte*>(ba_xml.constData()), ba_xml.size (), "/xml.xsd");

     parser->loadGrammar(inMemorySchemaSource, 
xercesc::Grammar::SchemaGrammarType, true);
parser->setFeature(xercesc::XMLUni::fgXercesUseCachedGrammarInParse, true);
     parser->setFeature(xercesc::XMLUni::fgSAX2CoreValidation, true);
     parser->setFeature(xercesc::XMLUni::fgSAX2CoreNameSpaces, true);
parser->setFeature(xercesc::XMLUni::fgXercesSchemaFullChecking, true);
parser->setProperty(xercesc::XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation, 
const_cast<void*>(static_cast<const void*>("")));
     parser->setErrorHandler(handler);
     parser->parse(inMemoryXMLSource);

     if (parser->getErrorCount() != 0) {
       std::cout << "ERROR: XML file '" << xml_file_path_ << "' does not 
conform to the schema" << std::endl;
     } else {
       std::cout << "Valid!" << std::endl;
       retval = true;
     }
   }
   catch (const xercesc::SAXParseException &) {
     std::cout << "Unhandled SAXParseException was caught" << std::endl;
   }
   catch (const xercesc::SAXException &) {
     std::cout << "Unhandled SAXException was caught" << std::endl;
   }

   return retval;

</snip>

In addition to the bits one has to add to the <xs:schema> element, is 
there anything else I have to do to turn on 1.1 validation in Xerces?
Thank you.


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
my_schema.xsd (application/xml, 2.7 KB) - not displayed
my_test.xml (text/xml, 912 B)
<?xml version="1.0" encoding="UTF-8"?>
<root xsi:noNamespaceSchemaLocation="./my_schema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <importfile linebreaks="CRLF" quotes="true" delimiter="SEMICOLON" maptable="professions_import" type="proflist" mimetype="text/csv" quotechar="DQ">
    <columns columnheaders="true">
      <col strict="true" name="ID" ignore="false" regexp="XGR7MSwyfQ==" max="63" min="1" type="uint" mapcolumn="id"/>
      <col strict="false" name="Description" maxlen="255" ignore="false" regexp="W1xkXXsxLDJ9XHNcUys=" type="string" mapcolumn="descr"/>
    </columns>
    <columns columnheaders="false">
      <col strict="true" ignore="false" regexp="XGR7MSwyfQ==" max="63" min="1" type="uint" mapcolumn="id"/>
      <col maxlen="255" strict="false" ord="2" ignore="false" regexp="W1xkXXsxLDJ9XHNcUys=" type="string" mapcolumn="descr"/>
    </columns>
  </importfile>
</root>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.