如果我想用python创建一个简单的XML文件,我有什么选择?(图书馆明智)

我想要的xml看起来像:

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

</root>

当前回答

对于这样一个简单的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>

模板方法的缺点是不能免费获得<和>的转义。我从xml.sax中引入了一个util,绕过了这个问题

其他回答

Yattag http://www.yattag.org/或https://github.com/leforestier/yattag提供了一个有趣的API来创建这样的XML文档(以及HTML文档)。

它使用上下文管理器和带关键字。

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>

lxml库包含一种非常方便的XML生成语法,称为E-factory。以下是我对你给出的例子的理解:

#!/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'))

对于最简单的选择,我会选择minidom: http://docs.python.org/library/xml.dom.minidom.html。它内置在python标准库中,在简单的情况下可以直接使用。

这里有一个非常简单的教程:http://www.boddie.org.uk/python/XML_intro.html

对于这样一个简单的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>

模板方法的缺点是不能免费获得<和>的转义。我从xml.sax中引入了一个util,绕过了这个问题

我刚刚写完一个xml生成器,使用bigh_29的方法的模板…这是一种很好的方式来控制你的输出没有太多的对象得到“在路上”。

As for the tag and value, I used two arrays, one which gave the tag name and position in the output xml and another which referenced a parameter file having the same list of tags. The parameter file, however, also has the position number in the corresponding input (csv) file where the data will be taken from. This way, if there's any changes to the position of the data coming in from the input file, the program doesn't change; it dynamically works out the data field position from the appropriate tag in the parameter file.