赤紫蘇2.

忍坂2(α)

akaxiso2.0-beta1


忍坂2は、XML-Schemaドキュメントから、シリアライザブルなクラスを生成するためのスキーマコンパイラです。

コマンドライン

osixaka2 [-p] [-d] [-o ディレクトリ名] [-D] [-L 設定ファイル名] [-S 設定ファイル名] <XML文書 ファイル>

オプション

オプション文字 意味

-p

スキーマファイルをパースするのみで終了する。
-d パースされたスキーマドキュメントを、シリアライズする。
-o <ディレクトリ名> 出力ディレクトリの指定。無指定の場合カレントディレクトリ
-v 詳細ログモード
-L <設定ファイル名> 与えられたプリファレンスファイルを読み込む。
-S <設定ファイル名> プリファレンスファイルを書き出す。
-D 与えられたXML文書からDTDを読み込み、XML-Schemaドキュメントに変換、書き出す。
-h ヘルプを表示

例として、忍坂2による、XML Schemaのためのスキーマ文書生成について説明します。

XMLSchemaは、以下の二つのスキーマ文書により定義されています。

名前空間URI ファイル名 オリジナルスキーマのURL
http://www.w3.org/2001/XMLSchema XMLSchema.xsd http://www.w3.org/2001/XMLSchema.xsd
http://www.w3.org/XML/1998/namespace xml.xsd http://www.w3.org/2001/xml.xsd

これらのファイルは、オリジナルのスキーマです。
忍坂2でのスキーマ生成では、以下の前処理を施す必要があります。

  • xs:include、xs:importなどで指定する外部スキーマ文書の位置を、処理対象となるスキーマ文書からの相対パスに変更
    • XMLSchema.xsdの場合には、xs:includeで指定されるxml.xsdのパスを相対パスに変更。

前処理を施したファイルは、akaxiso2/osixaka2以下にあります。このファイルを使用して、以下のコマンドを実行してください。

Windowsの場合(akaxiso2\binディレクトリにて)

akaxiso2\bin> osixaka2 ..\osixaka2\XMLSchema.xsd

Linuxの場合(akaxiso2/osixaka2ディレクトリにて)

$ ./osixaka2 XMLSchema.xsd

この操作により、element.h/xiso.h/xiso.cppの三つのファイルが生成されます。それぞれの内容を以下に示します。

ファイル名
内容
element.h シリアライザブルなクラスの宣言
シリアライズ関数の宣言
xiso.h leaf<>クラスの宣言
xiso.cpp leaf<>クラスの実装
シリアライズ関数の実装

以上のファイルをコンパイルし、赤紫蘇ライブラリとリンクすることで、XML Schemaドキュメントのシリアライズ、デシリアライズが可能となります。デシリアライズ、シリアライズするためのサンプルコードは、osixaka2/test_main.cpp(HTML版)をご参照ください。
(Linuxであれば、osixaka2ディレクトリで、make deserializerを行うことで、ビルドできます。)

設定ファイル

設定ファイルでは、以下の項目を設定可能です。設定ファイルは、XMLドキュメントです。
形式については、XML Schemaドキュメント、akaxiso2/osixaka2/preference.xsd をご参照ください。

設定項目 要素 値の例
aka:choiceのコンテナ choice_container std::vector、std::listなど
配列のコンテナ array_container std::vector、std::listなど
クラスメンバの書式 member_format @prefixで、メンバ名の接頭語を@postfixでメンバ名の接尾後を指定
<member_format prefix="m_"、postfix=""/>
とすると、m_member;のようなメンバ名が指定される。
配列の型名 array_format @prefixで、配列のtypedef名の接頭語を@postfixで接尾語を指定
<array_format prefix="array_of_" postfix="s"/>
とすると、
typedef std::vector<person> array_of_persons;
というふうに配列の型名が生成される。
単語の置換 substitution 単語の置換。XML Schema内で指定される名前が、C++の予約語と重なるような場合に用いる。
<substitution original="class" substituted="_class"/>
とすると、classが、_classに置換される。
文字の置換(エスケープ) escape '-'(ハイフン)など、XML Schemaで名前として使用可能な文字をエスケープする。
<escape to_escape="-" escaped="_"/>
と指定すると、"XML-Schema-Name"が、"XML_Schema_Name"と変換される。
名前空間 namespace 名前空間のプレフィックスとURIの対応付けを行う。
<namespace prefix="akaxiso" uri="http://akaxiso.sourceforgte.jp"/>
などとして用いる。
値を持たない型 nill_type 値を持たない型を指定
C++組み込み型のマッピング指定 cpp_builtins <type>要素により、XML Schemaの単純型を、C++組み込み型に対応付ける。
XML Schema単純型のマッピング指定 schema_builtins <type>要素により、XML Schemaの単純型を、C++クラスに対応付ける。
単純型からC++クラスへのマッピング指定 type type@nameにて、XML Schemaドキュメント中の型を指定。
type/cpp要素で対応するC++クラス名を指定
type/leaf要素で対応するleafクラス名を指定
type/array要素で、対応する配列クラスを指定。
type/array_leaf要素で対応する配列クラスのleafクラス名を指定。
type/leaf要素が省略されている場合には、xiso::leaf<C++クラス名>が用いられる。
type/array_leaf要素が省略されている場合には、leafクラス名として、<配列クラス名>_leafが用いられる。

設定ファイルの作成と使用

-S、-Lオプションを用いて、設定ファイルの作成と使用を行います。

設定ファイルの作成
$ osixaka2 -S preference.xml

設定ファイルの使用
$ osixaka2 -L preference.xml <XML Schemaドキュメントファイル名>

akaxiso2/osixaka2/osixaka1.xml ファイルは、旧忍坂と互換なファイルを生成するための設定ファイルです。

$ osixaka2 -L osixaka1.xml <XML Schemaドキュメントファイル名>

とすることで、(旧)忍坂と互換なファイルを生成することができます。

以下、デフォルトで使用される設定ファイルを示します。

<?xml version="1.0" encoding="Shift_JIS" standalone="yes"?>
<osx:preference xmlns:osx="http://akaxiso.sourceforge.jp/osixaka/preference">
  <choice_container type="std::list"/>
  <array_container type="std::list"/>
  <member_format prefix="" postfix="_"/>
  <array_format prefix="" postfix="_array"/>
  <substitution original="class" substituted="_class"/>
  <substitution original="public" substituted="_public"/>
  <substitution original="protected" substituted="_protected"/>
  <substitution original="private" substituted="_private"/>
  <substitution original="union" substituted="_union"/>
  <substitution original="enum" substituted="_enum"/>
  <substitution original="namespace" substituted="_namespace"/>
  <substitution original="using" substituted="_using"/>
  <escape to_escape="-" escaped="_"/>
  <namespace prefix="wsdl" uri="http://schemas.xmlsoap.org/wsdl/"/>
  <nill_type>aka:nill</nill_type>
  <cpp_builtins>
    <type name="xs:byte">
      <cpp>char</cpp>
      <array>aka:char_array</array>
    </type>
    <type name="xs:unsignedByte">
      <cpp>unsigned char</cpp>
      <array>aka:uchar_array</array>
    </type>
    <type name="xs:short">
      <cpp>short</cpp>
      <array>aka:short_array</array>
    </type>
    <type name="xs:unsignedShort">
      <cpp>short</cpp>
      <array>aka:short_array</array>
    </type>
    <type name="xs:int">
      <cpp>long</cpp>
      <array>aka:long_array</array>
    </type>
    <type name="xs:unsignedInt">
      <cpp>ULONGLONG</cpp>
      <array>aka:longlong_array</array>
    </type>
    <type name="xs:long">
      <cpp>LONGLONG</cpp>
      <array>aka:longlong_array</array>
    </type>
    <type name="xs:unsignedLong">
      <cpp>ULONGLONG</cpp>
      <array>aka:ulonglong_array</array>
    </type>
    <type name="xs:integer">
      <cpp>long</cpp>
      <array>aka:long_array</array>
    </type>
    <type name="xs:boolean">
      <cpp>bool</cpp>
      <array>aka:bool_array</array>
    </type>
    <type name="xs:float">
      <cpp>float</cpp>
      <array>aka:float_array</array>
    </type>
    <type name="xs:double">
      <cpp>double</cpp>
      <array>aka:double_array</array>
    </type>
    <type name="xs:string">
      <cpp>std:string</cpp>
      <array>aka:string_array</array>
    </type>
    <type name="xs:anySimpleType">
      <cpp>std:string</cpp>
      <array>aka:string_array</array>
    </type>
    <type name="aka:nill">
      <cpp>aka:nill</cpp>
      <array>aka:nill_array</array>
    </type>
  </cpp_builtins>
  <schema_builtins>
    <type name="xs:normalizedString">
      <cpp>std:string</cpp>
      <array>xs:normalizedString_array</array>
    </type>
    <type name="xs:token">
      <cpp>std:string</cpp>
      <array>xs:token_array</array>
    </type>
    <type name="xs:base64Binary">
      <cpp>std:string</cpp>
      <array>xs:base64Binary_array</array>
    </type>
    <type name="xs:hexBinary">
      <cpp>std:string</cpp>
      <array>xs:hexBinary_array</array>
    </type>
    <type name="xs:positiveInteger">
      <cpp>long</cpp>
      <array>xs:positiveInteger_array</array>
    </type>
    <type name="xs:negativeInteger">
      <cpp>long</cpp>
      <array>xs:negativeInteger_array</array>
    </type>
    <type name="xs:nonNegativeInteger">
      <cpp>long</cpp>
      <array>xs:nonNegativeInteger_array</array>
    </type>
    <type name="xs:nonPositiveInteger">
      <cpp>long</cpp>
      <array>xs:nonPositiveInteger_array</array>
    </type>
    <type name="xs:decimal">
      <cpp>long</cpp>
      <array>xs:decimal_array</array>
    </type>
    <type name="xs:time">
      <cpp>std:string</cpp>
      <array>xs:time_array</array>
    </type>
    <type name="xs:dateTime">
      <cpp>std:string</cpp>
      <array>xs:dateTime_array</array>
    </type>
    <type name="xs:duration">
      <cpp>std:string</cpp>
      <array>xs:duration_array</array>
    </type>
    <type name="xs:date">
      <cpp>std:string</cpp>
      <array>xs:date_array</array>
    </type>
    <type name="xs:gMonth">
      <cpp>std:string</cpp>
      <array>xs:gMonth_array</array>
    </type>
    <type name="xs:gYear">
      <cpp>std:string</cpp>
      <array>xs:gYear_array</array>
    </type>
    <type name="xs:gYearMonth">
      <cpp>std:string</cpp>
      <array>xs:gYearMonth_array</array>
    </type>
    <type name="xs:gDay">
      <cpp>std:string</cpp>
      <array>xs:gDay_array</array>
    </type>
    <type name="xs:gMonthDay">
      <cpp>std:string</cpp>
      <array>xs:gMonthDay_array</array>
    </type>
    <type name="xs:Name">
      <cpp>std:string</cpp>
      <array>xs:Name</array>
    </type>
    <type name="xs:QName">
      <cpp>aka:qname</cpp>
      <leaf>xs:QNameLeaf</leaf>
      <array>xs:QName_array</array>
    </type>
    <type name="xs:NCName">
      <cpp>std:string</cpp>
      <array>xs:NCName_array</array>
    </type>
    <type name="xs:anyURI">
      <cpp>std:string</cpp>
      <array>xs:anyURI_array</array>
    </type>
    <type name="xs:language">
      <cpp>std:string</cpp>
      <array>xs:language_array</array>
    </type>
    <type name="xs:ID">
      <cpp>std:string</cpp>
      <array>xs:ID_array</array>
    </type>
    <type name="xs:IDREF">
      <cpp>std:string</cpp>
      <array>xs:IDREF_array</array>
    </type>
    <type name="xs:IDREFS">
      <cpp>std:string</cpp>
      <array>xs:IDREFS_array</array>
    </type>
    <type name="xs:ENTITY">
      <cpp>std:string</cpp>
      <array>xs:ENTITY_array</array>
    </type>
    <type name="xs:ENTITIES">
      <cpp>std:string</cpp>
      <array>xs:ENTITIES_array</array>
    </type>
    <type name="xs:NOTATION">
      <cpp>std:string</cpp>
      <array>xs:NOTATION_array</array>
    </type>
    <type name="xs:NMTOKEN">
      <cpp>std:string</cpp>
      <array>xs:NMTOKEN_array</array>
    </type>
    <type name="xs:NMTOKENS">
      <cpp>std:string</cpp>
      <array>xs:NMTOKENS_array</array>
    </type>
  </schema_builtins>
</osx:preference>

仕様、制限、未実装部など

  • XML-Schema中の組込み型は、忍坂2により、C++クラスにマッピングされます。
    リファレンス 4.組み込み型を参照ください。また、これらの対応は、設定ファイルにより変更可能です。

  • xs:simpleTypeによる単純型の定義を用いた場合、生成される型は、std::stringのtypedef名となります。
    また、単純型の制限、拡張の定義について、妥当性検証ロジックはサポートされません。

  • 以下のタグ、属性は、サポートされません。
    • xs:keybase、xs:keyref、xs:substitutionGroup、mixed属性、

  • 以下のタグ、属性は、未実装です。
    • xs:redefine、abstract属性、final属性、block属性、blockDefault属性

  • complexContent以下におけるrestrictionの定義に関して、制約のチェックは、未実装です。

  • 赤紫蘇では、XMLSchemaで記述されるドキュメント構造を、より少ない数のクラスで表現できるようにしてあります。
    このため、XML Schemaで定義される文書をそのまま、C++のクラスへと変換すると冗長な宣言になります。このため、忍坂2では、内部でドキュメント構造の単純化、最適化を行っています。このロジックについては、より、詳細な実装を行う予定です。

  • xs:include、xs:importの処理時に指定されるschemaLocation属性は、処理対象のスキーマファイルからの相対パスで記述されるものとします。


ホームに戻る 赤紫蘇2プロジェクトページへ