【问题标题】:Xerces XML validation with XSD使用 XSD 进行 Xerces XML 验证
【发布时间】:2014-03-27 18:17:59
【问题描述】:

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

要创建 XSD,我使用了 Free online XSD generator,如果我在同一站点上使用 (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>

【问题讨论】:

  • 简而言之,可能的解决方法是使用 DOMLSParser,如 link 和博客 link 中所述。但我不知道这个问题的根本原因。另外,我发现了两个可能重复的问题:linklink
  • 谢谢,我会尽快查看这些链接。
  • 重新表述我的答案:简而言之,一种可能的解决方法是使用 DOMLSParser,如 this sample program 中所述,this blog 中所述。但我不知道这个问题的根本原因。另外,我发现了两个可能重复的问题:12

标签: c++ xerces


【解决方案1】:

我用下面的代码解决了这个问题,我认为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();

【讨论】:

    【解决方案2】:

    在这里留下一些信息给其他可能在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(...);
    

    【讨论】:

      猜你喜欢
      • 2011-05-31
      • 2014-01-16
      • 2012-08-24
      • 2012-04-13
      • 2019-02-15
      • 2013-09-02
      • 1970-01-01
      • 2016-10-18
      相关资源
      最近更新 更多