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

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

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

"xml.dom.pulldom" モジュールは "プルパーザ" を提供します。 プルパーザ
は必要に応じて文書の DOM アクセス可能な断片を生成することができます。
基本概念は、入力 XML のストリームから "イベント" を取り出し (pull し)
て処理することです。 SAX とは、コールバックつきのイベント駆動処理モデ
ルを採用しているという点で同様ですが、SAX とは対照的に、プルパーザの使
用者には処理が完了するかエラー状態が発生するまで、明示的にストリームか
らイベントを取り出し、イベントに対しループを回す責任があります。

警告:

  "xml.dom.pulldom" モジュールは悪意を持って作成されたデータに対して安
  全ではありません。信頼できないデータや認証されていないデータをパース
  する必要がある場合は 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" は定数で以下の内の一つです:

* "START_ELEMENT"

* "END_ELEMENT"

* "COMMENT"

* "START_DOCUMENT"

* "END_DOCUMENT"

* "CHARACTERS"

* "PROCESSING_INSTRUCTION"

* "IGNORABLE_WHITESPACE"

"node" は型 "xml.dom.minidom.Document"、 "xml.dom.minidom.Element" ま
たは "xml.dom.minidom.Text" のオブジェクトです。

文書はイベントの *フラットな* 流れとして扱われるため、文書の "木" は暗
黙のうちに全て読み込まれ、目的の要素は木の中の深さに依らずに見つけられ
ます。つまり、文書ノードの再帰的な検索のような階層的な問題を考える必要
はありません。しかしながら要素の前後関係が重要な場合は、前後関係の状態
を維持する (すなわち文章中の任意の点の場所を記憶する) か、
"DOMEventStream.expandNode()" メソッドを使用して DOM 関連の処理に切り
替える必要があります。

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

   "xml.sax.handler.ContentHandler" のサブクラスです。

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

   "xml.sax.handler.ContentHandler" のサブクラスです。

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" を返します。

xml.dom.pulldom.default_bufsize

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

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


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

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

   バージョン 3.8 で非推奨: "シーケンスプロトコル" のサポートは非推奨
   になりました。

   getEvent()

      event が "START_DOCUMENT" の場合は *event* と
      "xml.dom.minidom.Document" としての現在の *node* からなるタプル
      を、 "START_ELEMENT" か "END_ELEMENT" の場合は
      "xml.dom.minidom.Element" を、 "CHARACTERS" の場合は
      "xml.dom.minidom.Text" を返します。 "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':
                 # Following statement only prints '<p/>'
                 print(node.toxml())
                 doc.expandNode(node)
                 # Following statement prints node with all its children '<p>Some text <div>and more</div></p>'
                 print(node.toxml())

   reset()
