
/** @mainpage
TinyXMLは、シンプルで小型のC++ XMLパーサーであり、他のプログラムに簡単に統合できます。
簡単に言えば、TinyXMLはXMLドキュメントを解析し、そこから読み取り、変更、保存が可能なDocument Object Model(DOM)を構築します。
XMLは「eXtensible Markup Language」の略です。これにより、独自のドキュメントマークアップを作成できます。HTMLがブラウザ向けのドキュメントマークアップに非常に優れているのに対し、XMLではあらゆる種類のドキュメントマークアップを定義できます。例えば、オーガナイザーアプリケーション用の「To Do」リストを記述するドキュメントなどです。XMLは非常に構造化された便利な形式です。アプリケーションデータを保存するために作成された、あらゆるランダムなファイル形式は、すべてXMLに置き換えることができます。すべてに一つのパーサーで済みます。
完全で正確、そして率直に言って読みにくい仕様書の最適な場所は、http://www.w3.org/TR/2004/REC-xml-20040204/です。XMLの入門(私がとても気に入っているもの)は、http://skew.org/xml/tutorialにあります。
XMLデータにアクセスして操作する方法はいくつかあります。TinyXMLはDocument Object Model(DOM)を使用します。つまり、XMLデータはC++オブジェクトに解析され、ブラウズや操作が可能になり、ディスクや他の出力ストリームに書き込めます。また、C++オブジェクトを使ってXMLドキュメントをゼロから構築し、ディスクや他の出力ストリームに書き込むこともできます。
TinyXMLは、簡単かつ迅速に習得できるように設計されています。2つのヘッダーファイルと4つのcppファイルで構成されています。これらをプロジェクトに追加するだけで、すぐに使用開始できます。入門用のサンプルファイル(xmltest.cpp)も用意されています。
TinyXMLはZLibライセンスの下でリリースされているため、オープンソースまたは商用コードで使用できます。ライセンスの詳細は、各ソースファイルの先頭に記載されています。
TinyXMLは柔軟なパーサーを目指していますが、真に正確で準拠したXML出力を提供します。TinyXMLは、合理的にC++に準拠したシステムであればコンパイルできるはずです。例外やRTTIに依存していません。STLサポートの有無にかかわらずコンパイル可能です。TinyXMLはUTF-8エンコーディングと、最初の64k文字エンティティを完全にサポートしています。
TinyXMLは、DTD(Document Type Definitions)やXSL(eXtensible Stylesheet Language)を解析したり使用したりしません。より充実した機能を備えた他のパーサー(www.sourceforge.orgをチェックして、XMLで検索してください)もあります。しかし、それらははるかに大きく、プロジェクトへのセットアップに時間がかかり、学習曲線が急で、多くの場合、より制限の厳しいライセンスを持っています。ブラウザを扱っている場合や、より完全なXMLのニーズがある場合、TinyXMLは適切なパーサーではありません。
以下のDTD構文は、現時点ではTinyXMLで解析されません。
@verbatim ]> @endverbatim
これは、TinyXMLがこれを!DOCTYPEノードと見なし、その中に!ELEMENTノードが不正に埋め込まれていると解釈するためです。これは将来対処される可能性があります。
急いでいる方のために、すぐに始められるチュートリアルを用意しました。始めるのに最適な方法ですが、この(非常に短い)マニュアルを完全に読む価値はあります。
TinyXMLは成熟した、テスト済みのコードです。非常に安定しています。バグを発見した場合は、sourceforgeウェブサイト(www.sourceforge.net/projects/tinyxml)にバグレポートを提出してください。できるだけ早く修正します。
改善すべき点もいくつかあります。TinyXMLの開発に興味があれば、sourceforgeをチェックしてください。
役立つかもしれないTinyXMLプロジェクト!(各プロジェクトの説明)
TinyXMLは、STLを使用するかしないかでコンパイルできます。STLを使用する場合、TinyXMLはstd::stringクラスを使用し、std::istream、std::ostream、operator<<、operator>>を完全にサポートします。多くのAPIメソッドには、'const char*'形式と'const std::string&'形式の両方があります。
STLサポートをコンパイルから除外すると、STLファイルは一切含まれません。すべての文字列クラスはTinyXML自身によって実装されます。APIメソッドはすべて、入力に'const char*'形式を使用します。
コンパイル時の#defineを使用します。
TIXML_USE_STL
これにより、一方のバージョンまたは他方のバージョンをコンパイルします。これはコンパイラに渡すか、"tinyxml.h"の最初の行として設定できます。
注意:Linuxでテストコードをコンパイルする場合、環境変数TINYXML_USE_STL=YES/NOを設定すると、STLコンパイルが制御されます。Windowsプロジェクトファイルでは、STLと非STLのターゲットが提供されています。あなたのプロジェクトでは、"tinyxml.h"の最初の行に "#define TIXML_USE_STL" を追加するのがおそらく最も簡単です。
TinyXMLはUTF-8をサポートしており、任意の言語のXMLファイルを操作できます。TinyXMLは「レガシーモード」(UTF-8サポート前のエンコーディングで、おそらく「拡張ASCII」と表現するのが最適)もサポートしています。
通常、TinyXMLは正しいエンコーディングを検出して使用しようとします。ただし、ヘッダーファイルでTIXML_DEFAULT_ENCODINGの値を設定することで、TinyXMLに常に1つのエンコーディングを使用するように強制できます。
TinyXMLは、次のいずれかが発生するまでレガシーモードを想定します。
エンコーディングが誤って設定または検出された場合はどうなりますか?TinyXMLは、不正にエンコードされたと見なされるテキストを読み取り、通過させようとします。奇妙な結果や文字化けが発生する可能性があります。TinyXMLを正しいモードに強制することをお勧めします。
LoadFile( TIXML_ENCODING_LEGACY ) または LoadFile( filename, TIXML_ENCODING_LEGACY ) を使用して、TinyXMLをレガシーモードに強制できます。TIXML_DEFAULT_ENCODING = TIXML_ENCODING_LEGACY を設定することで、常にレガシーモードを使用するように強制することもできます。同様に、同じ手法で TIXML_ENCODING_UTF8 に強制することもできます。
英語ユーザーにとって、英語のXMLを使用する場合、UTF-8は低ASCIIと同じです。UTF-8を意識したり、コードを変更する必要はありません。UTF-8はASCIIの「スーパーセット」と考えることができます。
UTF-8はダブルバイト形式ではありませんが、Unicodeの標準エンコーディングです!TinyXMLは現在、wchar、TCHAR、Microsoftの_UNICODEを使用または直接サポートしていません。「Unicode」という用語が、UnicodeのワイドバイトエンコーディングであるUTF-16を誤って指すことはよくあります。これは混乱の原因です。
「高ASCII」言語(英語以外のほぼすべての言語)の場合、TinyXMLは、XMLがUTF-8でエンコードされていれば、すべての言語を同時に処理できます。これは少し厄介です。古いプログラムやオペレーティングシステムは、「デフォルト」または「従来の」コードページを使用する傾向があります。多くのアプリ(そしてほとんどすべての現代的なアプリ)はUTF-8を出力できますが、古いアプリや頑固な(あるいは単に壊れた)アプリは、依然としてデフォルトのコードページでテキストを出力します。
例えば、日本語システムは伝統的にSHIFT-JISエンコーディングを使用します。SHIFT-JISでエンコードされたテキストは、TinyXMLで読み取ることができません。優れたテキストエディタはSHIFT-JISをインポートし、UTF-8として保存できます。
Skew.orgのリンクは、エンコーディングの問題をうまくカバーしています。
テストファイル「utf8test.xml」は、英語、スペイン語、ロシア語、簡体字中国語を含むXMLです。(うまく翻訳されていることを願っています)。ファイル「utf8test.gif」は、IEでレンダリングされたXMLファイルのスクリーンキャプチャです。システムに正しいフォント(簡体字中国語またはロシア語)がない場合、たとえ正しく解析できても、GIFファイルに一致する出力は表示されないことに注意してください。また、(少なくとも私のWindowsマシンでは)コンソール出力は西ヨーロッパのコードページであるため、Print()やprintf()ではファイルを正しく表示できません。これはTinyXMLのバグではなく、OSの問題です。TinyXMLによってデータが失われたり破損したりすることはありません。コンソールがUTF-8をレンダリングしないだけです。
@verbatim & & < < > > " " ' ' @endverbatim
これらはXMLドキュメントの読み取り時に認識され、UTF-8相当のものに変換されます。例えば、以下のXMLを含むテキストは、
@verbatim Far & Away @endverbatim
TiXmlTextオブジェクトからValue()を照会すると「Far & Away」となり、XMLストリーム/ファイルに書き戻されるときはアンパサンドとして書き込まれます。古いバージョンのTinyXMLは文字エンティティを「保存」していましたが、新しいバージョンでは文字に変換します。
さらに、任意の文字はUnicodeコードポイントで指定できます。構文「 」または「 」はどちらも改行しないスペース文字を表します。
Print( FILE* )。std-Cストリームへの出力。これにはすべてのCファイルとstdoutが含まれます。
operator<<。C++ストリームへの出力。
TiXmlPrinter。std::stringまたはメモリバッファへの出力。
Cスタイルの出力: - FILE* に基づく - Print() および SaveFile() メソッド
十分な空白を含むフォーマットされた出力を生成し、可能な限り人間が読みやすいように設計されています。非常に高速で、不正な形式のXMLドキュメントにも寛容です。例えば、2つのルート要素と2つの宣言を含むXMLドキュメントでも出力されます。
Cスタイルの入力: - FILE* に基づく - Parse() および LoadFile() メソッド
高速で寛容な読み取り。C++ストリームが必要ない場合は常にこれを使用してください。
C++スタイルの出力: - std::ostream に基づく - operator<<
可読性よりもネットワーク送信を目的とした、凝縮された出力を生成します。お使いのシステムのostreamクラスの実装によっては、やや遅くなる可能性があります(またはそうでない場合もあります)。不正な形式のXMLには寛容ではありません。ドキュメントには正しい1つのルート要素が含まれている必要があります。追加のルートレベルの要素はストリーム出力されません。
C++スタイルの入力: - std::istream に基づく - operator>>
ストリームからXMLを読み取るため、ネットワーク送信に役立ちます。難しいのは、ストリームにはほぼ確実に他のデータもあるため、XMLドキュメントがいつ完了したかを知ることです。TinyXMLは、ルート要素を読み取った後、XMLデータが完了したと見なします。言い換えれば、複数のルート要素を持つ不正な構造のドキュメントは正しく読み取られません。また、operator>>は、STLの実装とTinyXMLの制限の両方により、Parseよりも多少遅いことに注意してください。
これは、私が満足するまで解決されていない問題です。TinyXMLは最初の2つのアプローチをサポートしています。TiXmlBase::SetCondenseWhiteSpace( bool ) を呼び出して、希望する動作を設定します。デフォルトは空白を圧縮することです。
デフォルトを変更する場合は、XMLデータのParse呼び出しを行う前に TiXmlBase::SetCondenseWhiteSpace( bool ) を呼び出す必要があります。設定後に変更することはお勧めしません。
@verbatim TiXmlElement* root = document.FirstChildElement( "Document" ); if ( root ) { TiXmlElement* element = root->FirstChildElement( "Element" ); if ( element ) { TiXmlElement* child = element->FirstChildElement( "Child" ); if ( child ) { TiXmlElement* child2 = child->NextSiblingElement( "Child" ); if ( child2 ) { // ようやく何か役に立つことをする @endverbatim
これを整理するためにハンドルが導入されました。TiXmlHandleクラスを使用すると、上記のコードは次のように簡略化されます。
@verbatim TiXmlHandle docHandle( &document ); TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); if ( child2 ) { // 何か役に立つことをする @endverbatim
これにより、はるかに扱いやすくなります。詳細については、TiXmlHandleを参照してください。
TinyXMLは、テキストファイル内のすべてのノードと属性の行と列の起点を追跡できます。TiXmlBase::Row() および TiXmlBase::Column() メソッドは、ソーステキスト内のノードの起点を返します。正しいタブは、TiXmlDocument::SetTabSize() で設定できます。
xmltestをコンパイルして実行するには:
Linux用のMakefileとWindows Visual C++ .dswファイルが提供されています。単純にコンパイルして実行してください。デモテストファイルdemotest.xmlがディスクに書き込まれ、画面に出力が生成されます。また、異なる手法を使用して見つかったノードの数を出力することで、DOMの走査もテストします。
Linuxのmakefileは非常に汎用的で、多くのシステムで動作します(現在はmingwとMacOSXでテストされています)。'make depend'を実行する必要はありません。依存関係はハードコードされています。
PROFILE, DEBUG, TINYXML_USE_STL。詳細はmakefileに記載されています。
tinyxmlディレクトリで、"make clean" を実行し、次に "make" を実行します。実行ファイル 'xmltest' が作成されます。
tinyxml.cpp, tinyxml.h, tinyxmlerror.cpp, tinyxmlparser.cpp, tinystr.cpp, tinystr.h をプロジェクトまたはmakeファイルに追加します。これだけです!合理的にC++準拠のシステムであればコンパイルできるはずです。TinyXMLのために例外やRTTIを有効にする必要はありません。
例を示すのがおそらく最良の方法です。次のものを考えてみましょう。 @verbatim <?xml version="1.0" standalone=no> おもちゃ屋に行く! 請求書を処理する @endverbatim
これは大したTo Doリストではありませんが、例としては十分です。このファイル("demo.xml" とします)を読み取るには、ドキュメントを作成し、解析します。 @verbatim TiXmlDocument doc( "demo.xml" ); doc.LoadFile(); @endverbatim
これで準備完了です。次に、いくつかの行とそれらがDOMにどのように関連するかを見てみましょう。
@verbatim
@endverbatim 最初の行は宣言であり、TiXmlDeclarationクラスに変換されます。これはドキュメントノードの最初の子になります。 これは、TinyXMLによって解析される唯一のディレクティブ/特別なタグです。通常、ディレクティブタグはTiXmlUnknownに保存されるため、ディスクに保存し直すときにコマンドが失われることはありません。 @verbatim @endverbatim コメント。TiXmlCommentオブジェクトになります。 @verbatim @endverbatim "ToDo"タグはTiXmlElementオブジェクトを定義します。このタグには属性はありませんが、他の2つの要素が含まれています。 @verbatim @endverbatim "ToDo"要素の子である別のTiXmlElementを作成します。この要素には1つの属性があり、名前は"priority"、値は"1"です。 @verbatim おもちゃ屋に @endverbatim TiXmlText。これはリーフノードであり、他のノードを含めることはできません。"Item" TiXmlElementの子です。 @verbatim @endverbatim 別のTiXmlElement。今回は"Item"要素の子です。 以下同様です。 オブジェクトツリー全体を見ると、次のようになります。 @verbatim TiXmlDocument "demo.xml" TiXmlDeclaration "version='1.0'" "standalone=no" TiXmlComment " 私たちのTo Doリストデータ" TiXmlElement "ToDo" TiXmlElement "Item" 属性: priority = 1 TiXmlText "おもちゃ屋に " TiXmlElement "bold" TiXmlText "行く!" TiXmlElement "Item" 属性: priority=2 TiXmlText "請求書を処理する" @endverbatim