"xml.parsers.expat" --- Expat を使用した高速な XML 解析
*******************************************************

======================================================================

注釈:

  信頼できないデータや認証されていないデータを解析する場合は、XML のセ
  キュリティ を参照してください。

"xml.parsers.expat" モジュールは、妥当性検証を行わない XML パーサー
Expat の Python インターフェースです。 XML パーサーの現在の状態を表す
"xmlparser" という単一の拡張型を提供します。 "xmlparser" オブジェクト
を作成したら、その各種属性にハンドラー関数を設定できます。 その後 XML
文書をパーサーに渡すと、文書内の文字データやマークアップに応じてハンド
ラー関数が呼び出されます。

このモジュールでは、Expatパーザへのアクセスを提供するために "pyexpat"
モジュールを使用します。 "pyexpat" モジュールの直接使用は非推奨です。

このモジュールは次の例外、型オブジェクト、データ項目を提供します。

exception xml.parsers.expat.ExpatError

   Expat がエラーを報告したときに例外を送出します。 Expatのエラーを解
   釈する上での詳細な情報は、 ExpatError 例外 を参照してください。

exception xml.parsers.expat.error

   "ExpatError" の別名です。

xml.parsers.expat.XMLParserType

   "ParserCreate()" 関数から返された戻り値の型を示します。

xml.parsers.expat.EXPAT_VERSION

   インタープリタが読み込んだ Expat ライブラリのバージョン文字列です。
   例えば "'expat_2.8.4'" のようになります。

xml.parsers.expat.version_info

   インタープリタが読み込んだ Expat ライブラリのバージョンを、メジャー
   、マイナー、マイクロの 3 つの整数のタプルで表します。

xml.parsers.expat.features

   読み込んだ Expat ライブラリのコンパイル時に有効にされた機能を、
   "(name, value)" のペアのリストで表します。 値が意味を持つのは、
   "'XML_CONTEXT_BYTES'" や保護機構のデフォルトの制限値
   "'XML_BLAP_ACT_THRES'"、"'XML_AT_MAX_AMP'" など、値を伴う機能だけで
   す。 "'XML_DTD'" や "'XML_NS'" などの他の機能では、値は "0" で、名
   前の有無だけが意味を持ちます。

"xml.parsers.expat" モジュールには 2 つの関数があります。

xml.parsers.expat.ErrorString(errno)

   与えられたエラー番号 *errno* を解説する文字列を返します。

xml.parsers.expat.ParserCreate(encoding=None, namespace_separator=None, intern=None)

   新しい "xmlparser" オブジェクトを作成し、返します。 *encoding* が指
   定されていた場合、XMLデータで使われている文字列のエンコード名でなけ
   ればなりません。 Expatは、Pythonのように多くのエンコードをサポート
   しておらず、またエンコーディングのレパートリを拡張することはできま
   せん; サポートするエンコードは、UTF-8, UTF-16, ISO-8859-1 (Latin1),
   ASCII です。 *encoding* [1] が指定されると、文書に対する明示的、非
   明示的なエンコード指定を上書き (override) します。

   "ParserCreate()" で作成したパーサーは、親パーサーを持たないという意
   味で「ルート」パーサーと呼びます。 ルート以外のパーサーは
   "parser.ExternalEntityParserCreate" で作成します。

   Expat はオプションで XML 名前空間の処理を行うことができます。これは
   引数 *namespace_separator* に値を指定することで有効になります。この
   値は、1文字の文字列でなければなりません; 文字列が誤った長さを持つ場
   合には "ValueError" が送出されます ("None" は値の省略と見なされます
   )。名前空間の処理が可能なとき、名前空間に属する要素と属性が展開され
   ます。要素のハンドラである "StartElementHandler" と
   "EndElementHandler" に渡された要素名は、名前空間の URI、名前空間の
   区切り文字、要素名のローカル部を連結したものになります。名前空間の
   区切り文字が 0 バイト ("chr(0)") の場合、名前空間の URI とローカル
   部は区切り文字なしで連結されます。

   たとえば、*namespace_separator* に空白文字("' '")がセットされ、次の
   ような文書が解析されるとします:

      <?xml version="1.0"?>
      <root xmlns    = "http://default-namespace.org/"
            xmlns:py = "http://www.python.org/ns/">
        <py:elem1 />
        <elem2 xmlns="" />
      </root>

   "StartElementHandler" は各要素ごとに次のような文字列を受け取ります:

      http://default-namespace.org/ root
      http://www.python.org/ns/ elem1
      elem2

   *intern* を指定する場合は辞書でなければなりません。 要素名と属性名
   のインターンに使われ、"intern" 属性として参照できます。 デフォルト
   では、パーサーごとに新しい空の辞書が作成されます。

   "pyexpat" が使っている "Expat" ライブラリの制限により、返される
   "xmlparser" インスタンスは単独の XML ドキュメントの解析にしか使えま
   せん。それぞれのドキュメントごとに別々のパーサのインスタンスを作る
   ために "ParserCreate" を呼び出してください。

参考:

  The Expat XML Parser
     Expatプロジェクトのホームページ。


XMLParser オブジェクト
======================

"xmlparser" オブジェクトは以下のようなメソッドを持ちます:

xmlparser.Parse(data[, isfinal])

   *data* の内容を解析し、適切なハンドラー関数を呼び出して解析したデー
   タを処理します。 *data* には *bytes-like object* または文字列を指定
   できます。 文字列の場合、XML データのエンコーディング宣言は無視され
   、デコード済みのテキストとして解析されます。 このメソッドの最後の呼
   び出しでは *isfinal* を真にしなければなりません。 これは単一のファ
   イルを分割して解析するための仕組みで、複数のファイルを渡すためのも
   のではありません。 *data* はどの呼び出しでも空にできます。

xmlparser.ParseFile(file)

   オブジェクト *file* から読み込んだ XML データを解析します。 *file*
   に必要なのは "read(nbytes)" メソッドだけです。 このメソッドは bytes
   を返し、データがなくなると空の bytes オブジェクトを返す必要がありま
   す。 テキストファイルはサポートされていません。 デコード済みのデー
   タには "Parse()" を使ってください。

xmlparser.SetBase(base)

   (XML) 宣言中のシステム識別子中の相対 URI を解決するための、基底 URI
   を設定します。相対識別子の解決はアプリケーションに任されます: この
   値は関数 "ExternalEntityRefHandler()" や "NotationDeclHandler()",
   "UnparsedEntityDeclHandler()" に引数 *base* としてそのまま渡されま
   す。

xmlparser.GetBase()

   以前の "SetBase()" によって設定された基底 URI を文字列の形で返しま
   す。 "SetBase()" が呼ばれていないときには "None" を返します。

xmlparser.GetInputContext()

   現在のイベントを生成した入力データを "bytes" オブジェクトとして返し
   ます。 データのエンコーディングは、そのテキストを含むエンティティの
   ものです。 現在バッファにある入力の末尾までを返すため、後続のイベン
   トのデータも含む場合があります。 また、イベントが大量のテキストから
   生成された場合は、そのすべてを取得できるとは限りません。 イベントハ
   ンドラーの実行中以外に呼び出すと、戻り値は "None" です。

xmlparser.ExternalEntityParserCreate(context[, encoding])

   親パーサーが解析する内容から参照される、解析対象の外部エンティティ
   を解析するための「子」パーサーを作成します。 *context* 引数には、後
   述の "ExternalEntityRefHandler()" ハンドラー関数に渡された文字列を
   指定します。 子パーサーの "ordered_attributes" と
   "specified_attributes" には、このパーサーの値が設定されます。

xmlparser.SetParamEntityParsing(flag)

   パラメータエンティティ (外部DTDサブセットを含む) の解析を制御します
   。 *flag* の有効な値は、 "XML_PARAM_ENTITY_PARSING_NEVER",
   "XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE",
   "XML_PARAM_ENTITY_PARSING_ALWAYS" です。 フラグの設定に成功した場合
   は真を返します。

xmlparser.UseForeignDTD([flag])

   *flag* の値をデフォルトのtrueにすると、Expatは代わりのDTDをロードす
   るため、すべての引数に "None" を設定して "ExternalEntityRefHandler"
   を呼び出します。XML文書が文書型定義を持っていなければ、
   "ExternalEntityRefHandler" が呼び出しますが、
   "StartDoctypeDeclHandler" と "EndDoctypeDeclHandler" は呼び出されま
   せん。

   *flag* にfalseを与えると、メソッドが前回呼ばれた時のtrueの設定が解
   除されますが、他には何も起こりません。

   このメソッドは "Parse()" または "ParseFile()" メソッドが呼び出され
   る前にだけ呼び出されます;これら2つのメソッドのどちらかが呼び出され
   たあとにメソッドが呼ばれると、 "code" に定数
   "errors.codes[errors.XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING]"
   が設定されて例外 "ExpatError" が送出されます。

xmlparser.SetReparseDeferralEnabled(enabled)

   警告:

     "SetReparseDeferralEnabled(False)" の呼び出しには、以下で説明する
     セキュリティ上の影響があります。 "SetReparseDeferralEnabled" メソ
     ッドを使う前に、これらの影響を理解してください。

   Expat 2.6.0 では「再解析の遅延」というセキュリティ機構が導入されま
   した。 大きなトークンの再解析によって実行時間が二次的に増大し、サー
   ビス拒否が起こるのを防ぐため、未完了のトークンの再解析はデフォルト
   で十分な量の入力が集まるまで遅延されます。 この遅延により、Expat に
   渡す入力チャンクの大きさによっては、新しい入力をパーサーに渡した直
   後には登録済みのハンドラーが呼び出されなくなります。 即時の応答が必
   要で、大きなトークンによるサービス拒否への対策を自身で担う場合、
   "SetReparseDeferralEnabled(False)" を呼び出すと、現在の Expat パー
   サーインスタンスの再解析の遅延を一時的または継続的に無効化できます
   。 "SetReparseDeferralEnabled(True)" を呼び出すと、再解析の遅延を再
   び有効にできます。

   "SetReparseDeferralEnabled()" は、セキュリティ修正として一部の過去
   の CPython リリースにもバックポートされています。 さまざまな Python
   バージョンで動作するコードでは、"hasattr()" で利用可能か確認してく
   ださい。

   Added in version 3.13.

xmlparser.GetReparseDeferralEnabled()

   この Expat パーサーインスタンスで再解析の遅延が現在有効かどうかを返
   します。

   Added in version 3.13.

"xmlparser" オブジェクトには、一般的な XML の脆弱性に対する保護を調整
するための次のメソッドがあります。

xmlparser.SetBillionLaughsAttackProtectionActivationThreshold(threshold, /)

   billion laughs 攻撃に対する保護を有効にする出力バイト数を設定します
   。

   出力バイト数には、エンティティの展開や DTD ファイルの読み込みによる
   増幅を含みます。

   パーサーオブジェクトの保護を有効にする閾値は通常 8 MiB ですが、実際
   のデフォルト値は基になる Expat ライブラリによって異なります。

   このメソッドを non-root パーサーで呼び出すと "ExpatError" が送出さ
   れます。 対応する "lineno" と "offset" は意味を持たない場合があるた
   め、使わないでください。

   "SetBillionLaughsAttackProtectionActivationThreshold()" は、セキュ
   リティ修正として一部の過去の CPython リリースにもバックポートされて
   います。 さまざまな Python バージョンで動作するコードでは、
   "hasattr()" で利用可能か確認してください。

   注釈:

     保護を有効にする閾値を 4 MiB 未満にすると DITA 1.3 のデータを扱え
     なくなることが分かっているため、推奨しません。

   Added in version 3.15.

xmlparser.SetBillionLaughsAttackProtectionMaximumAmplification(max_factor, /)

   billion laughs 攻撃に対する保護で許容する最大増幅率を設定します。

   解析中の増幅率は "(direct + indirect) / direct" で計算されます。
   "direct" は解析対象の主文書から読み込んだバイト数、"indirect" はエ
   ンティティの展開や外部 DTD ファイルの読み込みで加わったバイト数です
   。

   *max_factor* は NaN ではない 1.0 以上の "float" 値でなければなりま
   せん。 実際には、小さな無害なファイルでも、データ全体で 15,000 倍、
   解析途中では 30,000 倍のピーク増幅率が観測されています。 特に、誤検
   知を避けるため、保護を有効にする閾値は慎重に選ぶ必要があります。

   パーサーオブジェクトの最大増幅率は通常 100 ですが、実際のデフォルト
   値は基になる Expat ライブラリによって異なります。

   このメソッドを non-root パーサーで呼び出した場合や、*max_factor* が
   有効な範囲を外れている場合は "ExpatError" が送出されます。 対応する
   "lineno" と "offset" は意味を持たない場合があるため、使わないでくだ
   さい。

   "SetBillionLaughsAttackProtectionMaximumAmplification()" は、セキュ
   リティ修正として一部の過去の CPython リリースにもバックポートされて
   います。 さまざまな Python バージョンで動作するコードでは、
   "hasattr()" で利用可能か確認してください。

   注釈:

     最大増幅率が考慮されるのは、
     "SetBillionLaughsAttackProtectionActivationThreshold()" で調整す
     る閾値を超えた場合だけです。

   Added in version 3.15.

xmlparser.SetAllocTrackerActivationThreshold(threshold, /)

   不釣り合いな RAM 使用量に対する保護を有効にする、動的メモリの割り当
   てバイト数を設定します。

   パーサーオブジェクトのメモリ割り当て量に関する保護を有効にする閾値
   は通常 64 MiB ですが、実際のデフォルト値は基になる Expat ライブラリ
   によって異なります。

   このメソッドを non-root パーサーで呼び出すと "ExpatError" が送出さ
   れます。 対応する "lineno" と "offset" は意味を持たない場合があるた
   め、使わないでください。

   "SetAllocTrackerActivationThreshold()" は、セキュリティ修正として一
   部の過去の CPython リリースにもバックポートされています。 さまざま
   な Python バージョンで動作するコードでは、"hasattr()" で利用可能か
   確認してください。

   Added in version 3.15.

xmlparser.SetAllocTrackerMaximumAmplification(max_factor, /)

   直接入力されたデータのバイト数に対する、割り当てた動的メモリのバイ
   ト数の最大増幅率を設定します。

   解析中の増幅率は "allocated / direct" で計算されます。 "direct" は
   解析対象の主文書から読み込んだバイト数、"allocated" はパーサー階層
   内で割り当てた動的メモリのバイト数です。

   *max_factor* は NaN ではない 1.0 以上の "float" 値でなければなりま
   せん。 実際には、無害なファイルでも解析開始付近で 100.0 を超える増
   幅率が観測されることがあります。 特に、誤検知を避けるため、保護を有
   効にする閾値は慎重に選ぶ必要があります。

   パーサーオブジェクトの最大増幅率は通常 100 ですが、実際のデフォルト
   値は基になる Expat ライブラリによって異なります。

   このメソッドを non-root パーサーで呼び出した場合や、*max_factor* が
   有効な範囲を外れている場合は "ExpatError" が送出されます。 対応する
   "lineno" と "offset" は意味を持たない場合があるため、使わないでくだ
   さい。

   "SetAllocTrackerMaximumAmplification()" は、セキュリティ修正として
   一部の過去の CPython リリースにもバックポートされています。 さまざ
   まな Python バージョンで動作するコードでは、"hasattr()" で利用可能
   か確認してください。

   注釈:

     最大増幅率が考慮されるのは、
     "SetAllocTrackerActivationThreshold()" で調整する閾値を超えた場合
     だけです。

   Added in version 3.15.

"xmlparser" オブジェクトは次のような属性を持ちます:

xmlparser.buffer_size

   "buffer_text" が真の時に使われるバッファのサイズです。この属性に新
   しい整数値を代入することで違うバッファサイズにできます。サイズが変
   えられるときにバッファはフラッシュされます。

xmlparser.buffer_text

   この属性を真にすると、"xmlparser" オブジェクトは Expat が返すテキス
   ト内容をバッファに保持し、"CharacterDataHandler()" コールバックが複
   数回呼ばれることをできるだけ避けます。 Expat は通常、改行のたびに文
   字データを分割するため、この設定で性能が大幅に向上することがありま
   す。 デフォルトは偽で、いつでも変更できます。 偽の場合、改行を含ま
   ないデータも分割されることに注意してください。

xmlparser.buffer_used

   "buffer_text" が有効な場合、バッファに保持されているバイト数です。
   これらのバイトは UTF-8 でエンコードされたテキストを表します。
   "buffer_text" が偽の場合、この属性は意味を持ちません。

xmlparser.ordered_attributes

   この属性をゼロ以外の整数にすると、報告される(XMLノードの) 属性を辞
   書型ではなくリスト型にします。属性は文書のテキスト中の出現順で示さ
   れます。それぞれの属性は、2つのリストのエントリ: 属性名とその値、が
   与えられます。 (このモジュールの古いバージョンでも、同じフォーマッ
   トが使われています。) デフォルトでは、この属性はデフォルトでは偽と
   なりますが、いつでも変更可能です。

xmlparser.specified_attributes

   ゼロ以外の整数にすると、パーザは文書のインスタンスで特定される属性
   だけを報告し、属性宣言から導出された属性は報告しないようになります
   。この属性が指定されたアプリケーションでは、XMLプロセッサの振る舞い
   に関する標準に従うために必要とされる (文書型) 宣言によって、どのよ
   うな付加情報が利用できるのかということについて特に注意を払わなけれ
   ばなりません。デフォルトで、この属性は偽となりますが、いつでも変更
   可能です。

xmlparser.intern

   要素名と属性名のインターンに使う辞書です。 "ParserCreate()" の
   *intern* 引数に渡した辞書、またはこのパーサー用に新しく作成した辞書
   です。

xmlparser.namespace_prefixes

   この属性が真で、名前空間処理が有効な場合、名前空間プレフィックスが
   展開された名前の 3 番目の部分として、名前空間の区切り文字で区切って
   報告されます。 プレフィックスを持たない名前には影響しません。 デフ
   ォルトは偽で、いつでも変更できます。

以下の属性には、 "xmlparser" オブジェクトで最も最近に起きたエラーに関
する値が入っており、また "Parse()" または "ParseFile()" メソッドが
"xml.parsers.expat.ExpatError" 例外を送出した際にのみ正しい値となりま
す。

xmlparser.ErrorByteIndex

   エラーが発生したバイトのインデクスです。

xmlparser.ErrorCode

   エラーを特定する数値によるコードです。この値は "ErrorString()" に渡
   したり、 "errors" オブジェクトで定義された内容と比較できます。

xmlparser.ErrorColumnNumber

   エラーの発生したカラム番号です。

xmlparser.ErrorLineNumber

   エラーの発生した行番号です。

以下の属性は "xmlparser" オブジェクトがその時パースしている位置に関す
る値を保持しています。 コールバックがパースイベントを報告している間、
これらの値はイベントを発生させた文字列の先頭の位置を指し示します。 コ
ールバックの外から参照された時には、対応するコールバックの有無にかかわ
らず、最後のパースイベントの直後の位置を示します。

xmlparser.CurrentByteIndex

   パーサへの入力の、現在のバイトインデックス。

xmlparser.CurrentColumnNumber

   パーサへの入力の、現在のカラム番号。

xmlparser.CurrentLineNumber

   パーサへの入力の、現在の行番号。

以下に指定可能なハンドラのリストを示します。 "xmlparser" オブジェクト
*o* にハンドラを指定するには、 "o.handlername = func" を使用します。
*handlername* は、以下のリストに挙げた値をとらなければならず、また
*func* は正しい数の引数を受理する呼び出し可能なオブジェクトでなければ
なりません。引数は特に明記しない限り、すべて文字列となります。

xmlparser.XmlDeclHandler(version, encoding, standalone)

   Called when the XML declaration is parsed.  The XML declaration is
   the (optional) declaration of the applicable version of the XML
   recommendation, the encoding of the document text, and an optional
   "standalone" declaration. *version* and *encoding* will be strings,
   and *standalone* will be "1" if the document is declared
   standalone, "0" if it is declared not to be standalone, or "-1" if
   the standalone clause was omitted.

xmlparser.StartDoctypeDeclHandler(doctypeName, systemId, publicId, has_internal_subset)

   Expat が文書型宣言 ("<!DOCTYPE ...") の解析を始めるときに呼び出され
   ます。 *doctypeName* は記載されたとおりに渡されます。 *systemId* と
   *publicId* には、指定されていればシステム識別子と公開識別子が渡され
   、省略されていれば "None" が渡されます。 文書に内部宣言サブセットが
   あれば、*has_internal_subset* は真になります。

xmlparser.EndDoctypeDeclHandler()

   Expat が文書型宣言の解析を終えたときに呼び出されます。

xmlparser.ElementDeclHandler(name, model)

   それぞれの要素型宣言ごとに呼び出されます。 *name* は要素型の名前で
   あり、 *model* は内容モデル (content model) の表現です。

xmlparser.AttlistDeclHandler(elname, attname, type, default, required)

   要素型に対して宣言された属性ごとに呼び出されます。 属性リスト宣言で
   3 つの属性を宣言した場合、このハンドラーは属性ごとに 1 回、計 3 回
   呼び出されます。 *elname* は宣言の対象となる要素の名前で、*attname*
   は宣言された属性の名前です。 属性の型は *type* に文字列として渡され
   、"'CDATA'"、"'ID'"、"'IDREF'"、"'IDREFS'"、"'ENTITY'"、
   "'ENTITIES'"、"'NMTOKEN'"、"'NMTOKENS'"、"'(x|y)'" のような列挙、ま
   たは "'NOTATION(n1|n2)'" のような記法リストです。 *default* は、文
   書内にその属性の指定がない場合に使うデフォルト値で、デフォルト値が
   ない場合 ("#IMPLIED") は "None" です。 文書内に属性の指定が必要な場
   合、*required* は真になります。

xmlparser.StartElementHandler(name, attributes)

   要素の開始ごとに呼び出されます。 *name* は要素名を持つ文字列で、
   *attributes* は要素の属性です。 "ordered_attributes" が真の場合これ
   はリストです (詳細は "ordered_attributes" を参照してください)。 そ
   うでなければ名前を値に対応させる辞書です。

xmlparser.EndElementHandler(name)

   要素の終端を処理するごとに呼び出されます。

xmlparser.ProcessingInstructionHandler(target, data)

   処理命令を処理するごとに呼び出されます。

xmlparser.CharacterDataHandler(data)

   文字データに対して呼び出されます。 通常の文字データ、CDATA としてマ
   ークされた内容、無視可能な空白に対して呼び出されます。 これらを区別
   する必要があるアプリケーションは、"StartCdataSectionHandler"、
   "EndCdataSectionHandler"、"ElementDeclHandler" のコールバックで必要
   な情報を収集できます。 短い文字データでも分割されることがあり、
   "CharacterDataHandler()" が複数回呼び出される場合があります。 これ
   を避けるには、インスタンス属性 "buffer_text" を "True" に設定してく
   ださい。

xmlparser.UnparsedEntityDeclHandler(entityName, base, systemId, publicId, notationName)

   解析対象外 (NDATA) のエンティティ宣言に対して呼び出されます。 この
   ハンドラーを設定しない場合、そのような宣言は "EntityDeclHandler" に
   よって報告されます。 新しいコードではこちらを使うことを推奨します。
   (基になる Expat ライブラリの関数は廃止予定とされています。)

xmlparser.EntityDeclHandler(entityName, is_parameter_entity, value, base, systemId, publicId, notationName)

   すべてのエンティティ宣言に対して呼び出されます。 パラメータエンティ
   ティと内部エンティティでは、*value* は宣言されたエンティティの内容
   を表す文字列で、外部エンティティでは "None" です。 *notationName*
   引数は、解析対象のエンティティでは "None"、解析対象外のエンティティ
   では記法の名前です。 *is_parameter_entity* はパラメータエンティティ
   では真、一般エンティティでは偽です (ほとんどのアプリケーションは一
   般エンティティだけを扱えば十分です)。

xmlparser.NotationDeclHandler(notationName, base, systemId, publicId)

   記法の宣言 (notation declaration) で呼び出されます。
   *notationName*, *base*, *systemId*, および *publicId* を与える場合
   、文字列にします。public な識別子が省略された場合、 *publicId* は
   "None" になります。

xmlparser.StartNamespaceDeclHandler(prefix, uri)

   要素が名前空間宣言を含んでいる場合に呼び出されます。名前空間宣言は
   、宣言が配置されている要素に対して "StartElementHandler" が呼び出さ
   れる前に処理されます。

xmlparser.EndNamespaceDeclHandler(prefix)

   名前空間宣言を含む要素の終了タグに達すると呼び出されます。 その要素
   の名前空間宣言ごとに 1 回ずつ、各宣言のスコープ開始を知らせた
   "StartNamespaceDeclHandler" とは逆順に呼び出されます。 このハンドラ
   ーは、その要素の終了を知らせる "EndElementHandler" の後に呼び出され
   ます。

xmlparser.CommentHandler(data)

   コメントで呼び出されます。 *data* はコメントのテキストで、先頭の
   '"<!-" "-"' と末尾の '"-" "->"' を除きます。

xmlparser.StartCdataSectionHandler()

   CDATA セクションの開始時に呼び出されます。CDATA セクションの構文的
   な開始と終了位置を識別できるようにするには、このハンドラと
   "EndCdataSectionHandler" が必要です。

xmlparser.EndCdataSectionHandler()

   CDATA セクションの終了時に呼び出されます。

xmlparser.DefaultHandler(data)

   XML 文書中で、適用可能なハンドラが指定されていない文字すべてに対し
   て呼び出されます。この文字とは、検出されたことが報告されるが、ハン
   ドラは指定されていないようなコンストラクト (construct) の一部である
   文字を意味します。

xmlparser.DefaultHandlerExpand(data)

   "DefaultHandler" と同じですが、内部エンティティの展開を抑止しません
   。 エンティティ参照はデフォルトハンドラーに渡されません。

xmlparser.NotStandaloneHandler()

   XML 文書がスタンドアロンの文書として宣言されていない場合に呼び出さ
   れます。外部サブセットやパラメタエンティティへの参照が存在するが、
   XML 宣言が XML 宣言中で standalone 変数を "yes" に設定していない場
   合に起きます。このハンドラが "0" を返すと、パーザは
   "XML_ERROR_NOT_STANDALONE" を発生させます。このハンドラが設定されて
   いなければ、パーザは前述の事態で例外を送出しません。

xmlparser.ExternalEntityRefHandler(context, base, systemId, publicId)

   警告:

     ユーザーが提供した XML 内容を "xmlparser" で扱う場合、ローカルフ
     ァイルやネットワークにアクセスするハンドラーを実装すると、外部エ
     ンティティ攻撃 の脆弱性が生じる可能性があります。 このハンドラー
     を実装する前に、脅威モデル を検討してください。

   外部エンティティの参照時に呼び出されます。 *base* は現在の基底
   (base) で、以前の "SetBase()" で設定された値になっています。 public
   、および system の識別子である、 *systemId* と *publicId* が指定さ
   れている場合、値は文字列です; public 識別子が指定されていない場合、
   *publicId* は "None" になります。 *context* の値は不明瞭なものであ
   り、以下に記述するようにしか使ってはなりません。

   外部エンティティが解析されるようにするには、このハンドラを実装しな
   ければなりません。 このハンドラは、
   "ExternalEntityParserCreate(context)" で子パーサーを作り、適切なコ
   ールバックを設定してからエンティティを解析する役割を担います。 この
   ハンドラは整数を返さなければなりません; "0" を返した場合、パーザは
   "XML_ERROR_EXTERNAL_ENTITY_HANDLING" エラーを送出します。 そうでな
   い場合、解析を継続します。

   このハンドラが与えられておらず、 "DefaultHandler" コールバックが指
   定されていれば、外部エンティティは "DefaultHandler" で報告されます
   。

xmlparser.SkippedEntityHandler(entityName, is_parameter_entity)

   パーサーがエンティティの宣言を読まなかったために展開されないエンテ
   ィティ参照に対して呼び出されます。 これは外部 DTD サブセットや外部
   パラメータエンティティを解析しない場合に起こります。
   *is_parameter_entity* はパラメータエンティティでは真、一般エンティ
   ティでは偽です。


ExpatError 例外
===============

"ExpatError" 例外はいくつかの興味深い属性を備えています:

ExpatError.code

   特定のエラーに対する Expat の内部エラー番号です。 "errors.messages"
   辞書はこれらのエラー番号を Expat のエラーメッセージに対応させます。
   例えば:

      from xml.parsers.expat import ParserCreate, ExpatError, errors

      p = ParserCreate()
      try:
          p.Parse(some_xml_document)
      except ExpatError as err:
          print("Error:", errors.messages[err.code])

   "errors" モジュールはエラーメッセージ定数と、それらのメッセージをエ
   ラーコードに対応させる辞書 "codes" も提供しています。以下を参照して
   ください。

ExpatError.lineno

   エラーが検出された場所の行番号です。最初の行の番号は "1" です。

ExpatError.offset

   エラーが発生した場所の行内でのオフセットです。最初のカラムの番号は
   "0" です。


使用例
======

以下のプログラムでは、与えられた引数を出力するだけの三つのハンドラを定
義しています。

   import xml.parsers.expat

   # 3 つのハンドラー関数
   def start_element(name, attrs):
       print('Start element:', name, attrs)
   def end_element(name):
       print('End element:', name)
   def char_data(data):
       print('Character data:', repr(data))

   p = xml.parsers.expat.ParserCreate()

   p.StartElementHandler = start_element
   p.EndElementHandler = end_element
   p.CharacterDataHandler = char_data

   p.Parse("""<?xml version="1.0"?>
   <parent id="top"><child1 name="paul">Text goes here</child1>
   <child2 name="fred">More text</child2>
   </parent>""", 1)

このプログラムの出力は以下のようになります:

   Start element: parent {'id': 'top'}
   Start element: child1 {'name': 'paul'}
   Character data: 'Text goes here'
   End element: child1
   Character data: '\n'
   Start element: child2 {'name': 'fred'}
   Character data: 'More text'
   End element: child2
   Character data: '\n'
   End element: parent


内容モデルの記述
================

内容モデルは入れ子になったタプルを使って記述されています。各タプルには
以下の 4 つの値が収められています: 型、限定詞 (quantifier)、名前、そし
て子のタプル。子のタプルは単に内容モデルを記述したものです。

最初の 2 つのフィールドの値は、"xml.parsers.expat.model" モジュールで
定義された定数です。 これらの定数は、モデル型と限定子の 2 つのグループ
に分けられます。

以下にモデル型グループにおける定数を示します:

xml.parsers.expat.model.XML_CTYPE_ANY

   モデル名で指定された要素は "ANY" の内容モデルを持つと宣言されます。

xml.parsers.expat.model.XML_CTYPE_CHOICE

   指定されたエレメントはいくつかのオプションから選択できるようになっ
   ています; "(A | B | C)" のような内容モデルで用いられます。

xml.parsers.expat.model.XML_CTYPE_EMPTY

   "EMPTY" であると宣言されている要素はこのモデル型を持ちます。

xml.parsers.expat.model.XML_CTYPE_MIXED

   指定された要素では文字データが許可され、指定された子要素をその間に
   挟むこともできます。 "(#PCDATA)" や "(#PCDATA | A | B)*" のような内
   容モデルで使います。

xml.parsers.expat.model.XML_CTYPE_NAME

   "A" のように、モデルは単一の要素を指定します。

xml.parsers.expat.model.XML_CTYPE_SEQ

   順々に続くようなモデルの系列を表すモデルがこのモデル型で表されます
   。 "(A, B, C)" のようなモデルで用いられます。

限定子グループにおける定数を以下に示します:

xml.parsers.expat.model.XML_CQUANT_NONE

   修飾子 (modifier) が指定されていません。従って "A" のように、厳密に
   一つだけです。

xml.parsers.expat.model.XML_CQUANT_OPT

   このモデルはオプションです: "A?" のように、一つか全くないかです。

xml.parsers.expat.model.XML_CQUANT_PLUS

   このモデルは ("A+" のように) 一つかそれ以上あります。

xml.parsers.expat.model.XML_CQUANT_REP

   このモデルは "A*" のようにゼロ回以上あります。


Expat エラー定数
================

次の定数は "xml.parsers.expat.errors" モジュールで提供されます。 これ
らは、エラー発生時に送出される "ExpatError" 例外オブジェクトの属性の一
部を解釈するのに役立ちます。 後方互換性のため、定数の値は数値のエラー
*コード* ではなくエラー *メッセージ* です。 そのため、例外の "code" 属
性を "errors.codes[errors.XML_ERROR_*CONSTANT_NAME*]" と比較して使いま
す。

"errors" モジュールには以下の属性があります:

xml.parsers.expat.errors.codes

   文字列の記述をエラーコードに対応させる辞書です。

   Added in version 3.2.

xml.parsers.expat.errors.messages

   数値的なエラーコードを文字列の記述に対応させる辞書です。

   Added in version 3.2.

xml.parsers.expat.errors.XML_ERROR_ASYNC_ENTITY

xml.parsers.expat.errors.XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF

   属性値中のエンティティ参照が、内部エンティティではなく外部エンティ
   ティを参照しました。

xml.parsers.expat.errors.XML_ERROR_BAD_CHAR_REF

   文字参照が、XML では正しくない (illegal) 文字を参照しました (例えば
   "0" や '"&#0;"')。

xml.parsers.expat.errors.XML_ERROR_BINARY_ENTITY_REF

   エンティティ参照が、記法 (notation) つきで宣言されているエンティテ
   ィを参照したため、解析できません。

xml.parsers.expat.errors.XML_ERROR_DUPLICATE_ATTRIBUTE

   一つの属性が一つの開始タグ内に一度より多く使われています。

xml.parsers.expat.errors.XML_ERROR_INCORRECT_ENCODING

xml.parsers.expat.errors.XML_ERROR_INVALID_TOKEN

   入力されたバイトが文字に適切に関連付けできない際に送出されます; 例
   えば、UTF-8 入力ストリームにおける NUL バイト (値 "0") などです。

xml.parsers.expat.errors.XML_ERROR_JUNK_AFTER_DOC_ELEMENT

   空白以外の何かがドキュメント要素の後にあります。

xml.parsers.expat.errors.XML_ERROR_MISPLACED_XML_PI

   入力データの先頭以外の場所に XML 定義が見つかりました。

xml.parsers.expat.errors.XML_ERROR_NO_ELEMENTS

   文書に要素がありません (XML では、すべての文書にトップレベルの要素
   がちょうど 1 つ必要です)。

xml.parsers.expat.errors.XML_ERROR_NO_MEMORY

   Expat が内部メモリを確保できませんでした。

xml.parsers.expat.errors.XML_ERROR_PARAM_ENTITY_REF

   パラメータエンティティの参照が、許可されていない場所で見つかりまし
   た。

xml.parsers.expat.errors.XML_ERROR_PARTIAL_CHAR

   入力に不完全な文字が見つかりました。

xml.parsers.expat.errors.XML_ERROR_RECURSIVE_ENTITY_REF

   エンティティ参照中に、同じエンティティへの別の参照が入っていました;
   おそらく違う名前で参照しているか、間接的に参照しています。

xml.parsers.expat.errors.XML_ERROR_SYNTAX

   詳細が特定されていない構文エラーが発生しました。

xml.parsers.expat.errors.XML_ERROR_TAG_MISMATCH

   終了タグが最も内側で開かれている開始タグに一致しません。

xml.parsers.expat.errors.XML_ERROR_UNCLOSED_TOKEN

   何らかの (開始タグのような) トークンが閉じられないまま、ストリーム
   の終端や次のトークンに遭遇しました。

xml.parsers.expat.errors.XML_ERROR_UNDEFINED_ENTITY

   定義されていないエンティティへの参照が行われました。

xml.parsers.expat.errors.XML_ERROR_UNKNOWN_ENCODING

   ドキュメントのエンコードが Expat でサポートされていません。

xml.parsers.expat.errors.XML_ERROR_UNCLOSED_CDATA_SECTION

   CDATAセクションが閉じられていません。

xml.parsers.expat.errors.XML_ERROR_EXTERNAL_ENTITY_HANDLING

xml.parsers.expat.errors.XML_ERROR_NOT_STANDALONE

   XML 文書は XML 宣言で "standalone" と宣言していましたが、パーサーは
   そうではないと判定しました。 また、"NotStandaloneHandler" が設定さ
   れていて、"0" を返しました。

xml.parsers.expat.errors.XML_ERROR_UNEXPECTED_STATE

xml.parsers.expat.errors.XML_ERROR_ENTITY_DECLARED_IN_PE

xml.parsers.expat.errors.XML_ERROR_FEATURE_REQUIRES_XML_DTD

   DTD のサポートを組み込んでコンパイルする必要がある操作が要求されま
   したが、Expat は DTD をサポートしない構成でした。
   "xml.parsers.expat" モジュールの標準ビルドでは、このエラーは報告さ
   れないはずです。

xml.parsers.expat.errors.XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING

   パースが始まったあとで動作の変更が要求されました。これはパースが開
   始される前にのみ変更可能です。（現在のところ） "UseForeignDTD()" に
   よってのみ送出されます。

xml.parsers.expat.errors.XML_ERROR_UNBOUND_PREFIX

   名前空間処理が有効な状態で、宣言されていないプレフィックスが見つか
   りました。

xml.parsers.expat.errors.XML_ERROR_UNDECLARING_PREFIX

   XML文書はプレフィックスに対応した名前空間宣言を削除しようとしました
   。

xml.parsers.expat.errors.XML_ERROR_INCOMPLETE_PE

   パラメータエンティティは不完全なマークアップを含んでいます。

xml.parsers.expat.errors.XML_ERROR_XML_DECL

   XML 宣言の解析中にエラーが発生しました。

xml.parsers.expat.errors.XML_ERROR_TEXT_DECL

   外部エンティティ中のテキスト宣言にエラーがあります。

xml.parsers.expat.errors.XML_ERROR_PUBLICID

   パブリックID中に許可されていない文字があります。

xml.parsers.expat.errors.XML_ERROR_SUSPENDED

   要求された操作は一時停止されたパーサで行われていますが、許可されて
   いない操作です。このエラーは追加の入力を行なおうとしている場合、も
   しくはパーサが停止しようとしている場合にも送出されます。

xml.parsers.expat.errors.XML_ERROR_NOT_SUSPENDED

   一時停止していないパーサーを再開しようとしました。

xml.parsers.expat.errors.XML_ERROR_ABORTED

   Pythonアプリケーションには通知されません。

xml.parsers.expat.errors.XML_ERROR_FINISHED

   入力の解析が完了したパーサーに対して、許可されない操作を要求しまし
   た。 追加の入力を渡す操作や、パーサーを停止する操作などが該当します
   。

xml.parsers.expat.errors.XML_ERROR_SUSPEND_PE

xml.parsers.expat.errors.XML_ERROR_RESERVED_PREFIX_XML

   予約済みの名前空間プレフィックス "xml" の宣言を解除するか、別の名前
   空間 URI に結び付けようとしました。

xml.parsers.expat.errors.XML_ERROR_RESERVED_PREFIX_XMLNS

   予約済みの名前空間プレフィックス "xmlns" を宣言するか、宣言を解除し
   ようとしました。

xml.parsers.expat.errors.XML_ERROR_RESERVED_NAMESPACE_URI

   予約済みの名前空間プレフィックス "xml" または "xmlns" の URI を、別
   の名前空間プレフィックスに結び付けようとしました。

xml.parsers.expat.errors.XML_ERROR_INVALID_ARGUMENT

   Pythonアプリケーションには通知されません。

xml.parsers.expat.errors.XML_ERROR_NO_BUFFER

   Pythonアプリケーションには通知されません。

xml.parsers.expat.errors.XML_ERROR_AMPLIFICATION_LIMIT_BREACH

   DTD とエンティティによる入力の増幅率が制限を超えました。

xml.parsers.expat.errors.XML_ERROR_NOT_STARTED

   パーサーを開始する前に、停止または一時停止しようとしました。

   Added in version 3.14.

-[ 脚注 ]-

[1] XML 出力に含まれるエンコーディング文字列は適切な規格に従っていなけ
    ればなりません。例えば、 "UTF-8" は有効ですが、 "UTF8" はそうでは
    ありません。https://www.w3.org/TR/2006/REC-xml11-20060816/#NT-
    EncodingDecl と https://www.iana.org/assignments/character-sets
    /character-sets.xhtml を参照してください。
