c++ 使用xerces读取XML

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包含头文件

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

5.2初始化环境

 1 try {
 2         XMLPlatformUtils::Initialize();
 3     }
 4     catch (const XMLException& toCatch) {
 5         // Do your failure processing here
 6         return;
 7     }
 8     ///
 9     XercesDOMParser *parser = new XercesDOMParser();
10     parser->setValidationScheme(XercesDOMParser::Val_Always);
11     parser->setDoNamespaces(true);    // optional
12 
13     ErrorHandler* errHandler = (ErrorHandler*) new HandlerBase();
14     parser->setErrorHandler(errHandler);

5.3载入XML文件

 1 try {
 2         parser->parse(“D:\RUN.XML”);
 3     }
 4     catch (const XMLException& toCatch) {
 5         char* message = XMLString::transcode(toCatch.getMessage());
 6         cout << "Exception message is: \n"
 7             << message << "\n";
 8         XMLString::release(&message);
 9         return;
10     }
11     catch (const DOMException& toCatch) {
12         char* message = XMLString::transcode(toCatch.msg);
13         cout << "Exception message is: \n"
14             << message << "\n";
15         XMLString::release(&message);
16         return;
17     }
18     catch (...) {
19         cout << "Unexpected Exception \n";
20         return;
21     }

5.4开始解析

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

5.5 找对应节点值与属性

 1 DOMNode *DN=root;
 2 DN = findchildNode(DN, "child");//查找child子节点
 3 for (DN = DN->getFirstChild(); DN != 0;DN = DN->getNextSibling())
 4     {//遍历node1,2,3子节点
 5         if (DN->getNodeType() == DOMNode::ELEMENT_NODE)//这个是必要的,因为如果不判断类型,实际上每一个节点会有一个TEXT_NODE,而且是第一个节点
 6         {
 7             if (XMLString::compareString(XMLString::transcode(findchildNode(DN, "list")->getAttributes()->getNamedItem(XMLString::transcode("name"))->getNodeValue()), XMLString::transcode("1")) == 0)
 8             {//找到<list name=”1”>的节点
 9                 cout <<”对应节点值为:” << XMLString::transcode(findchildNode(DN, " list")->getTextContent())<<endl;
10                     //DO IT CODE
11 12                 
13             };
14             
15         }
16      }
17 XMLPlatformUtils::Terminate();//释放环境

下面是findchildNode函数的代码

 1 DOMNode* findchildNode(DOMNode *n, char *nodename)
 2  {//寻找n节点下子节点名为nodename的节点
 3      try
 4      {
 5          for (DOMNode *child = n->getFirstChild(); child != 0; child = child->getNextSibling())
 6          {
 7              if (child->getNodeType() == DOMNode::ELEMENT_NODE  && XMLString::compareString(child->getNodeName(), XMLString::transcode(nodename)) == 0)
 8              {
 9                  return child;
10              }
11          }
12      }
13      catch (const XMLException& toCatch)
14      {
15          char* message = XMLString::transcode(toCatch.getMessage());
16          cout << "Exception message is: \n"
17              << message << "\n";
18          XMLString::release(&message);
19      }
20      return 0;
21  }

5.6 记得释放环境

XMLPlatformUtils::Terminate();

 

1.输出结果为

对应节点值为:test11

总结:

读取XML有两种模式,一种是基于事件的SAX方式,一种是DOM,本文采用DOM方式,其实与js中的getElementbyId()有些类似。代码主体是完整的,希望不影响理解。如有需要源代码的,可加QQ或微信:304772487或来信:thpychengai@aliyun.com

posted @ 2015-06-23 00:00  道为有为  阅读(3961)  评论(0编辑  收藏  举报