Xerces-C++でxml解析するプログラム作ったのでメモ残しとく。
xmlのパーサはXercesを使用することにした。
(最初はlibxml2を使おうとしたけど、APIが多すぎてイヤになった)
インストは以下手順でインスト。
$ tar xvzf xerces-c-3.1.1.tar.gz $ cd xerces-c-3.1.1 $ ./configure $ make $ sudo make install
まずは写経してみる。
解析するxmlファイルはこんなやつを用意。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <!DOCTYPE infos [ <!ELEMENT infos (info)*> <!ELEMENT info (id, status, datas?)> <!ELEMENT id (#PCDATA)> <!ELEMENT status (#PCDATA)> <!ELEMENT datas (data)*> <!ELEMENT data (#PCDATA)> <!ATTLIST data type CDATA #REQUIRED value CDATA #REQUIRED> ]> <infos> <info> <id>id1</id> <status>0</status> <datas> <data type="1" value="user@123"/> </datas> </info> <info> <id>id2</id> <status>1</status> </info> <info> <id>id3</id> <status>2</status> <datas></datas> </info> <info> <id>id4</id> <status>3</status> <datas> <data type="1" value="user@123"/> <data type="2" value="user@12345678"/> <data type="5" value="12345678"/> </datas> </info> </infos>
ソースはここのやつを参考(というか丸パクリ)にして作成。
xmlからDOMを生成して頭から表示するプログラム。
#include <iostream> using namespace std; #include <xercesc/dom/DOM.hpp> #include <xercesc/dom/DOMElement.hpp> #include <xercesc/dom/DOMNode.hpp> #include <xercesc/dom/DOMText.hpp> #include <xercesc/parsers/XercesDOMParser.hpp> #include <xercesc/sax/HandlerBase.hpp> using namespace xercesc; #define OK 0 #define NG 1 #define XMLFILE_PATH "sample.xml" void writeNode(DOMNode* node); void writeElement(DOMElement* element); void writeText(DOMText* text); int main(int argc, char** argv) { try{ XMLPlatformUtils::Initialize(); } catch(const XMLException& exp) { char* message = XMLString::transcode(exp.getMessage()); cerr << "Xerces-C++ 初期化エラー" << endl; cerr << message << endl; XMLString::release(&message); return NG; } XercesDOMParser* parser = new XercesDOMParser(); parser->setValidationScheme(XercesDOMParser::Val_Always); parser->setDoNamespaces(true); ErrorHandler* errHandler = new HandlerBase(); parser->setErrorHandler(errHandler); try { const char* xmlFile = XMLFILE_PATH; parser->parse(xmlFile); DOMDocument* dom = parser->getDocument(); writeNode(dom); } catch ( const XMLException& exp ) { char* message = XMLString::transcode(exp.getMessage()); cout<< "Exception message is: \n" << message << endl; XMLString::release(&message); return NG; } catch ( const DOMException& exp ) { char* message = XMLString::transcode(exp.getMessage()); cout<< "Exception message is: \n" << message << endl; XMLString::release(&message); return NG; } catch (...) { cout << "Unexpected Exception" << endl; return NG; } delete parser; delete errHandler; return OK; } void writeNode(DOMNode* node) { assert(node != NULL); switch( node->getNodeType() ) { case DOMNode::ELEMENT_NODE: writeElement(static_cast<DOMElement*>(node)); break; case DOMNode::TEXT_NODE: writeText(static_cast<DOMText*>(node)); break; } DOMNode* child = node->getFirstChild(); while(child) { writeNode(child); DOMNode* next = child->getNextSibling(); child = next; } } void writeElement(DOMElement* element) { char* name = XMLString::transcode(element->getTagName()); cout << "tag :" << name << endl; XMLString::release(&name); DOMNamedNodeMap* map = element->getAttributes(); for ( XMLSize_t i = 0; i < map->getLength(); i++ ) { DOMAttr* attr= static_cast<DOMAttr*>(map->item(i)); char* attr_name = XMLString::transcode(attr->getName()); char* attr_value = XMLString::transcode(attr->getValue()); cout << attr_name << ": " << attr_value << endl; XMLString::release(&attr_name); XMLString::release(&attr_value); } } void writeText(DOMText* text) { XMLCh* buffer = new XMLCh[XMLString::stringLen(text->getData()) + 1]; XMLString::copyString(buffer, text->getData()); XMLString::trim(buffer); char* content = XMLString::transcode(buffer); delete[] buffer; cout << "content :" << content << endl; XMLString::release(&content); }
実行結果。
tag :infos content : tag :info content : tag :id content :id1 content : tag :status content :0 content : tag :datas content : tag :data type: 1 value: user@123 content : content : content : tag :info content : tag :id content :id2 content : tag :status content :1 content : content : tag :info content : tag :id content :id3 content : tag :status content :2 content : tag :datas content : content : tag :info content : tag :id content :id4 content : tag :status content :3 content : tag :datas content : tag :data type: 1 value: user@123 content : tag :data type: 2 value: user@12345678 content : tag :data type: 5 value: 12345678 content : content : content :
一応動いた。
最終的にやりたいのは、このDOMオブジェクトに対して、任意のtagを指定したアクセスなので、もう少し勉強してみる。