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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM