用Python生成XML

时间:2013-05-02 21:17:05

标签: python xml

我正在使用Python开发一个API,它使用XML进行服务器调用。我正在讨论是否使用库(例如http://wiki.python.org/moin/MiniDom)或者它是否“更好”(意味着更少开销和更快)使用字符串连接以生成用于每个请求的XML。此外,我将生成的XML将非常动态,因此我不确定是否允许我动态管理元素的内容将是一个好处。

5 个答案:

答案 0 :(得分:2)

由于您只是使用authorize.net,为什么不使用a library specifically designed for the Authorize.net API而忘记构建自己的XML调用?

如果您想要或需要按照自己的方式使用XML,请不要使用minidom,使用ElementTree接口,例如cElementTree(位于标准库中)。它会更加痛苦和probably much faster。您当然需要一个XML库来解析您生成的XML,因此您也可以使用相同的API。

使用XML库的开销不太可能成为一个问题,干净代码的好处和知道你无法生成无效的XML是非常好的。

如果你绝对需要尽可能快,请使用Python的extremely fast templating libraries之一。它们可能比你做的任何天真的字符串连接快得多,也是安全的(即适当的转义)。

答案 1 :(得分:1)

我肯定会建议您使用其中一个Python库;例如MiniDomElementTreelxml.etreepyxser。没有理由不这样做,潜在的性能影响将是最小的。

虽然,我个人更喜欢使用simplejson(或简称为json)。

my_list = ["Value1", "Value2"]
json = simplejson.dumps(my_list)
# send json

答案 2 :(得分:1)

我真正的问题是你想要完成什么是最大的担忧?如果你担心速度/记忆,那么是的,minidom确实受到了打击。如果你想要一些可以快速部署的东西,我会说使用它。

我建议使用任何语言(Java,Python,C#,Perl等)处理XML,考虑使用已有的东西。每个人都至少写过一次自己的XML解析器,然后他们再也不会这样做,因为它背后是如此痛苦。公平地说,这些库已经修复了99.5%的问题。

答案 3 :(得分:0)

我建议LXML。它是非常快的C库 libxml2 libxslt 的Python绑定库。

LXML支持XPATH,并且具有elementTree实现。 LXML还有一个名为objectify的接口,用于将XML编写为对象层次结构:

from lxml import etree, objectify
E = objectify.ElementMaker(annotate=False)

my_alpha = my_alpha = E.alpha(E.beta(E.gamma(firstattr='True')),
                              E.beta(E.delta('text here')))
etree.tostring(my_alpha)
# '<alpha><beta><gamma firstattr="True"/></beta><beta><delta>text here</delta></beta></alpha>'

etree.tostring(my_alpha.beta[0])
# '<beta><gamma firstattr="True"/></beta>'

my_alpha.beta[1].delta.text
# 'text here'

答案 4 :(得分:0)

另一种选择是使用Jinja,特别是如果xml的动态特性相当简单。这是用于生成html响应的常见习语。

以下是生成aws S3 list objects响应的XML的jinja模板示例。我通常将模板存储在一个单独的文件中,以避免用丑陋的xml污染我优雅的python。

from datetime import datetime
from jinja2 import Template

list_bucket_result = """<?xml version="1.0" encoding="UTF-8"?>
<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <Name>{{bucket_name}}</Name>
    <Prefix/>
    <KeyCount>{{object_count}}</KeyCount>
    <MaxKeys>{{max_keys}}</MaxKeys>
    <IsTruncated>{{is_truncated}}</IsTruncated>
    {%- for object in object_list %}
    <Contents>
        <Key>{{object.key}}</Key>
        <LastModified>{{object.last_modified_date.isoformat()}}</LastModified>
        <ETag></ETag>
        <Size>{{object.size}}</Size>
        <StorageClass>STANDARD</StorageClass>
    </Contents>{% endfor %}
</ListBucketResult>
"""

class BucketObject:
    def __init__(self, key, last_modified_date, size):
        self.key = key
        self.last_modified_date = last_modified_date
        self.size = size

object_list = [
    BucketObject('/foo/bar.txt', datetime.utcnow(), 10*1024 ),
    BucketObject('/foo/baz.txt', datetime.utcnow(), 29*1024 ),
]

template = Template(list_bucket_result)
result = template.render(
    bucket_name='test-bucket',
    object_count=len(object_list),
    max_keys=1000,
    is_truncated=False,
    object_list=object_list
)
print result

输出:

<?xml version="1.0" encoding="UTF-8"?>
<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <Name>test-bucket</Name>
    <Prefix/>
    <KeyCount>2</KeyCount>
    <MaxKeys>1000</MaxKeys>
    <IsTruncated>False</IsTruncated>
    <Contents>
        <Key>/foo/bar.txt</Key>
        <LastModified>2017-10-31T02:28:34.551000</LastModified>
        <ETag></ETag>
        <Size>10240</Size>
        <StorageClass>STANDARD</StorageClass>
    </Contents>
    <Contents>
        <Key>/foo/baz.txt</Key>
        <LastModified>2017-10-31T02:28:34.551000</LastModified>
        <ETag></ETag>
        <Size>29696</Size>
        <StorageClass>STANDARD</StorageClass>
    </Contents>
</ListBucketResult>