0

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

4

5 回答 5

2

既然您只是在使用 authorize.net,为什么不使用专门为 Authorize.net API 设计的库而忘记构建自己的 XML 调用呢?

如果您想要或需要使用自己的方式使用 XML,请不要使用 minidom,而是使用带有ElementTree接口的东西,例如cElementTree(在标准库中)。它会少很多痛苦,可能会快得多。您肯定需要一个 XML 库来解析您生成的 XML,因此您不妨为两者使用相同的 API。

使用 XML 库的开销不太可能成为问题,而且干净代码和知道您不能生成无效 XML 的好处非常大。

如果您绝对肯定需要尽可能快,请使用可用于 Python的极快模板库之一。它们可能比你做的任何简单的字符串连接都要快得多,而且也是安全的(即进行适当的转义)。

于 2013-05-02T21:30:49.680 回答
2

另一种选择是使用Jinja,尤其是当您的 xml 的动态特性相当简单时。这是烧瓶中用于生成 html 响应的常见习语。

以下是生成 aws S3列表对象响应的 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>
于 2017-10-31T02:32:05.093 回答
1

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

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

my_list = ["Value1", "Value2"]
json = simplejson.dumps(my_list)
# send json
于 2013-05-02T21:19:09.377 回答
1

我真正的问题是你想要完成的最大问题是什么?如果您担心速度/内存,那么是的,minidom 确实会受到打击。如果您想要可以快速部署的相当可靠的东西,我会说使用它。

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

于 2013-05-02T21:21:31.417 回答
0

我推荐LXML。它是一个 Python 绑定库,用于非常快速的 C 库libxml2libxslt

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'
于 2013-05-02T21:46:50.530 回答