### ナビゲーション

- 索引
- モジュール |
- 次へ |
- 前へ |
- Python v2.6.2 documentation »
- Python 標準ライブラリ »
- 20. 構造化マークアップツール »

# 20.7. `xml.dom.minidom` — 軽量な DOM 実装

バージョン 2.0 で追加.

`xml.dom.minidom` は、軽量な文書オブジェクトモデルインタフェースの実装です。この実装では、完全な DOM よりも 単純で、かつ十分に小さくなるよう意図しています。

DOM アプリケーションは典型的に、XML を DOM に解析 (parse) することで開始します。 `xml.dom.minidom` では、以下のような解析用の関数を介して行います:

    from xml.dom.minidom import parse, parseString

    dom1 = parse('c:\\temp\\mydata.xml') # parse an XML file by name

    datasource = open('c:\\temp\\mydata.xml')
    dom2 = parse(datasource)   # parse an open file

    dom3 = parseString('<myxml>Some data<empty/> some more data</myxml>')

`parse()` 関数はファイル名か、開かれたファイルオブジェクトを引数にとることができます。

`xml.dom.minidom.``parse`(filename_or_file, parser)

  与えられた入力から `Document` を返します。 filename_or_file はファイル名でもファイルオブジェクトでもかまいません。 parser を指定する場合、SAX2 パーザオブジェクトでなければなりません。 この関数はパーザの文書ハンドラを変更し、名前空間サポートを有効にします; (エンティティリゾルバ (entity resolver) のような) 他のパーザ設定は前もっておこなわなければなりません。

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

`xml.dom.minidom.``parseString`(string[, parser])

  string を表現する `Document` を返します。このメソッドは文字列に対する `StringIO` オブジェクトを生成して、そのオブジェクトを `parse()` に渡します。

これらの関数は両方とも、文書の内容を表現する `Document` オブジェクトを返します。

`parse()` や `parseString()` といった関数が行うのは、 XML パーザを、何らかの SAX パーザからくる解析イベント (parse event) を受け取って DOM ツリーに変換できるような “DOM ビルダ (DOM builder)” に結合することです。関数は誤解を招くような名前になっているかもしれませんが、インタフェースについて学んでいるときには理解しやすい でしょう。文書の解析はこれらの関数が戻るより前に完結します; 要するに、これらの関数自体はパーザ実装を提供しないということです。

“DOM 実装” オブジェクトのメソッドを呼び出して `Document` を 生成することもできます。このオブジェクトは、 `xml.dom` パッケージ、または `xml.dom.minidom` モジュールの `getDOMImplementation()` 関数を呼び出して取得できます。 `xml.dom.minidom` モジュールの実装を使うと、常に minidom 実装の `Document` インスタンスを返します。一方、 `xml.dom` 版の関数では、別の実装によるインスタンスを返すかもれません (PyXML package がインストールされているとそうなるでしょう)。 `Document` を取得したら、DOM を構成するために子ノードを追加していくことができます:

    from xml.dom.minidom import getDOMImplementation

    impl = getDOMImplementation()

    newdoc = impl.createDocument(None, "some_tag", None)
    top_element = newdoc.documentElement
    text = newdoc.createTextNode('Some textual content.')
    top_element.appendChild(text)

DOM 文書オブジェクトを手にしたら、XML 文書のプロパティやメソッドを使って、文書の一部にアクセスすることができます。これらのプロパティは DOM 仕様で定義されています。文書オブジェクトの主要なプロパティは `documentElement` プロパティです。このプロパティは XML 文書の主要な要素: 他の全ての要素を保持する要素、を与えます。以下にプログラム例を示します:

    dom3 = parseString("<myxml>Some data</myxml>")
    assert dom3.documentElement.tagName == "myxml"

DOM を使い終えたら、後片付けを行わなければなりません。 Python のバージョンによっては、循環的に互いを参照するオブジェクト に対するガベージコレクションをサポートしていないため、この操作が必要となります。この制限が全てのバージョンの Python から除去される までは、循環参照オブジェクトが消去されないものとしてコードを書くのが無難です。

DOM を片付けるには、 `unlink()` メソッドを呼び出します:

    dom1.unlink()
    dom2.unlink()
    dom3.unlink()

`unlink()` は、 DOM API に対する `xml.dom.minidom` 特有の拡張です。ノードに対して `unlink()` を呼び出した後は、ノードとその下位ノードは本質的には無意味なものとなります。

参考

Document Object Model (DOM) Level 1 Specification
  `xml.dom.minidom` でサポートされている DOM の W3C 勧告。

## 20.7.1. DOM オブジェクト

Python の DOM API 定義は `xml.dom` モジュールドキュメント の一部として与えられています。この節では、 `xml.dom` の API と `xml.dom.minidom` との違いについて列挙します。

`Node.``unlink`()

  DOM との内部的な参照を破壊して、循環参照ガベージコレクションを持たないバージョンの Python でもガベージコレクションされるように します。循環参照ガベージコレクションが利用できても、このメソッドを使えば、大量のメモリをすぐに使えるようにできるため、必要なくなったらすぐにこのメソッドを DOM オブジェクトに対して呼ぶのが良い習慣です。このメソッドは `Document` オブジェクトに対してだけ呼び出せば よいのですが、あるノードの子ノードを放棄するために子ノードに対して呼び出してもかまいません。

`Node.``writexml`(writer[, indent=""[, addindent=""[, newl=""[, encoding=""]]]])

  XML を writer オブジェクトに書き込みます。 writer は、ファイルオブジェクトインタフェースの `write()` に該当する メソッドを持たなければなりません。 indent パラメタには現在のノードのインデントを指定します。 addindent パラメタには現在のノードの下にサブノードを追加する際のインデント増分を指定します。 newl には、改行時に行末を終端する文字列を指定します。

  バージョン 2.1 で変更: 美しい出力をサポートするため、新たなキーワード引数 indent 、 addindent 、および newl が追加されました.

  バージョン 2.3 で変更: `Document` ノードに対して、追加のキーワード引数 encoding を使って、 XML ヘッダの encoding フィールドを指定できるようになりました.

`Node.``toxml`([encoding])

  DOM が表現している XML を文字列にして返します。

  引数がなければ、 XML ヘッダは encoding を指定せず、文書内の全ての文字をデフォルトエンコード方式で表示できない場合、結果は Unicode 文字列となります。この文字列を UTF-8 以外のエンコード方式でエンコードするのは不正であり、なぜなら UTF-8 が XML のデフォルトエンコード方式だからです。

  明示的な encoding [1] 引数があると、結果は指定されたエンコード方式によるバイト文字列となります。引数を常に指定するよう推奨します。 表現不可能なテキストデータの場合に `UnicodeError` が送出されるのを避けるため、encoding 引数は “utf-8” に指定するべきです。

  バージョン 2.3 で変更: encoding が追加されました。 `writexml()` を参照して下さい。

`Node.``toprettyxml`([indent=""[, newl=""[, encoding=""]]])

  美しく出力されたバージョンの文書を返します。 indent はインデントを行うための文字で、デフォルトはタブです; newl には行末で出力される文字列を指定し、デフォルトは `\n` です。

  バージョン 2.1 で追加.

  バージョン 2.3 で変更: encoding 引数が追加されました。 `writexml()` を参照して下さい。

以下の標準 DOM メソッドは、 `xml.dom.minidom` では特別な注意をする必要があります:

`Node.``cloneNode`(deep)

  このメソッドは Python 2.0 にパッケージされているバージョンの `xml.dom.minidom` にはありましたが、これには深刻な 障害があります。以降のリリースでは修正されています。

## 20.7.2. DOM の例

以下のプログラム例は、かなり現実的な単純なプログラムの例です。特にこの例に関しては、DOM の柔軟性をあまり活用してはいません。

    import xml.dom.minidom

    document = """\
    <slideshow>
    <title>Demo slideshow</title>
    <slide><title>Slide title</title>
    <point>This is a demo</point>
    <point>Of a program for processing slides</point>
    </slide>

    <slide><title>Another demo slide</title>
    <point>It is important</point>
    <point>To have more than</point>
    <point>one slide</point>
    </slide>
    </slideshow>
    """

    dom = xml.dom.minidom.parseString(document)

    def getText(nodelist):
        rc = ""
        for node in nodelist:
            if node.nodeType == node.TEXT_NODE:
                rc = rc + node.data
        return rc

    def handleSlideshow(slideshow):
        print "<html>"
        handleSlideshowTitle(slideshow.getElementsByTagName("title")[0])
        slides = slideshow.getElementsByTagName("slide")
        handleToc(slides)
        handleSlides(slides)
        print "</html>"

    def handleSlides(slides):
        for slide in slides:
            handleSlide(slide)

    def handleSlide(slide):
        handleSlideTitle(slide.getElementsByTagName("title")[0])
        handlePoints(slide.getElementsByTagName("point"))

    def handleSlideshowTitle(title):
        print "<title>%s</title>" % getText(title.childNodes)

    def handleSlideTitle(title):
        print "<h2>%s</h2>" % getText(title.childNodes)

    def handlePoints(points):
        print "<ul>"
        for point in points:
            handlePoint(point)
        print "</ul>"

    def handlePoint(point):
        print "<li>%s</li>" % getText(point.childNodes)

    def handleToc(slides):
        for slide in slides:
            title = slide.getElementsByTagName("title")[0]
            print "<p>%s</p>" % getText(title.childNodes)

    handleSlideshow(dom)

## 20.7.3. minidom と DOM 標準

`xml.dom.minidom` モジュールは、本質的には DOM 1.0 互換の DOM に、いくつかの DOM 2 機能 (主に名前空間機能) を追加したものです。

Python における DOM インタフェースは率直なものです。以下の対応付け規則が適用されます:

- インタフェースはインスタンスオブジェクトを介してアクセスされます。アプリケーション自身から、クラスをインスタンス化してはなりません; `Document` オブジェクト上で利用可能な生成関数 (creator function) を使わなければなりません。導出インタフェースでは基底インタフェースの全ての演算 (および属性) に加え、新たな演算をサポートします。
- 演算はメソッドとして使われます。DOM では `in` パラメタのみを使うので、引数は通常の順番 (左から右へ) で渡されます。 オプション引数はありません。 void 演算は `None` を返します。
- IDL 属性はインスタンス属性に対応付けられます。OMG IDL 言語における Python への対応付けとの互換性のために、属性 `foo` はアクセサメソッド `_get_foo()` および `_set_foo()` でもアクセスできます。 readonly 属性は変更してはなりません; とはいえ、これは実行時には強制されません。
- `short int` 、 `unsigned int` 、 `unsigned long long` 、および `boolean` 型は、全て Python 整数オブジェクトに対応付けられます。
- `DOMString` 型は Python 文字列型に対応付けられます。 `xml.dom.minidom` ではバイト文字列 (byte string) および Unicode 文字列のどちらかに対応づけられますが、通常 Unicode 文字列を生成します。 `DOMString` 型の値は、W3C の DOM 仕様で、IDL `null` 値になってもよいとされている場所では `None` になることもあります。
- const 宣言を行うと、 (`xml.dom.minidom.Node.PROCESSING_INSTRUCTION_NODE` のように) 対応するスコープ内の変数に対応付けを行います; これらは変更してはなりません。
- `DOMException` は現状では `xml.dom.minidom` でサポートされていません。その代わり、 `xml.dom.minidom` は、 `TypeError` や `AttributeError` といった標準の Python 例外を使います。
- `NodeList` オブジェクトは Python の組み込みリスト型を使って実装されています。 Python 2.2 からは、これらのオブジェクトは DOM 仕様で定義されたインタフェースを提供していますが、それ以前のバージョンの Python では、公式の API をサポートしていません。しかしながら、これらの API は W3C 勧告で定義されたインタフェースよりも “Python 的な” ものになっています。

以下のインタフェースは `xml.dom.minidom` では全く実装されていません:

- `DOMTimeStamp`
- `DocumentType` (added in Python 2.1)
- `DOMImplementation` (added in Python 2.1)
- `CharacterData`
- `CDATASection`
- `Notation`
- `Entity`
- `EntityReference`
- `DocumentFragment`

これらの大部分は、ほとんどの DOM のユーザにとって一般的な用途として有用とはならないような XML 文書内の情報を反映しています。

Footnotes

[1] | XML の出力に含まれるエンコーディング文字列は適切な標準に適合していなければなりません。 たとえば、”UTF-8” は正当ですが、”UTF8” は違います。 http://www.w3.org/TR/2006/REC-xml11-20060816/#NT-EncodingDecl と http://www.iana.org/assignments/character-sets を参照して下さい。

### ナビゲーション

- 索引
- モジュール |
- 次へ |
- 前へ |
- Python v2.6.2 documentation »
- Python 標準ライブラリ »
- 20. 構造化マークアップツール »