Pythonを使用して単純なXMLファイルを作成する


160

Pythonで単純なXMLファイルを作成する場合のオプションは何ですか?(ライブラリに関して)

私が欲しいxmlは次のようになります:

<root>
 <doc>
     <field1 name="blah">some value1</field1>
     <field2 name="asdfasd">some vlaue2</field2>
 </doc>

</root>

回答:


309

最近、最も人気のある(そして非常にシンプルな)オプションはElementTree APIで、Python 2.5以降の標準ライブラリに含まれています。

利用可能なオプションは次のとおりです。

  • ElementTree(ElementTreeの基本的な純粋なPython実装。2.5以降の標準ライブラリの一部)
  • cElementTree(ElementTreeの最適化されたC実装。2.5以降の標準ライブラリでも提供)
  • LXML(libxml2に基づく。ElementTreeAPIの豊富なスーパーセット、XPath、CSSセレクターなどを提供)

以下は、stdlib内のcElementTreeを使用してサンプルドキュメントを生成する方法の例です。

import xml.etree.cElementTree as ET

root = ET.Element("root")
doc = ET.SubElement(root, "doc")

ET.SubElement(doc, "field1", name="blah").text = "some value1"
ET.SubElement(doc, "field2", name="asdfasd").text = "some vlaue2"

tree = ET.ElementTree(root)
tree.write("filename.xml")

私はそれをテストしました、そしてそれは機能します、しかし私は空白が重要ではないと仮定しています。「プリティプリント」のインデントが必要な場合はお知らせください。その方法を調べます。(これはLXML固有のオプションである可能性があります。私はstdlib実装をあまり使用していません)

さらに読むために、ここにいくつかの便利なリンクがあります:

最後の注意として、cElementTreeまたはLXMLはすべてのニーズに対して十分に高速でなければなりません(どちらも最適化されたCコードです)が、パフォーマンスの最後のすべてのビットを絞り出す必要がある状況では、ベンチマークLXMLサイトは次のことを示しています。

  • LXMLはXMLのシリアライズ(生成)に勝つ
  • 適切な親トラバーサルを実装することの副作用として、LXMLはcElementTreeよりも少し解析が遅くなります。

1
@Kasper:私はMacを持っていないので、問題を再現することはできません。Pythonのバージョンを教えてください。Linuxでそれを複製できるかどうかを確認します。
ssokolow 2014年

4
@nonsensickle新しい質問をしてから、リンクを送って、誰もがそれを利用できるようにするべきでした。しかし、私はあなたを正しい方向に向けます。DOM(Document Object Model)ライブラリは常にメモリ内モデルを構築するため、代わりにSAX(Simple API for XML)実装が必要です。私はSAX実装を調べたことがありませんが、ここでは、入力ではなく出力にin-stdlibを使用するためのチュートリアルがあります。
ssokolow 2014年

1
@YonatanSimsonその正確な文字列を追加する方法がわかりません。ElementTree xml_declaration=Trueはエンコーディングを指定した場合にのみ従うように見えるので...しかし、同等の動作を得るには、次のtree.write()ように呼び出しtree.write("filename.xml", xml_declaration=True, encoding='utf-8')ます。明示的に指定する限り、任意のエンコーディングを使用できます。 1。(asciiWebサーバーが適切に構成されていない場合は、7ビットASCIIセット外のすべてのUnicode文字がエンティティエンコードされることを
強制し

1
修正しようとする他の誰にもちょうどリマインダーvlaue2value2タイプミスが元の質問で要求されたXML出力にあります。それが変わるまで、ここのタイプミスは実際に正しいです。
ssokolow 2017年

3
ドキュメントよると、cElementTreeはPython 3.3で
廃止されました

63

lxmlのライブラリが呼ばれるXML生成のために非常に便利な構文、含まE-工場を。ここにあなたが与える例を私が作る方法があります:

#!/usr/bin/python
import lxml.etree
import lxml.builder    

E = lxml.builder.ElementMaker()
ROOT = E.root
DOC = E.doc
FIELD1 = E.field1
FIELD2 = E.field2

the_doc = ROOT(
        DOC(
            FIELD1('some value1', name='blah'),
            FIELD2('some value2', name='asdfasd'),
            )   
        )   

print lxml.etree.tostring(the_doc, pretty_print=True)

出力:

<root>
  <doc>
    <field1 name="blah">some value1</field1>
    <field2 name="asdfasd">some value2</field2>
  </doc>
</root>

また、すでに作成されたノードへの追加もサポートします。たとえば、上記の後に次のように言うことができます

the_doc.append(FIELD2('another value again', name='hithere'))

3
タグの名前がPython識別子の規則に準拠していない場合はgetattr、などを使用できますgetattr(E, "some-tag")
haridsv 2016年

私にとって、lxml.etree.tostringはAttributeErrorを引き起こしていました: 'lxml.etree._Element'オブジェクトには属性 'etree'がありません。「lxml」を起動しなくても機能しました。例:etree.tostring(the_doc、pretty_print = True)
kodlan

19

Yattag http://www.yattag.org/またはhttps://github.com/leforestier/yattagは、このようなXMLドキュメント(およびHTMLドキュメント)を作成するための興味深いAPIを提供します。

コンテキストマネージャーwithキーワードを使用しています

from yattag import Doc, indent

doc, tag, text = Doc().tagtext()

with tag('root'):
    with tag('doc'):
        with tag('field1', name='blah'):
            text('some value1')
        with tag('field2', name='asdfasd'):
            text('some value2')

result = indent(
    doc.getvalue(),
    indentation = ' '*4,
    newline = '\r\n'
)

print(result)

だからあなたは得るでしょう:

<root>
    <doc>
        <field1 name="blah">some value1</field1>
        <field2 name="asdfasd">some value2</field2>
    </doc>
</root>

6

最も簡単な選択として、私はminidomを使用します:http ://docs.python.org/library/xml.dom.minidom.html 。これはpython標準ライブラリに組み込まれており、単純なケースで簡単に使用できます。

以下のチュートリアルは非常に簡単です。http//www.boddie.org.uk/python/XML_intro.html


6
この回答には、ミニドムの使用例を含める必要があります。
Stevoisiak

4

このような単純なXML構造では、本格的なXMLモジュールを使用したくない場合があります。最も単純な構造には文字列テンプレートを、もう少し複雑なものにはJinjaを検討してください。Jinjaは、データリストのループを処理して、ドキュメントリストの内部xmlを生成できます。未加工のPython文字列テンプレートでは少しトリッキーです

Jinjaの例については、同様の質問に対する私の回答を参照してください。

文字列テンプレートを使用してxmlを生成する例を次に示します。

import string
from xml.sax.saxutils import escape

inner_template = string.Template('    <field${id} name="${name}">${value}</field${id}>')

outer_template = string.Template("""<root>
 <doc>
${document_list}
 </doc>
</root>
 """)

data = [
    (1, 'foo', 'The value for the foo document'),
    (2, 'bar', 'The <value> for the <bar> document'),
]

inner_contents = [inner_template.substitute(id=id, name=name, value=escape(value)) for (id, name, value) in data]
result = outer_template.substitute(document_list='\n'.join(inner_contents))
print result

出力:

<root>
 <doc>
    <field1 name="foo">The value for the foo document</field1>
    <field2 name="bar">The &lt;value&gt; for the &lt;bar&gt; document</field2>
 </doc>
</root>

テンプレートアプローチのダウナーは、あなたがのエスケープを取得することはありませんということです<し、>自由のために。私はから問題を回避するためにutilをxml.sax


1

私は、bigh_29のテンプレートのメソッドを使用してxmlジェネレーターの作成を終了しました。オブジェクトの数が多すぎて「邪魔になる」ことなく、出力内容を制御する優れた方法です。

タグと値については、2つの配列を使用しました。1つは出力xmlでのタグ名と位置を指定し、もう1つは同じタグのリストを持つパラメーターファイルを参照しました。ただし、パラメーターファイルには、対応する入力(csv)ファイル内のデータが取得される位置番号も含まれています。このように、入力ファイルから入ってくるデータの位置に変更があっても、プログラムは変更されません。パラメータファイルの適切なタグからデータフィールドの位置を動的に計算します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.