问题:使用python创建一个简单的XML文件
如果我想在python中创建一个简单的XML文件,我有哪些选择?(明智的)
我想要的xml看起来像:
<root>
<doc>
<field1 name="blah">some value1</field1>
<field2 name="asdfasd">some vlaue2</field2>
</doc>
</root>
回答 0
如今,最受欢迎的(也是非常简单的)选项是ElementTree API,该元素自Python 2.5起已包含在标准库中。
可用的选项是:
- ElementTree(ElementTree的基本,纯Python实现。自2.5以来是标准库的一部分)
- cElementTree(ElementTree的优化C实现。从2.5开始在标准库中提供)
- LXML(基于libxml2。提供ElementTree API的丰富超集以及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")
我已经对其进行了测试,并且可以正常工作,但是我假设空格并不重要。如果您需要“ prettyprint”缩进,请告诉我,我将查找如何做。(这可能是特定于LXML的选项。我不太使用stdlib实现)
为了进一步阅读,这里有一些有用的链接:
- 适用于Python标准库的API文档
- 入门教程(来自原始作者的网站)
- LXML etree教程。(带有示例代码,用于从所有主要ElementTree实现中加载最佳可用选项)
最后一点,cElementTree或LXML都应该足够快以满足您的所有需求(都是经过优化的C代码),但是如果您处在需要挤出最后每一个性能的情况下,则基准LXML网站指示:
- LXML显然在序列化(生成)XML方面胜出
- 作为实现正确的父遍历的副作用,LXML的解析比cElementTree慢一些。
回答 1
该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'))
回答 2
Yattag http://www.yattag.org/或https://github.com/leforestier/yattag提供了一个有趣的API,用于创建此类XML文档(以及HTML文档)。
它使用上下文管理器和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>
回答 3
对于最简单的选择,我会选择minidom:http ://docs.python.org/library/xml.dom.minidom.html 。它内置在python标准库中,在简单情况下易于使用。
这是一个非常容易遵循的教程:http : //www.boddie.org.uk/python/XML_intro.html
回答 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 <value> for the <bar> document</field2>
</doc>
</root>
模板方法的令人沮丧的是,你不会得到的逃避<
和>
自由。我通过从中引入一个工具来解决这个问题xml.sax
回答 5
我刚刚使用bigh_29的Templates方法编写了一个xml生成器,这是一种控制输出内容的好方法,而没有太多对象“阻碍”。
至于标签和值,我使用了两个数组,一个数组给出了标签名称和在输出xml中的位置,另一个数组引用了具有相同标签列表的参数文件。但是,参数文件在相应的输入(csv)文件中也有位置编号,将从中获取数据。这样,如果来自输入文件的数据位置发生任何变化,则程序不会改变;它可以从参数文件中的相应标签动态计算出数据字段的位置。