`
java-mans
  • 浏览: 11468414 次
文章分类
社区版块
存档分类
最新评论

关于Xerces-C++执行schema校验相关问题的详细解答

 
阅读更多

转自:作者: 胡家辉/雨水 转载请注明出处:http://blog.csdn.net/gobitan


采用Xerces-C++对XML进行schema校验,这个在项目中应用还是比较多,目前我自己的所在的项目就有应用,它能确保XML文档满足业务的各种规则约束。大家可能比较关心,如果校验失败,如何查看错误信息,也就是如何看到失败的原因,以便对XML文档进行修正。
还有一点,我想也这里介绍一下。在前面的文章中,我介绍了对XML进行校验时直接从文件系统加载XML文档和XSD文档,但是实际项目中处于性能考虑往往是从某个内存空间进行加载,因此这里还将介绍一种从内存加载文档的方法。
最能说明问题的还是代码,为了保持完整性,我把上篇文章中用到的XML文档和schema文档实例在这里还是贴出来一下。
[被校验的XML文档:gobitan.xml ]

<?xml version="1.0" encoding="UTF-8"?>
<phonebook xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="gobitan.xsd">
 <name>
    <first>Tom</first>
    <last>Jones</last>
 </name>
<phone type="home">420-203-2032</phone>
</phonebook>
[执行校验的schema文档:gobitan.xsd ]

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xs:element name="phonebook">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="name" minOccurs="1" maxOccurs="1">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="first" type="xs:string"/>
              <xs:element name="last" type="xs:string"/>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
        <xs:element name="phone" minOccurs="0" maxOccurs="unbounded">
          <xs:complexType>
            <xs:simpleContent>
              <xs:extension base="xs:string">
                <xs:attribute name="type" type="xs:string"/>
              </xs:extension>
            </xs:simpleContent>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
 </xs:element>
</xs:schema>

[源代码:gobitan.cpp ]

#include <stdio.h>
 
#include<xercesc/sax2/XMLReaderFactory.hpp>
#include <xercesc/util/OutOfMemoryException.hpp>
#include "SAX2PrintHandlers.hpp"
 
XERCES_CPP_NAMESPACE_USE
 
int main( int argc , char** argv )
{
    //系统初始化
    try
    {
           XMLPlatformUtils::Initialize();
    }
    catch (const XMLException &xe)
    {
           printf("%s", (const char*)xe.getMessage());
          
           return -1;
    }
 
    // 创建解析器
    SAX2XMLReader* parser = XMLReaderFactory::createXMLReader();
 
    //设置名称空间属性, 如果没有如下两行则忽略名称空间 及名称空间前缀
    parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, true);
    parser->setFeature(XMLUni::fgSAX2CoreNameSpacePrefixes, true);
 
    //设置验证属性
    parser->setFeature(XMLUni::fgXercesValidationErrorAsFatal, true);
    parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
    parser->setFeature(XMLUni::fgXercesSchema, true);
    parser->setFeature(XMLUni::fgXercesSchemaFullChecking, true);
 
    //加载XSD文件
    parser->loadGrammar ("gobitan.xsd", Grammar::SchemaGrammarType, true);
    parser->setFeature (XMLUni::fgXercesUseCachedGrammarInParse, true);
   
    try
    {
           //定义打印对象
           SAX2PrintHandlers handler("UTF-8", XMLFormatter::UnRep_CharRef, false);
       
           //设置内容打印函数: 如果没有这行,则不打印出XML文档内容
        parser->setContentHandler(&handler);
 
           //设置错误打印函数: 如果没有这行,则不打印错误信息
        parser->setErrorHandler(&handler);
 
           //解析并验证XML文档
          parser->parse("gobitan.xml");
    }
    catch (const OutOfMemoryException &ome)
    {
            printf("%s", (const char*)ome.getMessage());
    }
    catch (const XMLException &xe)
    {
            printf("%s", (const char*)xe.getMessage());
    }
 
    printf("Error count: %d/n", parser->getErrorCount());
   
    delete parser;
 
    XMLPlatformUtils::Terminate();
   
    return 0;
   
}

下面对上面的代码进行解释和说明,源代码可分为六个部分:
(1)系统初始化,代码如下
XMLPlatformUtils::Initialize(); //主要完成Xerces系统的初始化工作
(2)创建解析器
SAX2XMLReader* parser = XMLReaderFactory::createXMLReader();
其实Xerces不只这一种方式,这里暂不深究。
(3)解析器属性设置:这是介绍的重点之一
parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, true);
如果将这项属性设置为true,那么该解析器就支持名称空间,否则忽略。
parser->setFeature(XMLUni::fgSAX2CoreNameSpacePrefixes, true);
如果将这项属性设置为true,那么该解析器就支持名称空间前缀,否则忽略。
parser->setFeature(XMLUni::fgXercesValidationErrorAsFatal, true);
这是一个非常重要的属性,正如fgXercesValidationErrorAsFatal名字的含义一样,如果该属性设置为true,那么当解析器执行校验时,将校验错误看作是致命的,系统就停止解析。
如果该属性设置为false,那么无论遇到多少个校验错误,系统都回执行完毕,如果设置了打印函数,那么系统会将所有的校验错误一一列出。
(4)加载schema文件
parser->loadGrammar ("gobitan.xsd", Grammar::SchemaGrammarType, true);
这是加载schema文档,这里就不多说。
parser->setFeature (XMLUni::fgXercesUseCachedGrammarInParse, true);
这是设置缓存属性,是否缓存加载的schema内容。
(5)设置打印函数
注意,这个打印函数是Xerces自带的,当你下载的是xerces-c_2_7_0-windows_2000-msvc_60.zip文件时,解压后/xerces-c-windows_2000-msvc_60/samples/SAX2Print目录下有一个SAX2PrintHandlers文件,它定义了该打印函数。
然后分别设置内容打印和错误打印,如下:
parser->setContentHandler(&handler);
如果不设置这项,那么系统解析时就不打印解析的内容。
parser->setErrorHandler(&handler);
如果不设置这项,那么schema的校验错误就不会打印出来,所以这句很关键。
(6)最后就是执行解析和校验。
注意:上面凡是有设置true的地方,系统的默认值均为false,也就说当你设置为false时,该语句可以省略。
以上程序在VC6.0下编译通过执行,注意上面的如果你下载下去没问题程序执行结果应该是打印出XML文档,并显示校验错误数为0。执行程序时请将xml和schema文件跟工程放在同一级目录,否则文件名应该带有路径。
为了对上面对的程序有较为深入的认识,请在XML文档中的<first>Tom</first>下一行中加入
<mid>Tom</mid>
那么再执行上面的程序,系统就会报校验错误,并打印出如下所示的错误提示:
Error at file D:/MyPrj/xml/gobitan.xml, line 6, char 10
Message: Unknown element 'mid'
因为在schema文件中没有定义mid这个元素,因此校验时就会报错。这样你就可以根据错误提示对你的XML文档进行修正。
下面介绍如何从内存中加载xm和schema文件。Xerces提供了一个内存构造器MemBufInputSource,可以从内存中构造数据源。
*******************************************************************
/* 创建Xml数据源 */
MemBufInputSource *pXmlMemBufIS = new MemBufInputSource(
(const XMLByte*)pcXmlDoc,
(const unsigned int)strlen(pcXmlDoc),
g_cXmlBufferId);
/*创建XSD数据源 */
MemBufInputSource *pXsdMemBufIS = new MemBufInputSource(
(const XMLByte*)pcSchema,
(const unsigned int)strlen(pcSchema),
g_cXsdBufferId);
*******************************************************************
上面的pcXmlDoc和pcSchema分别是存放xml和schema文件的内存区域,g_cXmlBufferId是定义的一个ID,可以随意定义一个,如http://www.hujiahui.cn均可。
如果使用上面的方式,还需要加入头文件如下:
#include <xercesc/framework/MemBufInputSource.hpp>
然后在加载xml和schema的地方换成* pXsdMemBufIS就可以了。


分享到:
评论

相关推荐

    Xerces-J-tools.2.11.0-xml-schema-1.1-beta.zip下载

    Xerces-J-tools.2.11.0-xml-schema-1.1-beta.zip为apache开源xml相关,可用于xml解析 Xerces是由Apache组织所推动的一项XML文档解析开源项目,它目前有多种语言版本包括JAVA、C++、PERL、COM等。[1] Xerces是一个...

    xerces-c++-3.1.3

    IBM 将这两个项目的源代码让与 Apache 软件基金会(Apache Software Foundation),他们将其分别改名为 Xerces-C++ 和 Xerces-J。注:“Xerces-C”和“Xerces-C++”是同一个东西。 Xerces是一个与可扩展标记语言(XML...

    Xerces-c++指南

    Xerces-c++指南

    xerces-c-3.2.3.zip

    xerces-c-3.2.3的64位库,由VS 2015编译而成。Xerces是由Apache组织所推动的一项XML文档解析开源项目,它目前有多种语言版本包括JAVA、C++、PERL、COM等。

    xerces-c-3.0.0-x86_64-windows-vc-9.0.rar

    xerces-c-3.0.0 编译好的库,可以直接... 这两个项目是 Apache XML 组的核心项目(如果看到的是“Xerces-C”而不是“Xerces-C++”,也是同一个东西,因为这个项目一开始就是用 C(译者注:原文为C++)语言编写的)。

    Xerces-xml-schema

    Xerces-J-tools.2.11.0-xml-schema-1.1-beta.zip为apache开源xml相关,可用于xml解析

    Xerces-C++

    Xerces-C++ XML解析Xerces-C++ Xerces-C++ DOM编程指南

    xerces-c-3.2.3.tar.gz

    Apache Xerces-C validating XML parser Releases文件,下载下来可以直接使用

    d2school-Xerces-C++编译库part01

    Xerces-C++ (通常也称为:Xerces-C)是一套健壮、强大(同时也很庞大)的 XML 解析库,它提供了验证,以及 SAX 和 DOM API。来源:http://www.d2school.com/

    d2school-Xerces-C++编译库part02

    Xerces-C++ (通常也称为:Xerces-C)是一套健壮、强大(同时也很庞大)的 XML 解析库,它提供了验证,以及 SAX 和 DOM API。来源:http://www.d2school.com/

    demo_of_xerces-c++_MemoryManagement

    抽取xerces-c++内存管理部分代码+可作为学习demo使用。

    xerces src_2_8_0

    XML4C 和 XML4J 是两个并列的项目,IBM 将这两个项目的源代码让与 Apache 软件基金会,他们将其分别改名为 Xerces-C++ 和 Xerces-J。这两个项目是 Apache XML 组的核心项目。 Xerces-C++是一个非常健壮的 XML 解析器...

    MacOS:Xerces

    Xerces-C++ is a validating XML parser written in a portable subset of C++. Xerces-C++ makes it easy to give your application the ability to read and write XML data. A shared library is provided for ...

    xerces-2.6.2.jar

    xerces-2.6.2.jar xerces-2.6.2.jar

    xerces-c-3.1.1-x86-windows-vc-9.0.zip

    XML解析xerces VS2008使用

    xerces-c-3.1.1

    xerces-c-3.1.1,可编译,用于Ambulant项目。

    xerces-c-3.0.0.zip

    Xerces-C++ is a validating XML parser written in a portable subset of C++. Xerces-C++ makes it easy to give your application the ability to read and write XML data. A shared library is provided for ...

    Xerces-J-bin.2.9.1.zip

    用来处理XML文档的分析器

    xerces-c-src1_7_0.zip

    xerces-c-src1_7_0.zip

Global site tag (gtag.js) - Google Analytics