使用XSD对Xerces进行XML验证

时间:2014-02-25 13:28:45

标签: c++ xerces

我尝试使用给定的XSD语法文件验证XML文件。但是现在它始终返回错误no declaration found for element ...,而且我的XML文件中的每个元素或属性都有错误。

要创建我使用Free online XSD generator的XSD,如果我使用(Validator)[http://www.freeformatter.com/xml-validator-xsd.html]在该XSD中检查我的xml同一个网站,一切都很好。

为什么Xerces会失败?

我使用以下代码进行验证:

      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 ....
      }

我的XML测试文件是:

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

我使用的XSD是:

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

2 个答案:

答案 0 :(得分:4)

我在下面的代码中解决了这个问题,我认为setExternalNoNamespaceSchemaLocation就是诀窍。请注意,我还要为XSD重建absolute path

    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();

答案 1 :(得分:0)

只需在此处留一些信息,供其他可能因xercesc遇到麻烦的人使用。

问题作者提供的解决方案很有用,但可能不适用于您的情况。 首先,如果您使用setExternalSchemaLocation,则不需要loadGrammar

第二,如果您的架构处理名称空间,则也尝试setExternalSchemaLocation

我的代码:

xmlParser = std::make_unique<xercesc::XercesDOMParser>();
std::string xsdPath = "http://your.namespace.com path/to/schema.xsd";

xmlParser->setValidationScheme(xercesc::XercesDOMParser::Val_Always);
xmlParser->setDoNamespaces(true);
xmlParser->setDoSchema(true);
xmlParser->setValidationSchemaFullChecking(true);

//Finally...
xmlParser->setExternalSchemaLocation(xsdPath.c_str());

请注意,没有调用loadGrammar。另外,请注意,xercesc在您调用之前不会尝试解析模式

xmlParser->parse(...);