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

原创 2007年10月09日 18:37:00
 

*****************************************************

作者: 胡家辉/雨水转载请注明出处:http://www.hujiahui.cn

*****************************************************

小插曲: 前面我写了一篇名为《采用Xerces C++执行基于schema的XML文档校验》的文章放在我CSDN的BLOG上,当时只是为了简单地介绍了这个功能,没有对其相关的东西做详细的介绍。后来发现关注这篇文章的朋友还很多,不少朋友还发来邮件,让我感到很欣慰。其中也有来自国家应用软件产品质量监督检验中心的朋友。

为了更好的与更多的朋友交流这方面的技术问题,这里我对采用Xerces-C++执行基于schema的XML校验的相关问题做一个较为详细的介绍,欢迎大家评论交流!

*****************************************************

正文开始

*****************************************************

    采用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-c来进行xml schema校验

在xerces-c的官方网站上有文章指引说明是如何进行xml schema校验。http://xerces.apache.org/xerces-c/schema-3.html 给出的例子代码: /...
  • xuzhina
  • xuzhina
  • 2015年07月10日 10:24
  • 2391

Spark 和hadoop的一些面试题(准备)

Spark
  • qiezikuaichuan
  • qiezikuaichuan
  • 2016年06月03日 14:55
  • 14725

常见的计算机网络面试题目

1、OSI(Open System Interconnect):开放系统互联,是一个七层的计算机网络模型,分别为:物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。 TCP/IP(Tran...
  • zhang434
  • zhang434
  • 2014年04月27日 14:32
  • 3187

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

转自:作者: 胡家辉/雨水 转载请注明出处:http://blog.csdn.net/gobitan 采用Xerces-C++对XML进行schema校验,这个在项目中应用还是比较多...
  • w174504744
  • w174504744
  • 2012年05月09日 11:39
  • 1972

Xerces-C++ SAX2 Schema校验

经过几天的研究,终于完成了XML的SAX2 Schema校验。   关于什么是Schema校验,在这里就不废话了,可以去google一下。  下面我就把整个的过程写一下。 借用网上的一些XML文件...
  • wasb001
  • wasb001
  • 2013年10月11日 09:49
  • 838

xerces-c 解析xml schema

一:方法名 方法说明  Void SetDoSchema(const bool newState ) 设置Parser是否处理xml文档中的schema,如果为true,则Parser还要处理xml...
  • w174504744
  • w174504744
  • 2012年05月17日 10:44
  • 1702

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

  • 2017年12月17日 19:20
  • 6.36MB
  • 下载

Xerces-xml-schema

  • 2012年01月09日 17:05
  • 7.69MB
  • 下载

icpc讲义,详细描述C++各种问题的解答

  • 2010年06月23日 19:38
  • 1.41MB
  • 下载

Xerces C++ 学习笔记

1.   初始化平台: XMLPlatformUtils::Initialze() 2.   销毁平台: XMLPlatformUtils::Terminate(); 3.  ...
  • u012719556
  • u012719556
  • 2013年11月19日 08:23
  • 965
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于Xerces-C++执行schema校验相关问题的详细解答
举报原因:
原因补充:

(最多只允许输入30个字)