"xml.dom.pulldom" --- 部分的な DOM ツリー構築のサポート
*******************************************************

**Source code:** Lib/xml/dom/pulldom.py

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

"xml.dom.pulldom" モジュールは「プルパーザ」を提供し、必要に応じて、文
書の一部分を DOM でアクセスできる形で生成するよう要求できます。 基本的
な考え方は、入力される XML ストリームから「イベント」を取り出し、それ
を処理するというものです。 SAX もコールバックを使うイベント駆動の処理
モデルを採用していますが、プルパーザでは利用者が明示的にストリームから
イベントを取り出します。 利用者は処理が完了するかエラーが起こるまで、
イベントを順に処理します。

注釈:

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

バージョン 3.7.1 で変更: セキュリティを向上させるため、SAX パーサーは
デフォルトでは外部一般エンティティを処理しなくなりました。 外部エンテ
ィティの処理を有効にするには、次のようにカスタムのパーサーインスタンス
を渡します。

   from xml.dom.pulldom import parse
   from xml.sax import make_parser
   from xml.sax.handler import feature_external_ges

   parser = make_parser()
   parser.setFeature(feature_external_ges, True)
   parse(filename, parser=parser)

以下はプログラム例です:

   from xml.dom import pulldom

   doc = pulldom.parse('sales_items.xml')
   for event, node in doc:
       if event == pulldom.START_ELEMENT and node.tagName == 'item':
           if int(node.getAttribute('price')) > 50:
               doc.expandNode(node)
               print(node.toxml())

"event" は以下の定数のいずれかで、"node" はイベントの対象となるノード
です。 ノードは "xml.dom" のインターフェースを実装しており、"PullDOM"
に渡された DOM 実装によって作成されます。 デフォルトの実装は
"xml.dom.minidom" です。

xml.dom.pulldom.START_DOCUMENT
xml.dom.pulldom.END_DOCUMENT

   文書の開始と終了です。 *node* は "Document" です。

xml.dom.pulldom.START_ELEMENT
xml.dom.pulldom.END_ELEMENT

   要素の開始タグと終了タグです。 *node* は "Element" です。

xml.dom.pulldom.CHARACTERS

   文字データです。 *node* は "Text" ノードです。

xml.dom.pulldom.IGNORABLE_WHITESPACE

   DTD の宣言に基づく、要素内容中の空白です。 *node* は "Text" ノード
   です。

xml.dom.pulldom.COMMENT

   コメントです。 *node* は "Comment" ノードです。

xml.dom.pulldom.PROCESSING_INSTRUCTION

   処理命令です。 *node* は "ProcessingInstruction" ノードです。

文書を「平坦な」イベントの流れとして扱うため、文書の「木」は暗黙的に走
査され、木の中の深さにかかわらず目的の要素を見つけられます。 つまり、
文書ノードを再帰的に検索するなど、階層構造を考慮する必要はありません。
ただし、要素の文脈が重要な場合は、文脈に関する状態を管理する (文書中の
どの位置にいるかを常に記憶する) か、 "DOMEventStream.expandNode()" メ
ソッドを使って DOM による処理に切り替える必要があります。

class xml.dom.pulldom.PullDOM(documentFactory=None)

   SAX イベントをプルパーザのイベントに変換する、
   "xml.sax.handler.ContentHandler" のサブクラスです。 ノードは作成し
   ますが、"expandNode()" を呼び出さない限り木には追加しません。
   *documentFactory* を指定する場合は、文書を作成するための DOM 実装を
   渡します。 デフォルトでは "xml.dom.minidom" の実装を使います。

class xml.dom.pulldom.SAX2DOM(documentFactory=None)

   作成したノードをすべて木にも追加して完全な文書を構築する、"PullDOM"
   のサブクラスです。

xml.dom.pulldom.parse(stream_or_string, parser=None, bufsize=None)

   与えられた入力から "DOMEventStream" を返します。*stream_or_string*
   はファイル名かファイル様オブジェクトのいずれかです。*parser* は、与
   えれた場合、 "XMLReader" オブジェクトでなければなりません。この関数
   はパーザの文書ハンドラを変えて名前空間のサポートを有効にします。パ
   ーザの他の設定 (例えばエンティティリゾルバ) は前もってしておかなけ
   ればなりません。

XML データを文字列で持っている場合、 "parseString()" を代わりに使うこ
とができます:

xml.dom.pulldom.parseString(string, parser=None)

   *string* を表す "DOMEventStream" を返します。 *string* は "str" イ
   ンスタンスでなければなりません。 バイト列を解析するには、バイナリフ
   ァイルオブジェクトを "parse()" に渡してください。

xml.dom.pulldom.default_bufsize

   "parse()" の *bufsize* パラメタのデフォルト値です。

   この変数の値は "parse()" を呼び出す前に変更することができます。その
   場合、その新しい値が有効になります。


DOMEventStream オブジェクト
===========================

class xml.dom.pulldom.DOMEventStream(stream, parser, bufsize)

   "XMLReader" である *parser* がファイルオブジェクト *stream* から読
   み取ったデータに対するイベントを生成します。 データは一度に
   *bufsize* バイトずつ (テキストストリームの場合は文字数) 読み取りま
   す。

   バージョン 3.11 で変更: "__getitem__()" メソッドのサポートは削除さ
   れました。

   getEvent()

      次の "(event, node)" タプルを返します。 文書の末尾では "None" を
      返します。 イベントと対応するノードについては上記を参照してくだ
      さい。 "expandNode()" を呼び出さない限り、現在のノードには子ノー
      ドの情報が含まれません。

   expandNode(node)

      *node* の全子ノードを *node* に展開します。例:

         from xml.dom import pulldom

         xml = '<html><title>Foo</title> <p>Some text <div>and more</div></p> </html>'
         doc = pulldom.parseString(xml)
         for event, node in doc:
             if event == pulldom.START_ELEMENT and node.tagName == 'p':
                 # 次の文は '<p/>' だけを表示する。
                 print(node.toxml())
                 doc.expandNode(node)
                 # 次の文はすべての子を含むノード '<p>Some text <div>and more</div></p>' を表示する。
                 print(node.toxml())

   reset()

      まだ読み取っていないイベントを破棄し、新しい文書の解析に向けてオ
      ブジェクトを準備します。

   clear()

      パーザと文書を解放します。 ストリームは閉じませんが、このオブジ
      ェクトは以後使用できなくなります。
