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

kra*_*yzk 4 python xml django soap suds

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

所以我有两个问题:

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

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

提前致谢.

kra*_*yzk 7

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

client = Client(settings.WSDL_ADDRESS, retxml=True)
raw_reply = client.service.PersonSearch(soapified_search_object)
Run Code Online (Sandbox Code Playgroud)

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

parsed_result = client.service.PersonSearch(__inject={'reply': raw_reply})
Run Code Online (Sandbox Code Playgroud)

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

希望这有助于其他人.


Gus*_*rra 5

我使用kyrayzk解决方案已有一段时间,但始终发现它有点骇人听闻,因为我只为需要处理原始XML时创建一个单独的虚拟客户端。所以我有点重新实现了,.last_received()并且.last_sent()方法(通过错误将它们(在(恕我直言,错误地)在suds-jurko 0.4.1中删除了))MessagePlugin

希望它能帮助某人:

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)
Run Code Online (Sandbox Code Playgroud)

用法:

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

print plugin.last_sent_raw
print plugin.last_received_raw
Run Code Online (Sandbox Code Playgroud)

另外,如果您想要缩进的XML,请尝试以下操作:

from lxml import etree
def xmlpprint(xml):
    return etree.tostring(etree.fromstring(xml), pretty_print=True)
Run Code Online (Sandbox Code Playgroud)