如何从suds响应中获取未解析的XML,以及用于存储的最佳django模型字段

时间:2014-10-08 21:33:57

标签: python xml django soap suds

我正在使用suds来使用wsdl从第三方请求数据。我现在只保存一些返回的数据,但是我正在为我得到的数据付费,所以我想保留所有数据。我已经决定保存这些数据的最佳方法是将原始xml响应捕获到数据库字段中,以备将来使用,如果我决定要开始使用数据的不同部分,并在发生差异时作为文件跟踪。

所以我有两个问题:

是否有一种简单的方法可以从suds.client对象输出原始接收的xml?在我搜索到这个问题的答案时,我已经了解到这可以通过日志记录来完成,但我希望不必将日志中的信息反馈到数据库字段中。我也查看了MessagePlugin.recieved()钩子,但是在解析之后无法弄清楚如何访问这些信息,只是我可以覆盖该函数并且在解析时可以访问原始xml(这是在我决定它是否真的值得保存之前。我还研究了retxml选项,但我也想使用解析版本并进行两次单独调用,一次作为retxml,另一次解析将花费我两次。我希望在suds客户端中内置一个简单的函数(比如response.as_xml()或同样简单的东西),但还没有找到类似的东西。我头脑中冒泡的选项可能是使用.received()插件钩子扩展客户端对象,该钩子在解析之前将xml保存为对象参数,稍后将被引用...但执行此类似乎有点我现在很难接受,而且我很难相信肥皂水的客户不仅仅是已经把它建在某个地方,所以我想我先问一下。

我的问题的另一部分是:什么类型的django模型字段最适合处理最多约100 kb的文本数据作为原始xml?我打算简单地使用一个简单的CharField和一个愚蠢的max_length,但这感觉不对。

提前致谢。

2 个答案:

答案 0 :(得分:7)

我通过在客户端初始化时使用标志retxml解决了这个问题:

client = Client(settings.WSDL_ADDRESS, retxml=True)
raw_reply = client.service.PersonSearch(soapified_search_object)

然后我能够将raw_reply作为原始xml保存到django models.TextField()中 然后注入原始xml以获得suds解析结果,而不必重新提交我的搜索lika所以:

parsed_result = client.service.PersonSearch(__inject={'reply': raw_reply})

我想如果我想从原始回复中删除suds信封的东西我可以使用python xml库来进一步使用回复,但是因为我现有的代码已经从suds客户端获取了我想要的信息结果我刚刚用过它。

希望这有助于其他人。

答案 1 :(得分:4)

我已经使用了kyrayzk解决方案一段时间了,但总是发现它有点hackish,因为我必须创建一个单独的虚拟客户端,只是为了我需要处理原始XML时。 所以我通过.last_received()重新实现了.last_sent()MessagePlugin方法(在冥想(错误地)中删除了suds-jurko 0.4.1)。

希望它可以帮到某人:

class MyPlugin(MessagePlugin):
    def __init__(self):
        self.last_sent_raw = None
        self.last_received_raw = None

    def sending(self, context):
        self.last_sent_raw = str(context.envelope)

    def received(self, context):
        self.last_received_raw = str(context.reply)

用法:

plugin = MyPlugin()
client = Client(TRTH_WSDL_URL, plugins=[plugin])
client.service.SendSomeRequest()

print plugin.last_sent_raw
print plugin.last_received_raw

另外,如果你想要一个很好的缩进XML,试试这个:

from lxml import etree
def xmlpprint(xml):
    return etree.tostring(etree.fromstring(xml), pretty_print=True)