Xerces-C++を使ってみる

とりあえずXerces-C++の仕様を調べるためにこんなソースを書いてみた。
http://a-gamyl.hp.infoseek.co.jp/Clang/cppxml.html
を参考にしていますです。おおよそこのまま。

/**
 * @file Xercesのサンプル
 *
 * @author Hoshimi's Works
 * @date 2008/09/12
 * @note ご自由にお使いください。ただし責任は一切負いません。負えません。
 */
#include <iostream>
//xercesc関連のinclude
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/dom/DOMNode.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/sax/HandlerBase.hpp>
#include <xercesc/framework/LocalFileFormatTarget.hpp>
//libの読み込み
#ifdef _DEBUG
#pragma comment(lib,"xerces-c_2D.lib")
#pragma comment(lib,"xerces-depdom_2D.lib")
#endif //_DEBUG
#ifndef _DEBUG
#pragma comment(lib,"xeces-c_2.lib")
#pragma comment(lib,"xerces-depdom_2.lib")
#endif //_DEBUG

//Xercesのnamespaceをまとめて使うよ宣言
XERCES_CPP_NAMESPACE_USE
using namespace std;
//XMLを表示
void traceNode(DOMElement& root,int nDepth)
{
	DOMNodeList* pNodeList = root.getChildNodes();
	if(nDepth==0){
		DOMNode* r = (DOMNode*)&root;
		char* name = XMLString::transcode(r->getNodeName());
		printf("%s\n",name);
		XMLString::release(&name);
	}
	for(int i = 0;i < pNodeList->getLength();i++){//nodeの個数だけ処理
		DOMElement* pDomElement = (DOMElement *)pNodeList->item(i);
		if(((DOMNode*)pDomElement)->getNodeType() == pDomElement->ELEMENT_NODE){
			traceNode(*pDomElement,nDepth+1);
		}else if(((DOMNode*)pDomElement)->getNodeType() == pDomElement->TEXT_NODE){
			DOMNode* pDomNode = pDomElement->getParentNode();
			char *snode = XMLString::transcode(pDomNode->getNodeName());
			char *value = XMLString::transcode(pDomElement->getTextContent());
			for(int i = 0;i < nDepth;i++)printf("\t");
			printf("%s",snode);
			//Attributeの表示
			
			if(pDomNode->hasAttributes()){
				DOMNamedNodeMap* pNamedNodeMap = pDomNode->getAttributes();
				for(int i =0; i < pNamedNodeMap->getLength();i++){
					DOMNode* pAttributeNode = pNamedNodeMap->item(i);
					char *sAttNode = XMLString::transcode(pAttributeNode->getNodeName());
					char *sAttValue = XMLString::transcode(pAttributeNode->getTextContent());
					printf(" %s:%s",sAttNode,sAttValue);
				}
			}
			
			printf("\n");
            if(value[0] != '\n'){
                //printf("%d> %s:\t%s\n",depth,snode,value);
				for(int i = 0;i < nDepth+1;i++)printf("\t");
				printf("%s\n",value);
            }
            XMLString::release(&snode);
            XMLString::release(&value);
		}
	}
}

int main(int argc, const char* args[])
{
	try{
		XMLPlatformUtils::Initialize();
	}
	catch(const XMLException& e){
		char* message = XMLString::transcode(e.getMessage());
		fprintf(stderr,"Error during initialization! : %s\n",message);
		XMLString::release(&message);
		return 1;
	}
	
	XercesDOMParser* parser = new XercesDOMParser();

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

	char xmlFile[20] = "Sample.gxl";

	parser->parse(xmlFile);

	DOMDocument* doc = parser->getDocument();
	DOMElement * root = doc->getDocumentElement();

	traceNode(*root,0);

	delete parser;
	delete errHandler;

	XMLPlatformUtils::Terminate();

	int n = 0;
	std::cin>>n;

	return 0;
}

とりあえずこれで次のxmlファイルを読み込んでみる。

<?xml version="1.0" encoding="UTF-8" ?>
<gxl>
	<graph id="simpleExample-instance" edgeids="true">
		<node id="ドラえもん" color="0x3333ff">22世紀のネコ型ロボット。のび太を助けるために現代にやってきた。
未来の道具がいろいろ入った四次元ポケットを持つ。
量産型の子守用ネコ型ロボット。性別は雄。方倉設定では「特定意志薄弱児童監視指導員」という肩書きを持つ。
普段は野比のび太の家に居候しており、のび太の部屋の押入れがドラえもんの寝床となっている。
また、押入れはいろいろと改装されている。
親類として、子守用ネコ型ロボットのサポートのために特注で作られた、妹ロボットのドラミがいる。
		</node>
		<node id="のび太" color="0xaaffff">頭が悪く、運動も苦手な上に、怠け者でスケベという、かなり「落ちこぼれ」ている少年。
やるべきことがあっても呑気に昼寝を決め込み、母親やドラえもんに怒られるのが常である。
基本的には運にも恵まれていない。
物語は彼の不幸な将来を変えるために、未来の子孫であるセワシからドラえもんが送られたことから始まる。
以降、困りごとがあったり、トラブルに巻き込まれるとドラえもんに泣きつき、ひみつ道具に頼ろうとする。
それに応じて出したひみつ道具を応用する事に関しては、時折天才的なひらめきを見せるが、結果的に失敗することが多々ある。
大長編・映画版では上に述べた欠点が希薄になり、勇敢な少年として描かれることが多い。このことは作品内でもスネ夫に「のび太は大長編だとかっこよくなるんだから」といわれている[6]。
		</node>
		<edge id="ドラえもんとのび太" from="のび太" to="ドラえもん">
			<fromTitle>唯一の頼み綱</fromTitle>
			<toTitle>哀れな小学生</toTitle>
		</edge>
	</graph>
</gxl>

*1
ドラえもんのび太の関係をグラフ化するものである。データはwikipediaから。
以下は出力結果。

gxl
gxl
	graph edgeids:true id:simpleExample-instance
		node color:0x3333ff id:ドラえもん
			22世紀のネコ型ロボット。のび太を助けるために現代にやってきた。
未来の道具がいろいろ入った四次元ポケットを持つ。
量産型の子守用ネコ型ロボット。性別は雄。方倉設定では「特定意志薄弱児童監視指導員」という肩書きを持つ。
普段は野比のび太の家に居候しており、のび太の部屋の押入れがドラえもんの寝床となっている。
また、押入れはいろいろと改装されている。
親類として、子守用ネコ型ロボットのサポートのために特注で作られた、妹ロボットのドラミがいる。
		
	graph edgeids:true id:simpleExample-instance
		node color:0xaaffff id:のび太
			頭が悪く、運動も苦手な上に、怠け者でスケベという、かなり「落ちこぼれ」ている少年。
やるべきことがあっても呑気に昼寝を決め込み、母親やドラえもんに怒られるのが常である。
基本的には運にも恵まれていない。
物語は彼の不幸な将来を変えるために、未来の子孫であるセワシからドラえもんが送られたことから始まる。
以降、困りごとがあったり、トラブルに巻き込まれるとドラえもんに泣きつき、ひみつ道具に頼ろうとする。
それに応じて出したひみつ道具を応用する事に関しては、時折天才的なひらめきを見せるが、結果的に失敗することが多々ある。
大長編・映画版では上に述べた欠点が希薄になり、勇敢な少年として描かれることが多い。このことは作品内でもスネ夫に「のび太は大長編だとかっこよくなるんだから」といわれている[6]。
		
	graph edgeids:true id:simpleExample-instance
		edge from:のび太 id:ドラえもんとのび太 to:ドラえもん
			fromTitle
				唯一の頼み綱
		edge from:のび太 id:ドラえもんとのび太 to:ドラえもん
			toTitle
				哀れな小学生
		edge from:のび太 id:ドラえもんとのび太 to:ドラえもん
	graph edgeids:true id:simpleExample-instance
gxl

余談だが、このxmlファイルを解釈して画面に表示したflashは以下のとおり。
(自作。適当に作った)

以下作っていて思った点。

  • 文字コードUTF-8しか使えない?SJISなどはたとえ冒頭で文字コードの宣言をしていてもparseの段階でmallocエラーを起こす。これ回避できるのかな?それとも内部で自分で解釈してiconvとかつかっておきかえてやらないといけないのかな?
  • タグの値は""のようにの直後に文字列がないと無視されるみたい。
  • プロパティはお互いと"とcolorの間にスペースがないとやはりエラーを起こすようだ。まあここは気をつけてxmlをかけ、ということだろう。

*1:ちなみにこのxmlはgxlという形式でgraphmlという仕様にのっとって書かれている。http://graphml.graphdrawing.org/