Xercesっていうのは、Apache Software Foundationで開発されている、オープンソースのXMLパーサーのこと。
Java版がメジャーだけど、C++でXML読み込む必要があったので、実装してみた。
以下、Windows + Visual Studioでの手順のメモ書き。備忘録なので、かなりはしょってます。
また、とりあえず動けばいいや、で組んだプログラムなので、結構いい加減です。参考にする場合は自己責任でお願いします。
1.ソースのダウンロードとコンパイル
http://xerces.apache.org/xerces-c/download.cgi
で、xerces-c-3.0.1.zip(ソース)をダウンロード。
解凍した後、"xerces-c-3.0.1\xerces-c-3.0.1\projects\Win32\VC8\xerces-all"へ移動。
xerces-all.slnを起動して、普通にReleaseビルド。
2.実行環境作成
・出力されたxerces-c_3.libを適当なディレクトリへコピー。(ex. <開発ディレクトリ>\lib)
・xerces-c_3_0.dllを開発ディレクトリの直下へコピー。
・解凍したソースコードのディレクトリの"xerces-c-3.0.1\src\xercesc"ディレクトリを適当な場所(ex. <開発ディレクトリ>\inc)へコピー
・Visual Studioのプロジェクトのプロパティを開き、左側のツリーから「構成プロパティ -> C/C++ -> 全般」を選択して、追加のインクルードディレクトリに、インクルードファイルをコピーした場所を追加(ex. inc)
・リンカの方にも同じくxerces-c_3.libへのライブラリパスとライブラリ名を追加しておく。
3.ソースコード
次のようなXMLファイルを読み込むプログラムを作る。
VOC2007 2007_000033.jpg n/a n/a 500 366 3 1
これを、
typedef enum{ FRONTAL, REAR, LEFT, RIGHT }OBJECT_POSE; typedef struct{ char name[128]; OBJECT_POSE pose; int truncate; int difficult; int xmax; int xmin; int ymax; int ymin; }VOC_OBJECT;
以下、ソースコード。XMLパーサにはDOMとSAXという2つの種類があるんだけど、ここではDOMを使いました。DOMとSAXの違いについては、この記事でも参考にしてください。
#include#include #include #include using namespace xercesc; #include using namespace std; /***** tagNameという名前の子要素を取得 *****/ DOMNodeList* getElementByCharTagName(DOMElement* elem, char *tagName) { XMLCh* attributeName=XMLString::transcode(tagName); DOMNodeList* nlist = elem->getElementsByTagName(attributeName); XMLString::release(&attributeName); return nlist; } /***** tagNameという名前の子要素からその中身(int型)を取得 *****/ int getIntByCharTagName(DOMElement* elem, char *tagName) { DOMNodeList* nlist = getElementByCharTagName(elem,tagName); const XMLCh* node_txt = ( (nlist->item(0))->getFirstChild() )->getNodeValue(); char* str = XMLString::transcode(node_txt); int ret = atoi(str); XMLString::release(&str); return ret; } // XMLファイルの読み込み void readXML(char* xmlFile) { /* Xercesの初期化(必須)*/ try { XMLPlatformUtils::Initialize(); } catch (const XMLException& toCatch) { // Do your failure processing here return; } XercesDOMParser *parser = new XercesDOMParser; VOC_OBJECT* voc_obj = 0; int obj_num = 0; try { parser->parse(xmlFile); DOMDocument *doc = parser->getDocument(); DOMElement *root = doc->getDocumentElement(); DOMNodeList* nlist = getElementByCharTagName(root,"object"); obj_num = (int)(nlist->getLength()); voc_obj = new VOC_OBJECT[obj_num]; char *str; DOMNodeList *nlist2; const XMLCh *node_txt; for(int i=0;i (nlist->item(i)),"name"); node_txt = ( (nlist2->item(0))->getFirstChild() )->getNodeValue(); str = XMLString::transcode(node_txt); strcpy(voc_obj[i].name, str); XMLString::release(&str); nlist2 = getElementByCharTagName(dynamic_cast (nlist->item(i)),"pose"); node_txt = ( (nlist2->item(0))->getFirstChild() )->getNodeValue(); str = XMLString::transcode(node_txt); if(!strcmp(str,"Frontal")){ voc_obj[i].pose = FRONTAL; } else if(!strcmp(str,"Rear")){ voc_obj[i].pose = REAR; } else if(!strcmp(str,"Left")){ voc_obj[i].pose = LEFT; } else if(!strcmp(str,"Right")){ voc_obj[i].pose = RIGHT; } XMLString::release(&str); voc_obj[i].truncate = getIntByCharTagName(dynamic_cast (nlist->item(i)),"truncated"); voc_obj[i].difficult = getIntByCharTagName(dynamic_cast (nlist->item(i)),"difficult"); nlist2 = getElementByCharTagName(dynamic_cast (nlist->item(i)),"bndbox"); voc_obj[i].xmin = getIntByCharTagName(dynamic_cast (nlist2->item(0)),"xmin"); voc_obj[i].xmax = getIntByCharTagName(dynamic_cast (nlist2->item(0)),"xmax"); voc_obj[i].ymin = getIntByCharTagName(dynamic_cast (nlist2->item(0)),"ymin"); voc_obj[i].ymax = getIntByCharTagName(dynamic_cast (nlist2->item(0)),"ymax"); } } catch(...) { cerr << "ファイルの解析に失敗しました。" << endl; } /* 読み込み結果の出力 */ for(int i=0;i 0) delete [] voc_obj; delete parser; /* Xercesの終了(必須)*/ XMLPlatformUtils::Terminate(); }
4.解説など
めんどくさいので、細かいソースの解説はしません。一応、簡単なTipsだけ載せます。