Search code examples
c++xerces

Xerces XML validation with XSD


I try to validate XML file using a given XSD grammar file. But for now it always return error saying no declaration found for element ... and that for each element or attribute I have in my XML file.

To create the XSD i used that Free online XSD generator and if I check my xml within that XSD using the (Validator)[http://www.freeformatter.com/xml-validator-xsd.html] on the same site, everything looks fine.

So why Xerces fails ?

I use the following code to validate:

      XercesDOMParser domParser;
      if (domParser.loadGrammar(schemaFilePath.c_str(), Grammar::SchemaGrammarType) == NULL)
      {
        throw Except("couldn't load schema");
      }

      ParserErrorHandler parserErrorHandler;

      domParser.setErrorHandler(&parserErrorHandler);
      domParser.setValidationScheme(XercesDOMParser::Val_Always);
      domParser.setDoNamespaces(true);
      domParser.setDoSchema(true);
      domParser.setValidationSchemaFullChecking(true);

      domParser.parse(xmlFilePath.c_str());
      if(domParser.getErrorCount() != 0)
      {     
        throw Except("Invalid XML vs. XSD: " + parserErrorHandler.getErrors()); //merge a error coming from my interceptor ....
      }

My XML test file is:

<?xml version="1.0" encoding="UTF-8" ?>
<schemes signature="9fadde05">
    <!-- NOTE: Do not modify this file. 
     Any modifications will invalidate the signature and result in an invalid file! 
     This is an example scheme, param_set etc... can be rename / market or / product
    -->
    <scheme>
        <name>test1</name>
        <other>test2</other>
    </scheme>
    <param_set>
        <input>
            <height min="1060" max="1100" />
            <width min="1900" max="1940" />
        </input>
    </param_set>
</schemes>

And the XSD I use is:

<xs:schema attributeFormDefault="qualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="schemes">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="scheme">
          <xs:complexType>
            <xs:sequence>
              <xs:element type="xs:string" name="name"/>
              <xs:element type="xs:string" name="other"/>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
        <xs:element name="param_set">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="input">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="height">
                      <xs:complexType>
                        <xs:simpleContent>
                          <xs:extension base="xs:string">
                            <xs:attribute type="xs:short" name="min"/>
                            <xs:attribute type="xs:short" name="max"/>
                          </xs:extension>
                        </xs:simpleContent>
                      </xs:complexType>
                    </xs:element>
                    <xs:element name="width">
                      <xs:complexType>
                        <xs:simpleContent>
                          <xs:extension base="xs:string">
                            <xs:attribute type="xs:short" name="min"/>
                            <xs:attribute type="xs:short" name="max"/>
                          </xs:extension>
                        </xs:simpleContent>
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
      <xs:attribute type="xs:string" name="signature"/>
    </xs:complexType>
  </xs:element>
</xs:schema>

Solution

  • I solve that issue the following code, and I think the setExternalNoNamespaceSchemaLocation is the trick. Note that I had also to rebuild an absolute path for the XSD.

        XMLPlatformUtils::Initialize();
        {
          XercesDOMParser domParser;
          bfs::path pXSD = absolute(schemaFilePath);      
          if (domParser.loadGrammar(pXSD.string().c_str(), Grammar::SchemaGrammarType) == NULL)
          {
            throw Except("couldn't load schema");
          }
    
          ParserErrorHandler parserErrorHandler;
    
          domParser.setErrorHandler(&parserErrorHandler);
          domParser.setValidationScheme(XercesDOMParser::Val_Always);
          domParser.setDoNamespaces(true);
          domParser.setDoSchema(true);
          domParser.setValidationSchemaFullChecking(true);
    
          domParser.setExternalNoNamespaceSchemaLocation(pXSD.string().c_str());
    
          domParser.parse(xmlFilePath.c_str());
          if(domParser.getErrorCount() != 0)
          {     
            throw Except("Invalid XML vs. XSD: " + parserErrorHandler.getErrors()); //merge a error coming from my interceptor ....
          }
        }
        XMLPlatformUtils::Terminate();