RDppはlibxml2のC++ラッパの一つです。
ほかのC++ラッパやlibxml2以外のDOMパーサと比べて以下の特徴があります。
欠点としては以下の点が挙げられます。
A1. libxml2が文字列をUTF-8で扱うため、libxml2の関数を呼び出す度にShift-JIS(もしくは、eucJP)とUTF-8との相互変換をする必要があります。文字コードの変換のような定型的でかつ、面倒な部分は「隠す」べきだと私は考えています。
残念ながら、私が知るほかのC++ラッパが文字コードについてあまり考慮していないので、「車輪の再発明」をすることにしました。既存のライブラリに文字変換ラッパクラスを注入することも考えましたが、単純にはいかないと判断したので、1からスクラッチで作りました。
A2. Xercesは私にとって複雑すぎます。また、愛用しているC++Builderでビルドはできるのですが、日本語がうまく扱えないのであきらめました。
MSXMLはWindowsに依存していますので、ほかのOSでは使えません。一応、C++Builder標準でもDOMパーサはあるのですが、XPathを使ってノードの検索ができません。libxml2はこれらの条件を満たしたのでlibxml2を選択しました。
A3. DOMパーサはオブジェクトの生成や消滅を自前でリソース管理をする必要があります。
これは、ラッパクラスでも同様です。(たとえば、libxml++は自前でリソースの管理をしています。)また、Xercesはガベージコレクションを実装しています。
ただ、これを行うと処理が複雑になる上、手軽に実装できなくなるので、リソース管理はすべてlibxml2に任せる方針にしてあります。
まぁ、最大の理由は私のスキル不足です。(^_^;
基本的に新規オブジェクトの生成はクラスメソッドによって行われます。 クラスメソッドによって生成されたオブジェクトは必ずオブジェクトが消滅する前にメソッド"free"で明示的にリソースの解放をしなければなりません。 コンストラクタは空のオブジェクトしか生成しません。
A4. 将来的にサポートする予定です。原則としてlibxml2でサポートしているSAX以外の機能はサポートしたいと思っています。
A5. Refitted DOM Perser for CPP(改装したC++用DOMパーサ)の略です。
Rubyを使った文書フォーマッタであるRDと重なる危惧があるのですが、問題が発生したら名称は変えます。
A6. 本プロジェクトのホームページはhttp://yaxmlpp.sourceforge.jp/です。最新版はこのサイトで入手できます。バグ報告、要望もこのサイトで受け付けます。
#include <iostream>
#include <RD.h>
int main(int argc, char* argv[])
{
RDDocument doc = RDDocument::create("1.0", "root", NULL);
RDNode root_node = doc.getRootNode();
RDNode node1 = root_node.addChild("child", "日本語の値");
node1.setAttribute("日本語のキー", "日本語の属性");
root_node.addChild("child", "test2");
root_node.addChild("child", "test3");
doc.saveFile("sjis.xml", "Shift_JIS", 1);
doc.saveFile("utf8.xml", "UTF-8", 1);
doc.free();
return 0;
}
#include <iostream>
#include <RD.h>
void WalkChilden(const RDNode& node)
{
RDNodeList::const_iterator pChildren;
std::string name;
std::string content;
std::string path;
RDNodeList Children = node.getChildren();
for (pChildren = Children.begin(); pChildren != Children.end(); pChildren++) {
name = pChildren->getName();
content = pChildren->getContent();
path = pChildren->getPath();
std::cout << "Type = " << std::string(pChildren->getElementTypeName()) << " " <<
"Path = " << path << " " <<
"Name = " << name << " " <<
"Content = " << content << std::endl;
}
}
int main(int argc, char* argv[])
{
RDDocument doc = RDDocument::parseFile("test.xml");
RDNode root_node = doc.getRootNode();
RDNodeList::iterator pChildren;
RDNodeList Children = root_node.getChildren();
std::string name;
std::string content;
std::string path;
for (pChildren = Children.begin(); pChildren != Children.end(); pChildren++) {
name = pChildren->getName();
content = pChildren->getContent();
path = pChildren->getPath();
std::cout << "Type = " << std::string(pChildren->getElementTypeName()) << " " <<
"Path = " << path << " " <<
"Name = " << name << " " <<
"Content = " << content << std::endl;
WalkChilden(*pChildren);
}
doc.free();
}
#include <iostream>
#include <RD.h>
int main (int argc, char** argv)
{
RDDocument doc = RDDocument::parseFile("slashdot16.xml");
RDXPath xpath = doc.evaluateXPath("/ultramode/story/title");
RDNodeset nodeset = xpath.getNodeset();
RDNodeset::iterator pNodeSet;
for (pNodeSet = nodeset.begin(); pNodeSet != nodeset.end(); pNodeSet++) {
std::cout << std::string(pNodeSet->getContent()) << std::endl;
}
doc.free();
return 0;
}
Copyright (c) 2003 Shinji.Chikugi All rights reserved.