# 20.8. `xml.dom.pulldom` --- 部分的な DOM ツリー構築のサポート

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

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

警告

`xml.dom.pulldom` モジュールは悪意を持って作成されたデータに対して安全ではありません。信頼できないデータや認証されていないデータをパースする必要がある場合は XML の脆弱性 を参照してください。

バージョン 3.6.7 で変更: 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()` を呼び出す前に変更することができます。その場合、その新しい値が有効になります。

## 20.8.1. DOMEventStream オブジェクト

class `xml.dom.pulldom.``DOMEventStream`(stream, parser, bufsize)
  `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`()