2010-10-02 112 views
59

我正在創建一個web api,並且需要一個很好的方法來快速生成一些格式良好的xml。我找不到在Python中做這件事的好方法。生成XML的最佳方法?

注意:某些庫看起來很有前途,但缺少文檔或僅輸出到文件。

回答

77

使用lxml

from lxml import etree 

# create XML 
root = etree.Element('root') 
root.append(etree.Element('child')) 
# another child with text 
child = etree.Element('child') 
child.text = 'some text' 
root.append(child) 

# pretty string 
s = etree.tostring(root, pretty_print=True) 
print s 

輸出:

<root> 
    <child/> 
    <child>some text</child> 
</root> 

更多信息,請參見tutorial

75

ElementTree是一個很好的模塊,可以讀取xml並寫入太多內容。

from xml.etree.ElementTree import Element, SubElement, tostring 

root = Element('root') 
child = SubElement(root, "child") 
child.text = "I am a child" 

print tostring(root) 

輸出:

<root><child>I am a child</child></root> 

更多細節,以及如何漂亮打印看到這個tutorial

或者,如果你的XML是簡單的,不要小看串的功率格式:)

xmlTemplate = """<root> 
    <person> 
     <name>%(name)s</name> 
     <address>%(address)s</address> 
    </person> 
</root>""" 

data = {'name':'anurag', 'address':'Pune, india'} 
print xmlTemplate%data 

輸出:

<root> 
    <person> 
     <name>anurag</name> 
     <address>Pune, india</address> 
    </person> 
</root> 

您可以使用string.Template或一些模板引擎也爲複雜的格式。

+5

小心第二種方法,因爲它不引用特殊字符,因此,如果您的數據中包含的字符,如'<>&'你可以用畸形XML結束。 – zch 2015-07-23 11:41:52

12

使用lxml.builder類,從:http://lxml.de/tutorial.html#the-e-factory

import lxml.builder as lb 
from lxml import etree 

nstext = "new story" 
story = lb.E.Asset(
    lb.E.Attribute(nstext, name="Name", act="set"), 
    lb.E.Relation(lb.E.Asset(idref="Scope:767"), 
      name="Scope", act="set") 
) 

print 'story:\n', etree.tostring(story, pretty_print=True) 

輸出:

story: 
<Asset> 
    <Attribute name="Name" act="set">new story</Attribute> 
    <Relation name="Scope" act="set"> 
    <Asset idref="Scope:767"/> 
    </Relation> 
</Asset> 
11

我會使用yattag庫。我認爲這是最Python的方式:

from yattag import Doc 

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

with tag('food'): 
    with tag('name'): 
     text('French Breakfast') 
    with tag('price', currency='USD'): 
     text('6.95') 
    with tag('ingredients'): 
     for ingredient in ('baguettes', 'jam', 'butter', 'croissants'): 
      with tag('ingredient'): 
       text(ingredient) 


print(doc.getvalue()) 
+1

我不確定,如果我認爲它實際上很美很難看。我已經使用'with'語句打開了文件,我認爲這有助於「清理」或「關閉」我在'with'語句後直接寫入的任何內容。因此,在這種情況下,它會關閉標籤?或者當它打開文件時,它會像文件句柄一樣扔掉它們?如果它把它扔掉了,爲什麼它仍然在最終的輸出中?必須是因爲那個'text()'函數。但是,這是不是繞過了「附帶」聲明的性質? – Zelphir 2015-07-27 23:13:24

9

,如果你想使用純Python的可選方式:

ElementTree是適合大多數情況下,但它不能CData的漂亮打印

所以,如果你需要CData的漂亮的打印你應該使用minidom

minidom_example.py:

from xml.dom import minidom 

doc = minidom.Document() 

root = doc.createElement('root') 
doc.appendChild(root) 

leaf = doc.createElement('leaf') 
text = doc.createTextNode('Text element with attributes') 
leaf.appendChild(text) 
leaf.setAttribute('color', 'white') 
root.appendChild(leaf) 

leaf_cdata = doc.createElement('leaf_cdata') 
cdata = doc.createCDATASection('<em>CData</em> can contain <strong>HTML tags</strong> without encoding') 
leaf_cdata.appendChild(cdata) 
root.appendChild(leaf_cdata) 

branch = doc.createElement('branch') 
branch.appendChild(leaf.cloneNode(True)) 
root.appendChild(branch) 

mixed = doc.createElement('mixed') 
mixed_leaf = leaf.cloneNode(True) 
mixed_leaf.setAttribute('color', 'black') 
mixed_leaf.setAttribute('state', 'modified') 
mixed.appendChild(mixed_leaf) 
mixed_text = doc.createTextNode('Do not use mixed elements if it possible.') 
mixed.appendChild(mixed_text) 
root.appendChild(mixed) 

xml_str = doc.toprettyxml(indent=" ") 
with open("minidom_example.xml", "w") as f: 
    f.write(xml_str) 

minidom_example。XML:

<?xml version="1.0" ?> 
<root> 
    <leaf color="white">Text element with attributes</leaf> 
    <leaf_cdata> 
<![CDATA[<em>CData</em> can contain <strong>HTML tags</strong> without encoding]]> </leaf_cdata> 
    <branch> 
    <leaf color="white">Text element with attributes</leaf> 
    </branch> 
    <mixed> 
    <leaf color="black" state="modified">Text element with attributes</leaf> 
    Do not use mixed elements if it possible. 
    </mixed> 
</root> 
0

我已經嘗試了一些解決方案,在此線程,不幸的是,我發現他們中的一些繁瑣和不雅(即做一些不平凡的時候需要過多的精力)。因此,我認爲我會把我的首選解決方案web2py HTML helper objects納入混合。

首先,安裝了standalone web2py module

pip install web2py 

不幸的是,上面安裝的web2py的一個非常陳舊的版本,但它會是不夠好這個例子。更新的來源是here

導入web2py記錄的HTML幫助對象here

from gluon.html import * 

現在,您可以使用web2py助手來生成XML/HTML。

words = ['this', 'is', 'my', 'item', 'list'] 
# helper function 
create_item = lambda idx, word: LI(word, _id = 'item_%s' % idx, _class = 'item') 
# create the HTML 
items = [create_item(idx, word) for idx,word in enumerate(words)] 
ul = UL(items, _id = 'my_item_list', _class = 'item_list') 
my_div = DIV(ul, _class = 'container') 

>>> my_div 

<gluon.html.DIV object at 0x00000000039DEAC8> 

>>> my_div.xml() 
# I added the line breaks for clarity 
<div class="container"> 
    <ul class="item_list" id="my_item_list"> 
     <li class="item" id="item_0">this</li> 
     <li class="item" id="item_1">is</li> 
     <li class="item" id="item_2">my</li> 
     <li class="item" id="item_3">item</li> 
     <li class="item" id="item_4">list</li> 
    </ul> 
</div>