xsi:noNamespaceSchemaLocation="gobitan.xsd">
Tom
Jones
*********************************************************************
[执行校验的schema文档:gobitan.xsd ]
*********************************************************************
*********************************************************************
[源代码:gobitan.cpp ]
*********************************************************************
#include
#include
#include
#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文档中的Tom下一行中加入
Tom
那么再执行上面的程序,系统就会报校验错误,并打印出如下所示的错误提示:
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
然后在加载xml和schema的地方换成* pXsdMemBufIS就可以了。
本文写的时间仓促,若有不妥之处欢迎指正!