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

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

注釈:

  If you need to parse untrusted or unauthenticated data, see XML
  security.

The "xml.parsers.expat" module is a Python interface to the Expat non-
validating XML parser. The module provides a single extension type,
"xmlparser", that represents the current state of an XML parser.
After an "xmlparser" object has been created, various attributes of
the object can be set to handler functions.  When an XML document is
then fed to the parser, the handler functions are called for the
character data and markup in the XML document.

このモジュールでは、Expatパーザへのアクセスを提供するために "pyexpat"
モジュールを使用します。 "pyexpat" モジュールの直接使用は撤廃されてい
ます。

このモジュールは、例外を一つと型オブジェクトを一つ提供しています:

exception xml.parsers.expat.ExpatError

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

exception xml.parsers.expat.error

   "ExpatError" の別名です。

xml.parsers.expat.XMLParserType

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

The "xml.parsers.expat" module contains two functions:

xml.parsers.expat.ErrorString(errno)

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

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

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

   Parsers created through "ParserCreate()" are called "root" parsers,
   in the sense that they do not have any parent parser attached. Non-
   root parsers are created by "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

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

参考:

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


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

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

xmlparser.Parse(data[, isfinal])

   文字列 *data* の内容を解析し、解析されたデータを処理するための適切
   な関数を呼び出します。このメソッドを最後に呼び出す時は *isfinal* を
   真にしなければなりません; 単体ファイルを細切れに渡して解析出来るこ
   とを意味しますが、複数ファイルは扱えません。 *data* にはいつでも空
   の文字列を渡せます。

xmlparser.ParseFile(file)

   *file* オブジェクトから読み込んだXMLデータを解析します。 *file* に
   は *read(nbytes)* メソッドのみが必要です。このメソッドはデータがな
   くなった場合に空文字列を返さねばなりません。。

xmlparser.SetBase(base)

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

xmlparser.GetBase()

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

xmlparser.GetInputContext()

   現在のイベントを発生させた入力データを文字列として返します。データ
   はテキストの入っているエンティティが持っているエンコードになります
   。イベントハンドラがアクティブでないときに呼ばれると、戻り値は
   "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" です。 flag の設定をしたら true
   を返します。

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)

   警告:

     Calling "SetReparseDeferralEnabled(False)" has security
     implications, as detailed below; please make sure to understand
     these consequences prior to using the "SetReparseDeferralEnabled"
     method.

   Expat 2.6.0 introduced a security mechanism called "reparse
   deferral" where instead of causing denial of service through
   quadratic runtime from reparsing large tokens, reparsing of
   unfinished tokens is now delayed by default until a sufficient
   amount of input is reached. Due to this delay, registered handlers
   may — depending of the sizing of input chunks pushed to Expat — no
   longer be called right after pushing new input to the parser.
   Where immediate feedback and taking over responsibility of
   protecting against denial of service from large tokens are both
   wanted, calling "SetReparseDeferralEnabled(False)" disables reparse
   deferral for the current Expat parser instance, temporarily or
   altogether. Calling "SetReparseDeferralEnabled(True)" allows re-
   enabling reparse deferral.

   Note that "SetReparseDeferralEnabled()" has been backported to some
   prior releases of CPython as a security fix.  Check for
   availability of "SetReparseDeferralEnabled()" using "hasattr()" if
   used in code running across a variety of Python versions.

   Added in version 3.13.

xmlparser.GetReparseDeferralEnabled()

   Returns whether reparse deferral is currently enabled for the given
   Expat parser instance.

   Added in version 3.13.

"xmlparser" objects have the following methods to tune protections
against some common XML vulnerabilities.

xmlparser.SetBillionLaughsAttackProtectionActivationThreshold(threshold, /)

   Sets the number of output bytes needed to activate protection
   against billion laughs attacks.

   The number of output bytes includes amplification from entity
   expansion and reading DTD files.

   Parser objects usually have a protection activation threshold of 8
   MiB, but the actual default value depends on the underlying Expat
   library.

   An "ExpatError" is raised if this method is called on a non-root
   parser. The corresponding "lineno" and "offset" should not be used
   as they may have no special meaning.

   注釈:

     Activation thresholds below 4 MiB are known to break support for
     DITA 1.3 payload and are hence not recommended.

   Added in version 3.14.6.

xmlparser.SetBillionLaughsAttackProtectionMaximumAmplification(max_factor, /)

   Sets the maximum tolerated amplification factor for protection
   against billion laughs attacks.

   The amplification factor is calculated as "(direct + indirect) /
   direct" while parsing, where "direct" is the number of bytes read
   from the primary document in parsing and "indirect" is the number
   of bytes added by expanding entities and reading of external DTD
   files.

   The *max_factor* value must be a non-NaN "float" value greater than
   or equal to 1.0. Peak amplifications of factor 15,000 for the
   entire payload and of factor 30,000 in the middle of parsing have
   been observed with small benign files in practice. In particular,
   the activation threshold should be carefully chosen to avoid false
   positives.

   Parser objects usually have a maximum amplification factor of 100,
   but the actual default value depends on the underlying Expat
   library.

   An "ExpatError" is raised if this method is called on a non-root
   parser or if *max_factor* is outside the valid range. The
   corresponding "lineno" and "offset" should not be used as they may
   have no special meaning.

   注釈:

     The maximum amplification factor is only considered if the
     threshold that can be adjusted by
     "SetBillionLaughsAttackProtectionActivationThreshold()" is
     exceeded.

   Added in version 3.14.6.

xmlparser.SetAllocTrackerActivationThreshold(threshold, /)

   Sets the number of allocated bytes of dynamic memory needed to
   activate protection against disproportionate use of RAM.

   Parser objects usually have an allocation activation threshold of
   64 MiB, but the actual default value depends on the underlying
   Expat library.

   An "ExpatError" is raised if this method is called on a non-root
   parser. The corresponding "lineno" and "offset" should not be used
   as they may have no special meaning.

   Added in version 3.14.1.

xmlparser.SetAllocTrackerMaximumAmplification(max_factor, /)

   Sets the maximum amplification factor between direct input and
   bytes of dynamic memory allocated.

   The amplification factor is calculated as "allocated / direct"
   while parsing, where "direct" is the number of bytes read from the
   primary document in parsing and "allocated" is the number of bytes
   of dynamic memory allocated in the parser hierarchy.

   The *max_factor* value must be a non-NaN "float" value greater than
   or equal to 1.0. Amplification factors greater than 100.0 can be
   observed near the start of parsing even with benign files in
   practice. In particular, the activation threshold should be
   carefully chosen to avoid false positives.

   Parser objects usually have a maximum amplification factor of 100,
   but the actual default value depends on the underlying Expat
   library.

   An "ExpatError" is raised if this method is called on a non-root
   parser or if *max_factor* is outside the valid range. The
   corresponding "lineno" and "offset" should not be used as they may
   have no special meaning.

   注釈:

     The maximum amplification factor is only considered if the
     threshold that can be adjusted by
     "SetAllocTrackerActivationThreshold()" is exceeded.

   Added in version 3.14.1.

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

xmlparser.buffer_size

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

xmlparser.buffer_text

   Setting this to true causes the "xmlparser" object to buffer
   textual content returned by Expat to avoid multiple calls to the
   "CharacterDataHandler()" callback whenever possible.  This can
   improve performance substantially since Expat normally breaks
   character data into chunks at every line ending.  This attribute is
   false by default, and may be changed at any time. Note that when it
   is false, data that does not contain newlines may be chunked too.

xmlparser.buffer_used

   "buffer_text" が利用可能なとき、バッファに保持されたバイト数です。
   これらのバイトはUTF-8でエンコードされたテキストを表します。この属性
   は "buffer_text" が偽の時には意味がありません。

xmlparser.ordered_attributes

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

xmlparser.specified_attributes

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

以下の属性には、 "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)

   XML 宣言が解析された時に呼ばれます。 XML宣言は XML 勧告の適用バージ
   ョン、文書テクストのエンコード、ならびに任意の "standalone" 宣言の
   (任意の) 宣言です。 *version* と *encoding* は文字列で、
   *standalone* は文書がスタンドアローンと宣言された場合は "1"、スタン
   ドアローンでないと宣言された場合は "0"、スタンドアローン節がない場
   合は "-1" です。 Expat のバージョン 1.95.0 以降でのみ使用できます。

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

   Called when Expat begins parsing the document type declaration
   ("<!DOCTYPE ...").  The *doctypeName* is provided exactly as
   presented.  The *systemId* and *publicId* parameters give the
   system and public identifiers if specified, or "None" if omitted.
   *has_internal_subset* will be true if the document contains an
   internal document declaration subset. This requires Expat version
   1.2 or newer.

xmlparser.EndDoctypeDeclHandler()

   Expatが文書型宣言の解析を終えたときに呼び出されます。このハンドラに
   は、Expat version 1.2以上が必要です。

xmlparser.ElementDeclHandler(name, model)

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

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

   ひとつの要素型で宣言される属性ごとに呼び出されます。属性リストの宣
   言が 3つの属性を宣言したとすると、このハンドラは各属性に1度ずつ、 3
   度呼び出されます。 *elname* は要素名であり、これに対して宣言が適用
   され、 *attname* が宣言された属性名となります。属性型は文字列で、
   *type* として渡されます。取り得る値は、 "'CDATA'", "'ID'",
   "'IDREF'", ... です。 *default* は、文書のインスタンスによって属性
   が指定されていないときに使用されるデフォルト値です。デフォルト値
   ("#IMPLIED" values)が存在しないときには "None" を与えます。文書のイ
   ンスタンス中に属性値を与える必要のあるときには *required* が true
   になります。これにはExpat version 1.95.0 以上が必要です。

xmlparser.StartElementHandler(name, attributes)

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

xmlparser.EndElementHandler(name)

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

xmlparser.ProcessingInstructionHandler(target, data)

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

xmlparser.CharacterDataHandler(data)

   Called for character data.  This will be called for normal
   character data, CDATA marked content, and ignorable whitespace.
   Applications which must distinguish these cases can use the
   "StartCdataSectionHandler", "EndCdataSectionHandler", and
   "ElementDeclHandler" callbacks to collect the required information.
   Note that the character data may be chunked even if it is short and
   so you may receive more than one call to "CharacterDataHandler()".
   Set the "buffer_text" instance attribute to "True" to avoid that.

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

   解析されていない (NDATA) エンティティ宣言を処理するために呼び出され
   ます。このハンドラは Expat ライブラリのバージョン1.2のためだけに存
   在します; より最近のバージョンでは、代わりに "EntityDeclHandler" を
   使用してください (根底にある Expat ライブラリ内の関数は、撤廃された
   ものであると宣言されています)。

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

   エンティティ宣言ごとに呼び出されます。パラメタと内部エンティティに
   ついて、 *value* はエンティティ宣言の宣言済みの内容を与える文字列と
   なります; 外部エンティティの時には "None" となります。解析済みエン
   ティティの場合、 *notationName* パラメタは "None" となり、解析され
   ていないエンティティの時には記法 (notation) 名となります。
   *is_parameter_entity* は、エンティティがパラメタエンティティの場合
   真に、一般エンティティ (general entitiy) の場合には偽になります (ほ
   とんどのアプリケーションでは、一般エンティティのことしか気にする必
   要がありません)。このハンドラは Expat ライブラリのバージョン1.95.0
   以降でのみ使用できます。

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

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

xmlparser.StartNamespaceDeclHandler(prefix, uri)

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

xmlparser.EndNamespaceDeclHandler(prefix)

   名前空間宣言を含んでいたエレメントの終了タグに到達したときに呼び出
   されます。このハンドラは、要素に関する名前空間宣言ごとに、
   "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)

   警告:

     Implementing a handler that accesses local files and/or the
     network may create a vulnerability to external entity attacks if
     "xmlparser" is used with user-provided XML content. Please
     reflect on your threat model before implementing this handler.

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

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

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


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 handler functions
   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)、名前、そし
て子のタプル。子のタプルは単に内容モデルを記述したものです。

The values of the first two fields are constants defined in the
"xml.parsers.expat.model" module.  These constants can be collected in
two groups: the model type group and the quantifier group.

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

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

xml.parsers.expat.model.XML_CTYPE_NAME

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 エラー定数
================

The following constants are provided in the "xml.parsers.expat.errors"
module.  These constants are useful in interpreting some of the
attributes of the "ExpatError" exception objects raised when an error
has occurred. Since for backwards compatibility reasons, the
constants' value is the error *message* and not the numeric error
*code*, you do this by comparing its "code" attribute with
"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 では全ての文書は確実に最上位の要
   素を正確に一つ持たなければなりません)。

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文書が "standalone" だと宣言されており "NotStandaloneHandler" が
   設定され "0" が返されているにもかかわらず、パーサは "standalone" で
   はないと判別しました。

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

   An operation was requested that requires DTD support to be compiled
   in, but Expat was configured without DTD support.  This should
   never be reported by a standard build of the "xml.parsers.expat"
   module.

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

   An attempt was made to undeclare reserved namespace prefix "xml" or
   to bind it to another namespace URI.

xml.parsers.expat.errors.XML_ERROR_RESERVED_PREFIX_XMLNS

   An attempt was made to declare or undeclare reserved namespace
   prefix "xmlns".

xml.parsers.expat.errors.XML_ERROR_RESERVED_NAMESPACE_URI

   An attempt was made to bind the URI of one the reserved namespace
   prefixes "xml" and "xmlns" to another namespace prefix.

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

   The limit on input amplification factor (from DTD and entities) has
   been breached.

xml.parsers.expat.errors.XML_ERROR_NOT_STARTED

   The parser was tried to be stopped or suspended before it 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 を参照してください。
