31 XML Class Generator for C++の使用

このトピックでは、Extensible Markup Language (XML) Class Generator for C++の使用方法について説明します。

トピック:

31.1 XML C++ Class Generatorの入手方法

XML C++ Class Generatorは、Oracle Databaseに付属しています。

31.2 XML C++ Class Generatorの使用

XML C++ Class Generatorは、XML Document Type Definition (DTD)またはXMLスキーマからソース・ファイルを作成します。これは、定義された各要素のクラスを生成します。これらのクラスをC++プログラムで使用して、DTDまたはXMLスキーマに準拠したXML文書を作成します。

これは、アプリケーションがDTDまたはXML Schemaに従って、またはXML文書を構成するWebフォームのバックエンドとして、他のアプリケーションにXMLメッセージを送信する必要がある場合に有効です。C++アプリケーションは、これらのクラスを使用して、入力用DTDに準拠するXML文書を構成、検証および出力できます。

XML C++ Class Generatorは、Oracle XML Parser for C++と組み合せて使用します。XML Parser for C++は、入力用DTDを解析し、解析済文書をClass Generatorに渡します。

トピック:

31.2.1 外部DTDの解析

XML C++ Class Generatorは、完全なドキュメント(ダミー・ドキュメント)をリクエストすることなく、直接外部DTDを解析することもできます。これには、Oracle XML Parser for C++ルーチンのxmlparseDTD()を使用します。提供されているコマンドライン・プログラムxmlcgには、-dオプションがあります。これは、外部DTDの解析に使用されます。

31.3 XML C++ Class Generatorコマンドライン・ユーティリティの使用

単独のClass Generatorは、bin/xmlcgをコールすることによって、実行可能ファイルとしてコールできます。

C++ Class Generatorは、次のようにコマンドラインから起動できます。

xmlcg [options] input_file

表31-1 C++ Class Generatorのオプション

オプション 説明

-d name

入力は外部DTDまたはDTDファイルです。name.cppおよびname.h.を生成します

-o directory

生成されたファイル用の出力ディレクトリ: デフォルトは、現在のディレクトリです。

-e encoding

デフォルトの入力ファイルのエンコーディングです。

-h

使用方法のヘルプを表示します。

-v

XML C++ Class Generatorのバージョンのバリデータ・オプションを表示します。

-s name

指定された名前を持つXML Schemaファイルを入力します。name.cppおよびname.hを生成します。

input_fileは、<!DOCTYPE>定義を含む解析済XML文書、解析済DTDまたはXMLスキーマ文書の名前です。XML文書には、DTDが対応付けられている必要があります。

XML C++ Class GeneratorへのDTDの入力は、DTDを含むXML文書、または外部DTDです。文書本体自体は無視され、DTDのみが使用されますが、文書はDTDに準拠している必要があります。

無効なオプションが使用された場合、または入力が指定されていない場合は、使用メッセージが出力されます。

2つのソース・ファイル、つまり、name.hヘッダー・ファイルとC++ファイルname.cppが出力されます。これらのファイルには、DTDファイルと同じ名前が付けられます。

出力ファイルは、通常、XML文書の生成に使用されます。

各クラス(要素)にコンストラクタが提供されているため、次の方法でオブジェクトを作成できます。

  • まず空のオブジェクトを作成し、後で子またはデータを追加します。

  • 最初からすべての子または初期データを含むオブジェクトを作成します。

#PCDATA(および混合)要素用に提供されているメソッドを使用すると、データを設定したり、適切な場合は、要素の属性を設定することができます。

トピック:

31.3.1 XML C++ Class Generatorへの入力

入力は、DTDを含むXML文書です。文書本体自体は無視され、DTDのみが使用されますが、ダミー・ドキュメントはDTDに準拠している必要があります。基礎となるXMLパーサーは、文書および関連する外部エンティティのファイル名を受け入れるのみです。

31.4 XML C++ Class Generatorの使用例

XML C++ Class Generatorのデモ・ファイルについて説明します。

表31-2 XML C++ Class Generatorファイル

ファイル名 説明

CG.cpp

サンプル・プログラム

CG.xml

DTDおよびダミー・ドキュメントを含むXMLファイル

CG.dtd

CG.xmlが参照するDTDファイル

Make.bat (Windows)

Makefile (UNIX)

クラスを生成し、サンプル・プログラムを構築する、バッチ・ファイル(Windowsの場合)またはMakeファイル(UNIXの場合)。

README

前述のファイルの説明を含むREADMEファイル

Make.batバッチ・ファイル(Windowsの場合)またはMakefile (UNIXの場合)は、次の操作が実行できます。

  • CG.xmlに基づいて、クラスをSample.hおよびSample.cppに生成します。

  • (Sample.hを使用して)プログラムsample.cppをコンパイルし、サンプル・オブジェクトとともに...\bin(または.../bin)ディレクトリにあるCG.exeという実行可能ファイルにリンクします。

トピック:

31.4.1 XML C++ Class Generatorの例1: XML - Class Generatorの入力ファイルCG.xml

XMLファイルCG.xmlを示します。これは、XML C++ Class Generatorへの入力です。これは、CG.dtdというDTDファイルを参照します。

<?xml version="1.0"?>
<!DOCTYPE Sample SYSTEM "CG.dtd">
  <Sample>
    <B>Be!</B>
    <D attr="value"></D>
    <E>
      <F>Formula1</F>
      <F>Formula2</F>
    </E>
  </Sample>

31.4.2 XML C++ Class Generatorの例2: DTD - Class Generatorの入力ファイルCG.dtd

DTDファイルCG.dtdを示します。これは、XML C++ Class Generatorへの入力であるXMLファイルCG.xmlにより参照されます。

<!ELEMENT Sample (A | (B, (C | (D, E))) | F)>
<!ELEMENT A (#PCDATA)>
<!ELEMENT B (#PCDATA | F)*>
<!ELEMENT C (#PCDATA)>
<!ELEMENT D (#PCDATA)>
<!ATTLIST D attr CDATA #REQUIRED>
<!ELEMENT E (F, F)>
<!ELEMENT F (#PCDATA)>

31.4.3 XML C++ Class Generatorの例3: CGサンプル・プログラム

サンプル・プログラムCGのCG.cppを示します。

次を実行します。

  1. XMLパーサーを初期化します。

  2. DTDを含むファイルのダミー・ドキュメント部分以外を解析することによって、DTDをロードします。

  3. 生成されたクラスを使用して複数のオブジェクトを作成します。

  4. 生成されたクラスがDTDに一致するかどうかを検証する、検証関数をコールします。

  5. 作成されたドキュメントをSample.xmlに書き込みます。

//////////////////////////////////////////////////////////////////////////////
// NAME        CG.cpp
// DESCRIPTION Demonstration program for C++ class generator usage
//////////////////////////////////////////////////////////////////////////////

#ifndef ORAXMLDOM_ORACLE
# include <oraxmldom.h>
#endif

#include <fstream.h>

#include "Sample.h"

#define DTD_DOCUMENT "CG.xml"
#define OUT_DOCUMENT Sample.xml"

int main()
{
    XMLParser parser;
    Document *doc;
    Sample   *samp;
    B        *b;
    D        *d;
    E        *e;
    F        *f1, *f2;
    fstream  *out;
    ub4       flags = XML_FLAG_VALIDATE;
    uword     ecode;

    // Initialize XML parser
    cout << "Initializing XML parser...\n";
    if (ecode = parser.xmlinit())
    {
        cout << "Failed to initialize parser, code " << ecode << "\n";
        return 1;
    }

    // Parse the document containing a DTD; parsing just a DTD is not
    // possible yet, so the file must contain a valid document (which
    // is parsed but we're ignoring).
    cout << "Loading DTD from " << DTD_DOCUMENT << "...\n";
    if (ecode = parser.xmlparse((oratext *) DTD_DOCUMENT, (oratext *)0, flags))
    {
        cout << "Failed to parse DTD document " << DTD_DOCUMENT <<
        ", code " << ecode << "\n";
        return 2;
    }

    // Fetch dummy document
    cout << "Fetching dummy document...\n";
    doc = parser.getDocument();

    // Create the constituent parts of a Sample
    cout << "Creating components...\n";
    b = new B(doc, (String) "Be there or be square");
    d = new D(doc, (String) "Dit dah");
    d->setattr((String) "attribute value");
    f1 = new F(doc, (String) "Formula1");
    f2 = new F(doc, (String) "Formula2");
    e = new E(doc, f1, f2);

    // Create the Sample
    cout << "Creating top-level element...\n";
    samp = new Sample(doc, b, d, e);

    // Validate the construct
    cout << "Validating...\n";
    if (ecode = parser.validate(samp))
    {
     cout << "Validation failed, code " << ecode << "\n";
     return 3;
    }

    // Write out doc
    cout << "Writing document to " << OUT_DOCUMENT << "\n";
    if (!(out = new fstream(OUT_DOCUMENT, ios::out)))
    {
      cout << "Failed to open output stream\n";
      return 4;
    }
    samp->print(out, 0);
    out->close();

    // Everything's OK
    cout << "Success.\n";

    // Shut down
    parser.xmlterm();
    return 0;
}

// end of CG.cpp