我正在使用Python开发一个API,它使用XML进行服务器调用。我正在讨论是否使用库(例如http://wiki.python.org/moin/MiniDom)或者它是否“更好”(意味着更少开销和更快)使用字符串连接以生成用于每个请求的XML。此外,我将生成的XML将非常动态,因此我不确定是否允许我动态管理元素的内容将是一个好处。
答案 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库;例如MiniDom,ElementTree,lxml.etree或pyxser。没有理由不这样做,潜在的性能影响将是最小的。
虽然,我个人更喜欢使用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>