RDpp Version Alpha-01

筑木 真志<Shinji.Chikugi@nifty.ne.jp>

はじめに

RDppはlibxml2のC++ラッパの一つです。
ほかのC++ラッパやlibxml2以外のDOMパーサと比べて以下の特徴があります。

欠点としては以下の点が挙げられます。

設計方針は、libxml2の関数/オブジェクトをC++/STL風にアクセスできるようにしただけですので、そのアーキテクチャはlibxml2に大きく依存します。

FAQ

Q1. すでにlibxml2のC++ラッパがあるのに、なぜ新しいC++ラッパを開発する必要があるのですか?

A1. libxml2が文字列をUTF-8で扱うため、libxml2の関数を呼び出す度にShift-JIS(もしくは、eucJP)とUTF-8との相互変換をする必要があります。文字コードの変換のような定型的でかつ、面倒な部分は「隠す」べきだと私は考えています。
残念ながら、私が知るほかのC++ラッパが文字コードについてあまり考慮していないので、「車輪の再発明」をすることにしました。既存のライブラリに文字変換ラッパクラスを注入することも考えましたが、単純にはいかないと判断したので、1からスクラッチで作りました。

Q2. ではlibxml2ではなくXercesやMSXMLなどのほかのパーサを使わないのはなぜですか?

A2. Xercesは私にとって複雑すぎます。また、愛用しているC++Builderでビルドはできるのですが、日本語がうまく扱えないのであきらめました。
MSXMLはWindowsに依存していますので、ほかのOSでは使えません。一応、C++Builder標準でもDOMパーサはあるのですが、XPathを使ってノードの検索ができません。libxml2はこれらの条件を満たしたのでlibxml2を選択しました。

Q3. C++ではデストラクタがあるのに、なぜ、明示的にリソースの解放をしなければならないのですか?これは「定型的」な処理のような気がしますが…

A3. DOMパーサはオブジェクトの生成や消滅を自前でリソース管理をする必要があります。
これは、ラッパクラスでも同様です。(たとえば、libxml++は自前でリソースの管理をしています。)また、Xercesはガベージコレクションを実装しています。
ただ、これを行うと処理が複雑になる上、手軽に実装できなくなるので、リソース管理はすべてlibxml2に任せる方針にしてあります。
まぁ、最大の理由は私のスキル不足です。(^_^;
基本的に新規オブジェクトの生成はクラスメソッドによって行われます。 クラスメソッドによって生成されたオブジェクトは必ずオブジェクトが消滅する前にメソッド"free"で明示的にリソースの解放をしなければなりません。 コンストラクタは空のオブジェクトしか生成しません。

Q4. XSLT、Namespace、XPointer等ががサポートされていません。

A4. 将来的にサポートする予定です。原則としてlibxml2でサポートしているSAX以外の機能はサポートしたいと思っています。

Q5. RDppの由来は何ですか?

A5. Refitted DOM Perser for CPP(改装したC++用DOMパーサ)の略です。
Rubyを使った文書フォーマッタであるRDと重なる危惧があるのですが、問題が発生したら名称は変えます。

Q6. 最新版はどこで入手できますか?また、バグ、要望はどのように伝えればよいですか?

A6. 本プロジェクトのホームページはhttp://yaxmlpp.sourceforge.jp/です。最新版はこのサイトで入手できます。バグ報告、要望もこのサイトで受け付けます。

サンプルコード

その1:新規データ作成

#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;
}

その2:Node&Attribute

#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();
}

その3:XPath

#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.