この章の内容は次のとおりです。
XML C++ Class Generatorは、Oracle Databaseに付属しています。
XML C++ Class Generatorは、XML DTDまたはXML Schemaからソース・ファイルを作成します。XML C++ Class GeneratorはDocument Type Definition(DTD)またはXML Schemaを使用し、定義された各要素用のクラスを生成します。これらのクラスをC++プログラムで使用し、DTDに準拠する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に渡します。
単独のClass Generatorは、bin/xmlcgをコールすることによって、実行可能ファイルとしてコールできます。
C++ Class Generatorは、コマンドラインに次のように入力して実行できます。
xmlcg [options] input_file
表29-1に、このユーティリティのオプションを示します。
表29-1 C++ Class Generatorのオプション
| オプション | 意味 | 
|---|---|
| 
 
  | 
 入力は外部DTDまたはDTDファイルです。  | 
| 
 
  | 
 生成されたファイル用の出力ディレクトリ: デフォルトは、現在のディレクトリです。  | 
| 
 
  | 
 デフォルトの入力ファイルのエンコーディングです。  | 
| 
 
  | 
 使用方法のヘルプを表示します。  | 
| 
 -v  | 
 XML C++ Class Generatorのバージョンのバリデータ・オプションを表示します。  | 
| 
 -s name  | 
 指定された名前を持つXML Schemaファイルを入力します。name.cppおよびname.hを生成します。  | 
input_file名は、<!DOCTYPE>を定義する解析済XML文書、解析済DTDまたはXML Schema文書の名前です。XML文書には、DTDが対応付けられている必要があります。
XML C++ Class GeneratorへのDTDの入力は、DTDを含むXML文書、または外部DTDです。文書本体自体は無視され、DTDのみが使用されますが、文書はDTDに準拠している必要があります。
オプションが無効な場合、または入力が指定されない場合は、前述した情報を含む使用メッセージが出力されます。
2つのソース・ファイル、name.hヘッダー・ファイルおよびC++ファイル、name.cppが出力されます。これらのファイルには、DTDファイルと同じ名前が付けられます。
出力ファイルは、通常、XML文書の生成に使用されます。
各クラス(要素)にコンストラクタが提供されているため、次の2つの方法でオブジェクトを作成できます。
まず空のオブジェクトを作成し、後で子またはデータを追加します。
最初からすべての子または初期データを含むオブジェクトを作成します。
#PCDATA(および混合)要素用に提供されているメソッドを使用すると、データを設定したり、適切な場合は、要素の属性を設定することができます。
入力は、DTDを含むXML文書です。文書本体自体は無視されます。DTDのみが関連しますが、ダミー・ドキュメントはDTDに準拠する必要があります。基礎となるXMLパーサーのみが、ドキュメントのファイル名およびそれに対応付けられた外部エンティティを受け入れます。
表29-2に、XML C++ Class Generatorのデモ・ファイルを示します。
表29-2 XML C++ Class Generatorファイル
| ファイル名 | 説明 | 
|---|---|
| 
 
  | 
 サンプル・プログラム  | 
| 
 
  | 
 DTDおよびダミー・ドキュメントを含むXMLファイル  | 
| 
 
  | 
 sample.xmlが参照するDTDファイル  | 
| 
 
 
  | 
 クラスを生成し、サンプル・プログラムを構築する、バッチ・ファイル(Windowsの場合)またはMakeファイル(UNIXの場合)  | 
| 
 README  | 
 前述のファイルの説明を含むREADMEファイル  | 
Make.batバッチ・ファイル(Windowsの場合)またはMakefile(UNIXの場合)では、次の操作が実行できます。
sample.xmlに基づいて、クラスをSample.hおよびSample.cppに生成します。
(Sample.hを使用して)プログラムsample.cppをコンパイルし、サンプル・オブジェクトとともに...\bin(または.../bin)ディレクトリにあるCG.exeという実行可能ファイルにリンクします。
XMLファイルsample.xmlは、XML C++ Class Generatorを入力します。sample.xmlは、DTDファイルsample.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>
DTDファイルsample.dtdは、XMLファイルsample.xmlによって参照されます。sample.xmlは、XML C++ Class Generatorを入力します。
<!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)>
サンプル・プログラムsample.cppは、次のとおり実行します。
XMLパーサーを初期化します。
DTDを含むファイルのダミー・ドキュメント部分以外を解析することによって、DTDをロードします。
生成されたクラスを使用して複数のオブジェクトを作成します。
生成されたクラスがDTDに一致するかどうかを検証する、検証関数をコールします。
作成されたドキュメントを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