iPEX(アイペックス)コラム:【基礎】iPEXクラスの利用 [Part_01]

この文書では、iPEXクラスを利用するための基礎を解説します。解説にはWindows版C++用ライブラリ形式のiPEXを用います。

作成するプログラム xmlecho.exe、xmldump.exe、xmlgenerator.exe
リンク ソースコード xmlecho.zipxmldump.zipxmlgenerator.zip

XML文書の読み込み・書き出し

次に示すコードは、ファイルよりXML文書を読み込んでDOMオブジェクトに展開し、その内容をXML文書として標準出力に書き出すアプリケーションxmlecho.exeです。

#include
#include
>using namespace std;

#include using namespace iPEX;
using namespace iPEX::DOM

#define WSTR(x) Character::toWCString(x, L"shift_jis")
#define MBSTR(x) Character::toMBString(x, L"shift_jis"

int main(int argc char* argv[])
{
  if (argc != 2) {
    cerr << "Usage: XMLEcho2 filename" << endl;
    return 1;
  }
  try {
    // iPEXの初期化
    Init init;
    iconv::CP932ConverterFactory fCP932(L"shift_jis");

    // 入力ファイルのオープン
    DOMString pathname = WSTR(argv[1]);
    Stream::InputStreamByFile ifs(pathname.c_str());
    if (!ifs) {
      cerr << "Could not open file: " << MBSTR(pathname) << endl;
      return 1;
    }
    // XMLデータの読み込み
    XMLReader reader(&ifs);
    Document* pDoc = IPEXDocument::createDocumentObject();
    if (0 == pDoc) {
      cerr << "Could not create document object" << endl;
      return 1;
    }
    if (!reader.read(pDoc)) {
      cerr << "Could not read xml: " << MBSTR(pathname) << endl;
      return 1;
    }
    // 出力ストリームのオープン
    Stream::OutputStreamByFile ofs(Stream::OutputStreamByFile::STDOUT L"shift_jis");
    if (!ofs) {
      cerr << "Could not open stdout" << endl;
      return 1;
    }
    // XMLデータの書き出し
    XMLWriter writer(&ofs);
    if (!writer.write(pDoc)) {
      cerr << "Could not write to stdout" << endl;
      return 1;
    }
    return 0;
  }
  catch (...) {
    cerr << "Somewhat error occured" << endl;
    return 1;
  }
}

次にコードの各処理について解説します。

iPEXの初期化

iPEXで定義されているクラスを使用するためには、以下のようにヘッダファイルipexdom.hをインクルードする必要があります。iPEXのクラスやメソッドは、すべてiPEXという名前のC++ネームスペースの中で宣言されています。また、DOM関連のクラス、APIはiPEX::DOMネームスペースの中で定義されているので、ここでは予めiPEXならびにiPEX::DOMネームスペースに対してusing宣言を使うことにします。

#include <iostream>
#include <memory>
using namespace std;

#include <ipexdom.h>
using namespace iPEX;
using namespace iPEX::DOM;

iPEXは使用する前に初期化する必要があります。初期化は、プロセス単位のものとスレッド単位のものがあります。このプログラムはシングルスレッドで動作するので、プロセス単位のものを用います。プロセス単位の初期化には、iPEX::Initクラスを使用します。次に初期化のコードを示します。

// iPEXの初期化
Init init;

プログラム内でiPEXを使用するためには、iPEXを使用する間iPEX::Initクラスのインスタンスが存在する必要があります。また、このクラスのインスタンスは、プロセスのプライマリスレッドからインスタンス化される必要があります。このため、このプログラムでは全ての処理が行われる間インスタンスが存在するように、関数main()の最初にインスタンスを作成しています。

次に文字のエンコーディングのための初期化を行います。DOM使用時には文字列はDOMStringクラスを用いて表現されます。このクラスは内部的に文字コードとしてUCS(Universal Character Set)を用います。このため、プログラムの実行環境となるプラットフォームが用いる文字コードがUCSでない場合は文字変換の仕組みが必要です。iPEXでは様々な文字セットに対するエンコーディングをサポートしています。Windows上でShift-JISを用いる場合は、次のように初期化を行います。

iconv::CP932ConverterFactory fCP932(L"shift_jis");

上記のコードでクラスCP932ConverterFactoryのインスタンスを作成すると、cp932のエンコーディングを"shift_jis"というエンコーディング名が対応付けられます。その結果、エンコーディングとして"shift_jis"が指定された場合に、cp932のテーブルを使用するようになります。指定した変換はCP932ConverterFactoryのインスタンスが存在している間のみ有効ですので、インスタンスを関数main()の最初に作成します。

実際に文字列変換を行うコードを簡単にするため、次のようなマクロをソースファイルの先頭で定義しておきます。

#define WSTR(x) Character::toWCString(x, L"shift_jis")
#define MBSTR(x) Character::toMBString(x, L"shift_jis")

Character::toWCString()は、指定したエンコーディングで表現された文字列をUCSの文字列に変換します。またCharacter::toMBString()はUCSで表現された文字列を指定のエンコーディングの文字列に変換します。指定されたエンコーディング名がConverterFactory派生クラスにて登録されていない場合はエラーになります。

このプログラムでは、CP932ConverterFactoryのインスタンスをエンコーディング名"shift_jis"を指定して作成し、マクロにてCharacter::toWCString()、Character::toMBString()に対するエンコーディング名の指定を"shift_jis"とすることにより、Shift-JIS文字列を扱いやすくしています。

XMLデータの入力

次にXMLデータをファイルから読み込む部分のコードを示します。

// 入力ファイルのオープン
DOMString pathname = WSTR(argv[1]);
Stream::InputStreamByFile ifs(pathname.c_str());
if (!ifs) {
  cerr << "Could not open file: " << MBSTR(pathname) << endl;
  return 1;
}
// XMLデータの読み込み
XMLReader reader(&ifs);
Document* pDoc = IPEXDocument::createDocumentObject();
if (0 == pDoc) {
  cerr << "Could not create document object" << endl;
  return 1;
}
if (!reader.read(pDoc)) {
  cerr << "Could not read xml: " << MBSTR(pathname) << endl;
  return 1;
}

まずファイル名称を指定して、クラスStream::InputStreamByFileのインスタンスをXMLデータの入力元とし、クラスXMLReaderのインスタンスを作成します。次にIPEXDocument::createDocumentObject()により、DocumentノードpDocを作成し、XMLReader::read()により、pDocをDocumentノードとするDOMツリーを構築します。

XMLReaderにはデータ入力元としてStream::InputStream派生クラスが指定できます。ここではInputStreamByFileの他のパラメータまたは他のStream::InputStream派生クラスを用いてファイルを入力元としましたが、標準入力、文字列、URL等を入力元として指定することも可能です。

XMLデータの出力

次にDOMオブジェクトが保持するXMLデータを標準出力へ出力する部分のコードを示します。

// 出力ストリームのオープン
Stream::OutputStreamByFile ofs(Stream::OutputStreamByFile::STDOUT, L"shift_jis");
if (!ofs) {
  cerr << "Could not open stdout" << endl;
  return 1;
}
// XMLデータの書き出し
XMLWriter writer(&ofs);
if (!writer.write(pDoc)) {
  cerr << "Could not write to stdout" << endl;
  return 1;
}

まずクラスStream:: OutputStreamByFileのインスタンスをXMLデータの出力先とし、クラスXMLWriterのインスタンスを作成します。次にXMLReader::write()により、pDocをDocumentノードとするDOMツリー出力元に指定して出力を行います。

XMLWriterにはデータ出力先としてStream::OnputStream派生クラスが指定できます。これによりXMLReaderと同様、標準出力の他にファイル、文字列、URL等を出力先として指定することが可能です。

xmlecho.exeの実行

xmlecho.exeはコマンドプロンプトにて次のコマンドを実行することにより、XMLファイルbooklist.xmlの内容を表示します。

C:\> xmlecho booklist.xml

© 2001 Infoteria Corporation

基礎:iPEXクラスの利用 [Part_01]/[Part_02]/ [Part_03]

このページのトップ