xml.dom.minidom —最小限のDOM実装—Pythonドキュメント

提供:Dev Guides
< PythonPython/docs/3.8/library/xml.dom.minidom
移動先:案内検索

xml.dom.minidom —最小限のDOM実装

ソースコード: :source: `Lib / xml / dom / minidom.py`



xml.dom.minidom は、他の言語のAPIと同様のAPIを使用した、ドキュメントオブジェクトモデルインターフェイスの最小限の実装です。 これは、完全なDOMよりも単純で、大幅に小さいことを目的としています。 まだDOMに習熟していないユーザーは、代わりに xml.etree.ElementTree モジュールをXML処理に使用することを検討する必要があります。

警告

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


DOMアプリケーションは通常、一部のXMLをDOMに解析することから始まります。 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=None, bufsize=None)
指定された入力からDocumentを返します。 filename_or_file は、ファイル名またはファイルのようなオブジェクトのいずれかです。 parser は、指定されている場合、SAX2パーサーオブジェクトである必要があります。 この関数は、パーサーのドキュメントハンドラーを変更し、名前空間のサポートをアクティブにします。 他のパーサー構成(エンティティリゾルバーの設定など)は、事前に行っておく必要があります。

文字列にXMLがある場合は、代わりに parseString()関数を使用できます。

xml.dom.minidom.parseString(string, parser=None)
文字列を表すDocumentを返します。 このメソッドは、文字列の io.StringIO オブジェクトを作成し、それを parse()に渡します。

どちらの関数も、ドキュメントのコンテンツを表すDocumentオブジェクトを返します。

parse()および parseString()関数が行うことは、XMLパーサーを任意のSAXパーサーからの解析イベントを受け入れてDOMツリーに変換できる「DOMビルダー」に接続することです。 。 関数の名前は誤解を招く可能性がありますが、インターフェイスを学習するときに簡単に理解できます。 ドキュメントの解析は、これらの関数が戻る前に完了します。 これらの関数自体がパーサーの実装を提供しないというだけです。

「DOMImplementation」オブジェクトのメソッドを呼び出して、Documentを作成することもできます。 このオブジェクトは、 xml.dom パッケージのgetDOMImplementation()関数または xml.dom.minidom モジュールを呼び出すことで取得できます。 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ツリーが完成したら、オプションでunlink()メソッドを呼び出して、不要になったオブジェクトの早期クリーンアップを促進できます。 unlink()は、 xml.dom.minidom 固有のDOMAPIの拡張機能であり、ノードとその子孫を本質的に役に立たないものにします。 それ以外の場合、Pythonのガベージコレクターは最終的にツリー内のオブジェクトを処理します。

も参照してください

ドキュメントオブジェクトモデル(DOM)レベル1仕様
xml.dom.minidom でサポートされているDOMのW3C勧告。


DOMオブジェクト

Python用のDOMAPIの定義は、 xml.dom モジュールのドキュメントの一部として提供されています。 このセクションでは、APIと xml.dom.minidom の違いを示します。

Node.unlink()

DOM内の内部参照を分割して、サイクリックGCのないバージョンのPythonでガベージコレクションされるようにします。 サイクリックGCが使用可能な場合でも、これを使用すると大量のメモリをより早く使用できるようになる可能性があるため、DOMオブジェクトで不要になったらすぐにこれを呼び出すことをお勧めします。 これは、Documentオブジェクトでのみ呼び出す必要がありますが、子ノードで呼び出すと、そのノードの子を破棄できます。

with ステートメントを使用すると、このメソッドを明示的に呼び出すことを回避できます。 次のコードは、withブロックが終了すると、 dom のリンクを自動的に解除します。

with xml.dom.minidom.parse(datasource) as dom:
    ... # Work with dom.
Node.writexml(writer, indent=, addindent=, newl=)

XMLをライターオブジェクトに書き込みます。 ライターはテキストを受け取りますが、入力としてバイトは受け取りません。ファイルオブジェクトインターフェイスのメソッドと一致するwrite()メソッドが必要です。 indent パラメーターは、現在のノードのインデントです。 addindent パラメーターは、現在のサブノードに使用する増分インデントです。 newl パラメーターは、改行を終了するために使用する文字列を指定します。

Documentノードの場合、追加のキーワード引数 encoding を使用して、XMLヘッダーのエンコードフィールドを指定できます。

バージョン3.8で変更: writexml()メソッドは、ユーザーが指定した属性の順序を保持するようになりました。

Node.toxml(encoding=None)

DOMノードで表されるXMLを含む文字列またはバイト文字列を返します。

明示的な encoding 1 引数を使用すると、結果は指定されたエンコーディングのバイト文字列になります。 encoding 引数がない場合、結果はUnicode文字列になり、結果の文字列のXML宣言はエンコーディングを指定しません。 UTF-8はXMLのデフォルトのエンコーディングであるため、この文字列をUTF-8以外のエンコーディングでエンコードすることはおそらく正しくありません。

バージョン3.8で変更: toxml()メソッドは、ユーザーが指定した属性の順序を保持するようになりました。

Node.toprettyxml(indent='\\t', newl='\\n', encoding=None)

きれいに印刷されたバージョンのドキュメントを返します。 indent はインデント文字列を指定し、デフォルトはタブキーです。 newl は、各行の終わりに出力される文字列を指定し、デフォルトは\nです。

encoding 引数は、 toxml()の対応する引数のように動作します。

バージョン3.8で変更: toprettyxml()メソッドは、ユーザーが指定した属性の順序を保持するようになりました。


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.append(node.data)
    return ''.join(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)

minidomとDOM標準

xml.dom.minidom モジュールは、基本的にDOM 1.0互換のDOMであり、いくつかのDOM 2機能(主に名前空間機能)を備えています。

PythonでのDOMインターフェースの使用法は簡単です。 次のマッピングルールが適用されます。

  • インターフェイスには、インスタンスオブジェクトを介してアクセスします。 アプリケーションはクラス自体をインスタンス化するべきではありません。 Documentオブジェクトで使用可能なクリエーター関数を使用する必要があります。 派生インターフェースは、基本インターフェースからのすべての操作(および属性)に加えて、新しい操作をサポートします。
  • 演算はメソッドとして使用されます。 DOMは in パラメーターのみを使用するため、引数は通常の順序(左から右)で渡されます。 オプションの引数はありません。 void操作はNoneを返します。
  • IDL属性はインスタンス属性にマップされます。 PythonのOMGIDL言語マッピングとの互換性のために、属性fooには、アクセサーメソッド_get_foo()および_set_foo()を介してアクセスすることもできます。 readonly属性は変更しないでください。 これは実行時に強制されません。
  • タイプshort intunsigned intunsigned long long、およびbooleanはすべて、Python整数オブジェクトにマップされます。
  • タイプDOMStringはPython文字列にマップされます。 xml.dom.minidom はバイトまたは文字列のいずれかをサポートしますが、通常は文字列を生成します。 タイプDOMStringの値は、W3CのDOM仕様によってIDL null値を持つことが許可されている場合、Noneにすることもできます。
  • const宣言は、それぞれのスコープ内の変数にマップされます(例: xml.dom.minidom.Node.PROCESSING_INSTRUCTION_NODE); それらは変更してはなりません。
  • DOMExceptionは現在、 xml.dom.minidom ではサポートされていません。 代わりに、 xml.dom.minidom は、 TypeErrorAttributeError などの標準のPython例外を使用します。
  • NodeListオブジェクトは、Pythonの組み込みリストタイプを使用して実装されます。 これらのオブジェクトは、DOM仕様で定義されたインターフェースを提供しますが、以前のバージョンのPythonでは、公式APIをサポートしていません。 ただし、これらはW3Cの推奨事項で定義されているインターフェイスよりもはるかに「Pythonic」です。

次のインターフェイスは、 xml.dom.minidom に実装されていません。

  • DOMTimeStamp
  • EntityReference

これらのほとんどは、ほとんどのDOMユーザーにとって一般的な有用性ではないXMLドキュメント内の情報を反映しています。

脚注

1
XML出力に含まれるエンコーディング名は、適切な標準に準拠している必要があります。 たとえば、「UTF-8」は有効ですが、「UTF8」は、Pythonがエンコード名として受け入れている場合でも、XMLドキュメントの宣言では無効です。 https://www.w3.org/TR/2006/REC-xml11-20060816/#NT-EncodingDeclおよび https://www.iana.org/assignments/character-setsを参照してください。 /character-sets.xhtml