Xerces XML validation with XSD

Xerces XML validation with XSD

本文关键字:XSD with validation XML Xerces      更新时间:2023-10-16

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

为了创建XSD,

我使用了免费的在线XSD生成器,如果我在同一站点上使用(验证器)[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>

我用以下代码解决了这个问题,我认为setExternalNoNamespaceSchemaLocation就是诀窍。请注意,我还必须为 XSD 重建absolute路径。

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

只是在这里为可能遇到一些麻烦的其他人留下一些信息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(...);