您的位置:首页 > 编程语言 > C语言/C++

c++ 使用xerces读取XML

2015-06-23 00:00 435 查看
XML作为一种重要的文件格式,应用面非常之广。从ASP.NET的web.config,到Android的页面设计开发,Webservice通信等。有时候难免需要我们通过程序进行创建与解析,最近刚完成一个C++项目,就需要读取XML配置文件,关于XML解析器的选择很多,可以参考:http://www.metsky.com/archives/578.html

个人比较喜欢Apache的开源项目,所以使用的是:Xerces。它的使用方法,其实官方上已经有很多demo,详见:http://xerces.apache.org/xerces-c/samples-3.html。个人觉得DOMCount比较实用,下面分享一下我的个人实践。通过DOM方式读取XML中指定节点的属性及文本值。

开发环境:Visual studio 2013

下载源码就不说了,地址:http://apache.dataguru.cn//xerces/c/3/sources/xerces-c-3.1.2.zip,无法下载,可以去http://xerces.apache.org/xerces-c/download.cgi下载。

首先,编译XercesLib工程,得到xerces-c_3_1D.dll,xerces-c_3D.lib两个文件,其次需要在目标工程添加这2个文件,以及相应的头文件,然后是一点配置,接下来就是编码。

下面详细分步进行:

1.VS 2013 打开xerces-c-3.1.2\projects\Win32\VC12\xerces-all\xerces-all.sln



选中XercesLib->右击->编译

2.复制xerces-c-3.1.2\Build\Win32\VC12\Debug文件夹下的xerces-c_3_1D.dll,xerces-c_3D.lib文件到目标工程的编译输出目录下(有编译过一次才有),如:~\ Debug\ 下面。

3.复制xerces-c-3.1.2下的src文件夹到目标工程下。

4.配置include Directories 增加.\src,



配置Dependencies 增加xerces-c_3D.lib,Library Directories 增加$(OutDir)(即编译输出目录)



2-4步是所有调用动态库的通用配置方法,如果明白其中的原理,其实可以灵活配置。
XML文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<config>
<child>
<node1>
<list name="1">test11</list>
<list name="2">test12</list>
</node1>
<node2>
<list name="1">test21</list>
<list name="2">test31</list>
</node2>
<node3>
<list name="1">test31</list>
<list name="2">test32</list>
</node3>
</child>
</config>


5.开始实现编码。

5.1包含头文件

#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/sax/HandlerBase.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>


5.2初始化环境

try {
XMLPlatformUtils::Initialize();
}
catch (const XMLException& toCatch) {
// Do your failure processing here
return;
}
///
XercesDOMParser *parser = new XercesDOMParser();
parser->setValidationScheme(XercesDOMParser::Val_Always);
parser->setDoNamespaces(true);    // optional

ErrorHandler* errHandler = (ErrorHandler*) new HandlerBase();
parser->setErrorHandler(errHandler);


5.3载入XML文件

try {
parser->parse(“D:\RUN.XML”);
}
catch (const XMLException& toCatch) {
char* message = XMLString::transcode(toCatch.getMessage());
cout << "Exception message is: \n"
<< message << "\n";
XMLString::release(&message);
return;
}
catch (const DOMException& toCatch) {
char* message = XMLString::transcode(toCatch.msg);
cout << "Exception message is: \n"
<< message << "\n";
XMLString::release(&message);
return;
}
catch (...) {
cout << "Unexpected Exception \n";
return;
}


5.4开始解析

DOMDocument *doc = parser->getDocument();
DOMElement *root = doc->getDocumentElement();//读取根节点


5.5 找对应节点值与属性

DOMNode *DN=root;
DN = findchildNode(DN, "child");//查找child子节点
for (DN = DN->getFirstChild(); DN != 0;DN = DN->getNextSibling())
{//遍历node1,2,3子节点
if (DN->getNodeType() == DOMNode::ELEMENT_NODE)//这个是必要的,因为如果不判断类型,实际上每一个节点会有一个TEXT_NODE,而且是第一个节点
{
if (XMLString::compareString(XMLString::transcode(findchildNode(DN, "list")->getAttributes()->getNamedItem(XMLString::transcode("name"))->getNodeValue()), XMLString::transcode("1")) == 0)
{//找到<list name=”1”>的节点
cout <<”对应节点值为:” << XMLString::transcode(findchildNode(DN, " list")->getTextContent())<<endl;
//DO IT CODE
…

};

}
}
XMLPlatformUtils::Terminate();//释放环境


下面是findchildNode函数的代码

DOMNode* findchildNode(DOMNode *n, char *nodename)
{//寻找n节点下子节点名为nodename的节点
try
{
for (DOMNode *child = n->getFirstChild(); child != 0; child = child->getNextSibling())
{
if (child->getNodeType() == DOMNode::ELEMENT_NODE  && XMLString::compareString(child->getNodeName(), XMLString::transcode(nodename)) == 0)
{
return child;
}
}
}
catch (const XMLException& toCatch)
{
char* message = XMLString::transcode(toCatch.getMessage());
cout << "Exception message is: \n"
<< message << "\n";
XMLString::release(&message);
}
return 0;
}


5.6 记得释放环境

XMLPlatformUtils::Terminate();


1.输出结果为

对应节点值为:test11


总结:

读取XML有两种模式,一种是基于事件的SAX方式,一种是DOM,本文采用DOM方式,其实与js中的getElementbyId()有些类似。代码主体是完整的,希望不影响理解。如有需要源代码的,可加QQ或微信:304772487或来信:thpychengai@aliyun.com
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: