4. 文書の読み込み
pugixmlには、ファイル、C++ iostream、メモリーバッファなど、さまざまな場所からXMLデータを読み込む関数があります。すべての関数は、妥当性検証を行わない非常に高速なパーサーを使います。このパーサーはW3C仕様に完全には準拠していません。有効なXML文書はすべて読み込めますが、一部の整形式性の検査は行いません。不正なXML文書を拒否するために相当の努力が払われていますが、性能上の理由から一部の検証を省いています。また、改行処理や属性値の正規化など、一部のXML変換は解析速度に影響するため、無効にできます。ただし、XML文書の大多数では、解析オプションによる性能の違いはありません。解析オプションは、特定のXMLノードを解析するかどうかも制御します。詳しくは解析オプションを参照してください。
XMLデータは、解析前に必ず内部の文字形式へ変換されます(Unicodeインターフェースを参照)。pugixmlは、広く使われているすべてのUnicodeエンコーディング(UTF-8、UTF-16のビッグエンディアンとリトルエンディアン、UTF-32のビッグエンディアンとリトルエンディアン)と、一部の非Unicodeエンコーディング(Latin-1)に対応し、すべてのエンコーディング変換を自動で処理します。UCS-2はUTF-16の厳密な部分集合なので、当然ながら対応しています。エンコーディングを明示しない限り、読み込み関数はXMLの原データからエンコーディングを自動検出するため、ほとんどの場合、文書のエンコーディングを指定する必要はありません。変換の詳細はエンコーディングで説明します。
4.1. ファイルからの文書の読み込み
XMLデータの読み込み元として最も一般的なのはファイルです。pugixmlには、ファイルからXML文書を読み込む専用の関数があります。
xml_parse_result xml_document::load_file(const char* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
xml_parse_result xml_document::load_file(const wchar_t* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);これらの関数は、第1引数にファイルパスを取り、ほかに省略可能な引数が2つあります。これらは解析オプション(解析オプションを参照)と入力データのエンコーディング(エンコーディングを参照)を指定します。パスは対象OSの形式に従います。相対パスでも絶対パスでも構いませんが、対象システムの区切り文字を使い、ファイルシステムが大文字と小文字を区別する場合には正確な文字の大小を指定するなどの必要があります。
最初の関数(const char* pathを受け取るもの)は、システムのファイルオープン関数へパスをそのまま渡します。2番目の関数は、ランタイムライブラリが専用のファイルオープン関数を提供していればそれを使い、それ以外の場合はパスをUTF-8へ変換してシステムのファイルオープン関数を使います。
load_fileは既存の文書ツリーを破棄してから、指定したファイルから新しいツリーを読み込もうとします。操作結果はxml_parse_resultオブジェクトとして返されます。このオブジェクトには、操作の状態と、それに関連する情報(解析に失敗した場合は、入力ファイル内の解析に成功した最後の位置など)が含まれます。エラー処理の詳細は解析エラーの処理を参照してください。
ファイルからXML文書を読み込む例です(samples/load_file.cpp)。
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file("tree.xml");
std::cout << "Load result: " << result.description() << ", mesh name: " << doc.child("mesh").attribute("name").value() << std::endl;
4.2. メモリーからの文書の読み込み
XMLデータをファイル以外、たとえばHTTP URLから読み込む必要がある場合もあります。また、仮想ファイルシステムの機能を使ったり、GZip圧縮ファイルからXMLを読み込んだりするために、標準以外の関数でファイルを読み込みたい場合もあります。これらの場合はいずれも、文書をメモリーから読み込む必要があります。まず、XMLデータ全体を含む連続したメモリーブロックを用意し、次にバッファ読み込み関数のいずれかを呼び出してください。これらの関数は、必要であればエンコーディング変換を処理した後、データを解析して対応するXMLツリーを作ります。バッファ読み込み関数にはいくつかあり、動作が異なるため、性能やメモリー使用量も異なります。
xml_parse_result xml_document::load_buffer(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
xml_parse_result xml_document::load_buffer_inplace(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
xml_parse_result xml_document::load_buffer_inplace_own(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);すべての関数は、XMLデータへのポインターcontentsと、バイト単位のデータサイズで表されるバッファを受け取ります。また、解析オプション(解析オプションを参照)と入力データのエンコーディング(エンコーディングを参照)を指定する、省略可能な引数が2つあります。バッファはゼロ終端である必要はありません。
load_bufferは変更不可のバッファを扱い、バッファを変更することは一切ありません。この制約のため、解析前に専用のバッファを作ってXMLデータをコピーしなければなりません。必要であればエンコーディング変換も適用します。このコピー操作には性能上の負担があるため、インプレース関数load_buffer_inplaceとload_buffer_inplace_ownが用意されています。これらは文書データをバッファに保持し、その過程でバッファを変更します。インプレース関数を使う場合は、文書を有効に保つため、バッファの寿命がツリーの寿命より長いことを保証しなければなりません。さらに、load_buffer_inplaceはバッファの所有権を引き受けないため、自分で破棄する必要があります。load_buffer_inplace_ownは所有権を引き受け、不要になった時点でバッファを破棄します。このため、load_buffer_inplace_ownを使う場合は、pugixmlの割り当て関数でメモリーを割り当てなければなりません。この関数はget_memory_allocation_functionで取得できます。
性能とメモリーの面で最善の方法は、load_buffer_inplace_ownで文書を読み込むことです。この関数はXMLデータを含むバッファを最大限に制御できるため、不要なコピーを避け、解析中のピークメモリー使用量を減らせます。メモリーから文書を読み込む必要があり、性能が重要な場合には、この関数を推奨します。
null終端の文字列からXML文書を読み込みたい場合には、単純な補助関数もあります。
xml_parse_result xml_document::load_string(const char_t* contents, unsigned int options = parse_default);これは、文字型に応じてsizeにstrlen(contents)またはwcslen(contents) * sizeof(wchar_t)を指定して、load_bufferを呼び出すことと同じです。この関数は入力データをネイティブエンコーディングと仮定するため、エンコーディング変換を行いません。一般に、文字列リテラルから小さい文書を読み込む用途には適していますが、バッファ読み込み関数よりオーバーヘッドが大きく、機能も少なくなります。
各種関数でメモリーからXML文書を読み込む例です(samples/load_memory.cpp)。
const char source[] = "<mesh name='sphere'><bounds>0 0 1 1</bounds></mesh>";
size_t size = sizeof(source);// You can use load_buffer to load document from immutable memory block:
pugi::xml_parse_result result = doc.load_buffer(source, size);// You can use load_buffer_inplace to load document from mutable memory block; the block's lifetime must exceed that of document
char* buffer = new char[size];
memcpy(buffer, source, size);
// The block can be allocated by any method; the block is modified during parsing
pugi::xml_parse_result result = doc.load_buffer_inplace(buffer, size);
// You have to destroy the block yourself after the document is no longer used
delete[] buffer;// You can use load_buffer_inplace_own to load document from mutable memory block and to pass the ownership of this block
// The block has to be allocated via pugixml allocation function - using i.e. operator new here is incorrect
char* buffer = static_cast<char*>(pugi::get_memory_allocation_function()(size));
memcpy(buffer, source, size);
// The block will be deleted by the document
pugi::xml_parse_result result = doc.load_buffer_inplace_own(buffer, size);// You can use load to load document from null-terminated strings, for example literals:
pugi::xml_parse_result result = doc.load_string("<mesh name='sphere'><bounds>0 0 1 1</bounds></mesh>");
4.3. C++ IOstreamからの文書の読み込み
相互運用性を高めるため、pugixmlには、C++のstd::istreamインターフェースを実装した任意のオブジェクトから文書を読み込む関数があります。これにより、標準のC++ストリーム(ファイルストリームなど)や、インターフェースに準拠した第三者の実装(Boost Iostreamsなど)から文書を読み込めます。関数は2つあり、一方はナロー文字ストリーム、もう一方はワイド文字ストリームを扱います。
xml_parse_result xml_document::load(std::istream& stream, unsigned int options = parse_default, xml_encoding encoding = encoding_auto);
xml_parse_result xml_document::load(std::wistream& stream, unsigned int options = parse_default);std::istream引数を取るloadは、現在の読み取り位置からストリームの末尾まで文書を読み込みます。ストリームの内容を、指定したエンコーディングのバイトストリームとして扱い、必要に応じてエンコーディングを自動検出します。そのため、開いているstd::ifstreamオブジェクトに対してxml_document::loadを呼び出すことは、xml_document::load_fileを呼び出すことと同じです。
std::wistream引数を取るloadは、ストリームの内容をワイド文字ストリームとして扱います。エンコーディングは常にencoding_wcharです。このため、ワイド文字ストリームでloadを使う場合は、imbue関数の使用など、慎重なストリーム設定が必要です。通常、この設定はプラットフォーム固有です。一般に、ワイド文字ストリームの使用は勧めませんが、Unicode以外のエンコーディングから文書を読み込むことができます。たとえば、適切なロケールを設定すると、Shift-JISのデータを読み込めます。
ストリームを使ってファイルからXML文書を読み込む簡単な例です(samples/load_stream.cpp)。ワイド文字ストリームやロケールを使う、より複雑な例はサンプルコードを読んでください。
std::ifstream stream("weekly-utf-8.xml");
pugi::xml_parse_result result = doc.load(stream);
4.4. 解析エラーの処理
文書読み込み関数はすべて、xml_parse_resultオブジェクトを通じて解析結果を返します。このオブジェクトには、解析状態、元のストリームの先頭から解析に成功した最後の文字までのオフセット、元のストリームのエンコーディングが含まれます。
struct xml_parse_result
{
xml_parse_status status;
ptrdiff_t offset;
xml_encoding encoding;
operator bool() const;
const char* description() const;
}; 解析状態はxml_parse_status列挙型で表され、次のいずれかになります。
-
status_okは、解析中にエラーが発生しなかったことを意味します。元のストリームは有効なXML文書を表し、全体が解析されてツリーへ変換されています。 -
status_file_not_foundはload_file関数からのみ返され、ファイルを開けなかったことを意味します。 -
status_io_errorは、load_file関数と、std::istreamまたはstd::wistream引数を取るload関数から返されます。ファイルやストリームの読み取り中にI/Oエラーが発生したことを意味します。 -
status_out_of_memoryは、いずれかの割り当て時にメモリーが足りなかったことを意味します。解析中の割り当て失敗は、すべてこのエラーになります。 -
status_internal_errorは、何かが深刻に失敗したことを意味します。現在、このエラーは発生しません。 -
status_unrecognized_tagは、タグの名前が空であるか、#などの不正な文字で始まっているために解析が停止したことを意味します。 -
status_bad_piは、不正な文書宣言や処理命令のために解析が停止したことを意味します。 -
status_bad_comment、status_bad_cdata、status_bad_doctype、status_bad_pcdataは、それぞれの型の構造が不正なために解析が停止したことを意味します。 -
status_bad_start_elementは、開始タグに閉じる>がないか、不正な記号が含まれているために解析が停止したことを意味します。 -
status_bad_attributeは、値がない属性や値が引用符で囲まれていない属性など、不正な属性のために解析が停止したことを意味します。<node attr=1>はXMLでは不正です。 -
status_bad_end_elementは、終了タグの構文が不正なために解析が停止したことを意味します。たとえば、タグ名と>の間に余分な非空白文字がある場合です。 -
status_end_element_mismatchは、終了タグが開始タグと一致しない(例:<node></nedo>)か、タグがまったく閉じられていないために解析が停止したことを意味します。 -
status_no_document_elementは、解析中に要素ノードが見つからなかったことを意味します。通常は、空または不正な文書を示します。
description()メンバー関数は、解析状態を文字列へ変換するために使えます。返されるメッセージは常に英語なので、翻訳された文字列が必要であれば、独自の関数を書く必要があります。ただし、description()が返す正確なメッセージは版によって変わることがあるため、複雑な状態処理はstatusの値に基づいて行ってください。また、description()はPUGIXML_WCHAR_MODEでもchar文字列を返します。wchar_t文字列を得るには、as_wideを呼び出す必要があります。
元のデータが有効なXMLでないために解析に失敗しても、結果のツリーは破棄されません。読み込み関数がエラーを返していても、解析に成功した部分のツリーは使えます。ただし、最後の要素の名前や値が予想外のものになる場合があります。たとえば、<node attr="value>some data</node>のように属性値が必要な引用符で終わっていない場合、属性attrの値にはvalue>some data</node>という文字列が含まれます。
解析結果には状態コードに加えてoffsetメンバーがあります。元のデータのエラーで解析に失敗した場合は、解析に成功した最後の文字のオフセットが含まれ、それ以外の場合はoffsetは0です。解析効率のため、pugixmlは解析中に現在の行を追跡しません。このオフセットの単位はpugi::char_tで、charモードではバイト、ワイド文字モードではワイド文字です。多くのテキストエディターには'Go To Position'機能があり、正確なエラー位置を探すために使えます。また、メモリーから文書を読み込む場合は、エラーの説明と一緒に該当部分を表示できます。下のコード例を参照してください。
注意
|
オフセットは、ネイティブエンコーディングのXMLバッファ内で計算されます。解析時にエンコーディング変換を行う場合、このオフセットでエラー位置を確実に追跡することはできません。 |
解析結果にはencodingメンバーもあり、元のデータのエンコーディングが正しく推定されたかを確認できます。この値は、エンディアンも含めて、実際に解析に使われた正確なエンコーディングと等しくなります。詳しくはエンコーディングを参照してください。
解析結果オブジェクトは暗黙にboolへ変換できます。解析エラーを詳細に処理する必要がなければ、読み込み関数の戻り値をif (doc.load_file("file.xml")) { … } else { … }のようにboolとして調べるだけで構いません。
読み込みエラーを処理する例です(samples/load_error_handling.cpp)。
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_string(source);
if (result)
{
std::cout << "XML [" << source << "] parsed without errors, attr value: [" << doc.child("node").attribute("attr").value() << "]\n\n";
}
else
{
std::cout << "XML [" << source << "] parsed with errors, attr value: [" << doc.child("node").attribute("attr").value() << "]\n";
std::cout << "Error description: " << result.description() << "\n";
std::cout << "Error offset: " << result.offset << " (error at [..." << (source + result.offset) << "]\n\n";
}
4.5. 解析オプション
文書読み込み関数はすべて、省略可能なoptionsパラメーターを受け取ります。これは解析処理を調整するビットマスクで、解析するノード型と、XMLテキストに適用する各種変換を選べます。一部の変換を無効にすると、文書によっては解析性能が向上することがあります。ただし、すべての変換処理は十分に最適化されているため、大多数の文書では性能上の利点はありません。目安として、既定では除外されるノード(宣言やコメントなど)を文書に含めたい場合にだけ、解析フラグを変更してください。
注記
|
ビットマスクの操作には、通常のビット演算を使ってください。フラグを有効にするにはmask | flag、無効にするにはmask & ~flagを使います。 |
次のフラグは、結果のツリーの内容を制御します。
-
parse_declarationは、XML文書宣言(node_declaration型のノード)をDOMツリーに入れるかどうかを決めます。無効の場合、ツリーには入りませんが、解析と正しさの検査は引き続き行われます。既定では無効です。 -
parse_doctypeは、XML文書型宣言(node_doctype型のノード)をDOMツリーに入れるかどうかを決めます。無効の場合、ツリーには入りませんが、解析と正しさの検査は引き続き行われます。既定では無効です。 -
parse_piは、処理命令(node_pi型のノード)をDOMツリーに入れるかどうかを決めます。無効の場合、ツリーには入りませんが、解析と正しさの検査は引き続き行われます。<?xml …?>(文書宣言)はPIとは見なされません。既定では無効です。 -
parse_commentsは、コメント(node_comment型のノード)をDOMツリーに入れるかどうかを決めます。無効の場合、ツリーには入りませんが、解析と正しさの検査は引き続き行われます。既定では無効です。 -
parse_cdataは、CDATAセクション(node_cdata型のノード)をDOMツリーに入れるかどうかを決めます。無効の場合、ツリーには入りませんが、解析と正しさの検査は引き続き行われます。既定では有効です。 -
parse_trim_pcdataは、PCDATAノードの先頭と末尾の空白文字を取り除くかどうかを決めます。アプリケーションによっては先頭や末尾の空白が重要ですが、多くの場合、空白以外の内容だけが必要なので、解析時にテキストの空白を取り除く方が扱いやすくなります。既定では無効です。 -
parse_ws_pcdataは、空白文字だけからなるPCDATAノード(node_pcdata型のノード)をDOMツリーに入れるかどうかを決めます。多くの場合、空白だけのデータはアプリケーションにとって重要ではなく、こうしたノードの割り当てと保持には、メモリーと速度の両面で大きな負担がかかることがあります。たとえば、XML文字列<node> <a/> </node>を解析すると、parse_ws_pcdataを設定した場合、<node>要素は3個の子を持ちます。値が" "のnode_pcdata型の子、名前が"a"のnode_element型の子、そして値が" "の別のnode_pcdata型の子です。parse_ws_pcdataを設定しない場合は、子は1個だけです。既定では無効です。 -
parse_ws_pcdata_singleは、兄弟ノードを持たない、空白だけのPCDATAノードをDOMツリーに入れるかどうかを決めます。たとえば<node> </node>のようなノードの空白だけの内容を解析する必要があり、それ以外の空白マークアップには関心がない場合があります。parse_ws_pcdataフラグも使えますが、余分な割り当てが発生し、文書処理も複雑になります。このフラグを使うと、それを避けられます。たとえば、parse_ws_pcdata_singleを設定してXML文字列<node> <a> </a> </node>を解析すると、<node>要素の子は<a>の1個だけになり、<a>要素の子は、値が" "のnode_pcdata型の1個だけになります。parse_ws_pcdataが有効な場合、このフラグは効果を持ちません。既定では無効です。 -
parse_embed_pcdataは、PCDATAの内容を要素の値として保存するかどうかを決めます。通常、要素ノードは名前を持ちますが値は持ちません。このフラグを指定すると、PCDATAが要素ノードの最初の子である場合、その内容を値として保存します。それ以外の場合は、通常どおりPCDATAノードを作ります。これにより、PCDATAノードの多い文書で必要なメモリーを大幅に減らせます。データの取得には、要素ノードのxml_node::value()や、child_value、textなどの高水準の関数を使えます。このフラグはDOM構造を大きく変えるため、メモリーが限られた環境で、PCDATAノードの多い文書を解析する場合にだけ推奨します。既定では無効です。 -
parse_merge_pcdataは、間にノードがなければ、PCDATAの内容を直前のPCDATAノードと結合するかどうかを決めます。PCDATAの間にCDATAセクション、PIノード、コメントがあり、parse_cdata、parse_pi、parse_commentsのいずれかが設定されていない場合、PCDATAノードの内容は直前のものと結合されます。既定では無効です。このフラグはparse_embed_pcdataと互換性がありません。 -
parse_fragmentは、文書を有効なXMLのフラグメントとして扱うかどうかを決めます。フラグメントとして解析すると、最上位のPCDATAの内容(ノードの内部にないテキスト)がツリーへ追加されます。また、要素ノードのない文書も有効として扱い、最上位の要素ノードを複数持つことも認めます。現在は、このフラグが無効でも最上位の要素ノードを複数持つことが認められていますが、その動作には依存しないでください。既定では無効です。
注意
|
parse_fragmentフラグとインプレース解析(load_buffer_inplace)を併用すると、バッファの最後の文字がPCDATAの一部である場合、その文字が失われることがあります。PCDATAの値はnull終端文字列なので、これを解決する唯一の方法は、null終端のバッファをload_buffer_inplaceへの入力として渡すことです。たとえばdoc.load_buffer_inplace("test\0", 5, pugi::parse_default | pugi::parse_fragment)です。 |
次のフラグは、ツリー要素の内容の変換を制御します。
-
parse_escapesは、解析時に文字参照と実体参照を展開するかどうかを決めます。文字参照の形式は&#…;または&#x…;で、…は文字のUnicode数値表現を10進数(&#…;)または16進数(&#x…;)で表したものです。実体参照は<、>、&、'、"です。pugixmlはDTDを処理しないため、使える実体はあらかじめ定義されたものだけです。文字参照や実体参照を展開できない場合は、そのまま残るので、後から追加の処理を行えます。参照の展開は属性値とPCDATAの内容に対して行われます。既定では有効です。 -
parse_eolは、入力データ(コメント内容、PCDATA・CDATA内容、属性値)に改行処理を行うかどうかを決めます。改行処理とは、\r\nを1文字の\nへ置き換え、単独の\rをすべて\nへ置き換えることです。既定では有効です。 -
parse_wconv_attributeは、すべての属性について属性値の正規化を行うかどうかを決めます。これは、空白文字(改行、タブ、スペース)をスペース(' ')へ置き換えることを意味します。改行文字は常にparse_eolが設定されているかのように扱われ、\r\nは1個のスペースへ変換されます。既定では有効です。 -
parse_wnorm_attributeは、すべての属性について拡張した属性値の正規化を行うかどうかを決めます。parse_wconv_attributeを設定した場合と同じ正規化の後に、先頭と末尾のスペースを除去し、連続するスペースをすべて1個のスペースに置き換えます。このフラグが有効な場合、parse_wconv_attributeは効果を持ちません。既定では無効です。
注記
|
parse_wconv_attributeオプションは、CDATAとして宣言された属性についてW3C仕様が要求する変換を行います。parse_wnorm_attributeは、NMTOKENS属性に必要な変換を行います。文書型宣言がない場合、すべての属性はCDATAとして宣言されたかのように振る舞うべきなので、parse_wconv_attributeが既定のオプションです。 |
さらに、あらかじめ定義されたオプションマスクが3つあります。
-
parse_minimalは、すべてのオプションを無効にします。このマスクでは、pugixmlは結果のツリーに宣言ノード、文書型宣言ノード、PIノード、CDATAセクション、コメントを追加せず、入力データの変換も行いません。そのため、理論上は最速のモードです。ただし、前述のとおり、実際にはparse_defaultも通常は同じ速さです。 -
parse_defaultは、すべてのオプションを既定値に設定した、既定のフラグ集合です。CDATAセクションの解析(コメントとPIは解析しません)、文字参照と実体参照の展開、属性値の空白文字からスペースへの置き換え、改行処理が含まれます。性能上の理由から、空白文字だけのPCDATAセクションは既定では解析されません。 -
parse_fullは、すべての型のノードを結果のツリーに追加し、入力データに既定の変換を行うフラグ集合です。CDATAセクション、コメント、PIノード、文書宣言ノード、文書型宣言ノードの解析、文字参照と実体参照の展開、属性値の空白文字からスペースへの置き換え、改行処理が含まれます。このモードでも、空白文字だけのPCDATAセクションは解析されません。
各種解析オプションを使う例です(samples/load_options.cpp)。
const char* source = "<!--comment--><node><</node>";
// Parsing with default options; note that comment node is not added to the tree, and entity reference < is expanded
doc.load_string(source);
std::cout << "First node value: [" << doc.first_child().value() << "], node child value: [" << doc.child_value("node") << "]\n";
// Parsing with additional parse_comments option; comment node is now added to the tree
doc.load_string(source, pugi::parse_default | pugi::parse_comments);
std::cout << "First node value: [" << doc.first_child().value() << "], node child value: [" << doc.child_value("node") << "]\n";
// Parsing with additional parse_comments option and without the (default) parse_escapes option; < is not expanded
doc.load_string(source, (pugi::parse_default | pugi::parse_comments) & ~pugi::parse_escapes);
std::cout << "First node value: [" << doc.first_child().value() << "], node child value: [" << doc.child_value("node") << "]\n";
// Parsing with minimal option mask; comment node is not added to the tree, and < is not expanded
doc.load_string(source, pugi::parse_minimal);
std::cout << "First node value: [" << doc.first_child().value() << "], node child value: [" << doc.child_value("node") << "]\n";
4.6. エンコーディング
pugixmlは、広く使われているすべてのUnicodeエンコーディング(UTF-8、UTF-16のビッグエンディアンとリトルエンディアン、UTF-32のビッグエンディアンとリトルエンディアン)と、一部の非Unicodeエンコーディング(Latin-1)に対応し、すべてのエンコーディング変換を処理します。UCS-2はUTF-16の厳密な部分集合なので、当然ながら対応しています。ほとんどの読み込み関数は、省略可能なencodingパラメーターを受け取ります。これはxml_encoding列挙型の値で、次のいずれかになります。
-
encoding_autoは、XMLの原データからエンコーディングの推定を試みることを意味します。このアルゴリズムは、XML勧告の附録Fに示されたものを変更したものです。まず、対応するエンコーディングのいずれかのバイト順マークを探します。見つからなければ、入力の先頭数バイトが、UTF-16またはUTF-32のいずれかの形式の<や<?に見えるかを調べます。それでも分からなければ、UTF-8か非Unicodeエンコーディングのいずれかと仮定します。最終的な判断のために、XML文書宣言のencoding属性の解析を試み、文書宣言がないか、対応するエンコーディングを指定していない場合は、最終的にUTF-8を使います。 -
encoding_utf8は、Unicode標準で定義されたUTF-8エンコーディングに対応します。長さが5または6のUTF-8シーケンスは標準ではないため、拒否されます。 -
encoding_utf16_leは、Unicode標準で定義されたリトルエンディアンのUTF-16エンコーディングに対応します。サロゲートペアにも対応しています。 -
encoding_utf16_beは、Unicode標準で定義されたビッグエンディアンのUTF-16エンコーディングに対応します。サロゲートペアにも対応しています。 -
encoding_utf16は、Unicode標準で定義されたUTF-16エンコーディングに対応します。エンディアンは、対象プラットフォームと同じと仮定します。 -
encoding_utf32_leは、Unicode標準で定義されたリトルエンディアンのUTF-32エンコーディングに対応します。 -
encoding_utf32_beは、Unicode標準で定義されたビッグエンディアンのUTF-32エンコーディングに対応します。 -
encoding_utf32は、Unicode標準で定義されたUTF-32エンコーディングに対応します。エンディアンは、対象プラットフォームと同じと仮定します。 -
encoding_wcharは、wchar_t型のエンコーディングに対応します。wchar_tのサイズに応じて、encoding_utf16またはencoding_utf32と同じ意味になります。 -
encoding_latin1は、ISO-8859-1エンコーディング(Latin-1とも呼ばれます)に対応します。
encoding_autoのアルゴリズムは、すべての整形式XML文書(文書宣言で始まるため)と、<で始まるその他のすべてのXML文書について、対応するUnicodeエンコーディングを正しく検出します。XML文書が<で始まらず、UTF-8以外のエンコーディングを使う場合は、エンコーディングを具体的に指定してください。
注記
|
現在のUnicode変換は、変換中に不正なUTFシーケンスをすべて読み飛ばします。この動作には依存しないでください。また、エンコーディング変換を行わない場合、不正なシーケンスは除去されず、ノードや属性の内容にそのまま含まれます。 |
4.7. W3C仕様への準拠
pugixmlはW3C仕様に完全には準拠していません。有効なXML文書はすべて読み込めますが、一部の整形式性の検査は行いません。不正なXML文書を拒否するために相当の努力が払われていますが、性能上の理由から一部の検証を省いています。
有効なXML文書を扱う場合の非準拠動作は1つだけです。pugixmlは解析時に、文書型宣言で提供された情報を使いません。このため、DOCTYPEで宣言された実体は展開されず、すべての属性値・PCDATA値は、解析オプションだけに依存する一律の方法で処理されます。
不正なXML文書の拒否については、次のものを含め、W3C仕様と一致しない点がいくつかあります。
-
同じノードの複数の属性が、同じ名前を持つことがあります。
-
タグ名と属性名が許可された文字だけで構成されるかどうかを完全には検証しないため、一部の不正なタグは拒否されません。
-
<を含む属性値は拒否されません。 -
不正な実体参照や文字参照は拒否されず、そのまま残されます。
-
コメントの値に
--を含められます。 -
XMLデータは文書宣言で始まる必要がなく、文書宣言がコメントやその他のノードの後に現れることもあります。
-
不正な文書型宣言は、場合によっては通知せず無視されます。
-
Unicodeの検証は行われないため、不正なUTFシーケンスは拒否されません。
-
文書は最上位の要素ノードを複数含められます。