You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Spyne的AnyDict返回结果中添加xsi:type="xsd:string"?

问题:为Spyne SOAP服务的AnyDict返回字段添加xsi:type属性

问题背景

我使用Spyne框架开发SOAP服务,需要为返回结果中AnyDict类型的字段添加xsi:type="xsd:string"属性。当前SOAP响应里的<state>和<err_msg>标签缺少该属性,期望为其补全。

当前SOAP响应

<soap11env:Envelope xmlns:soap11env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tns="http://localhost/nusoap">
   <soap11env:Body>
      <tns:ERespons>
         <tns:EResponsRecord>
            <state>failed</state>
            <err_msg>Nastala chyba</err_msg>
         </tns:EResponsRecord>
      </tns:ERespons>
   </soap11env:Body>
</soap11env:Envelope>

期望SOAP响应

<soap11env:Envelope xmlns:soap11env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tns="http://localhost/nusoap">
   <soap11env:Body>
      <tns:ERespons>
         <tns:EResponsRecord>
            <state xsi:type="xsd:string">failed</state>
            <err_msg xsi:type="xsd:string">Nastala chyba</err_msg>
         </tns:EResponsRecord>
      </tns:ERespons>
   </soap11env:Body>
</soap11env:Envelope>

现有服务代码

class AddEntryEC(ServiceBase):
        EntryObject.__namespace__ = 'Entry.soap'
        __out_header__ = EntryObject

        @rpc(
                AnyDict,
                _out_message_name = 'ERespons',
                _out_variable_name = 'EResponsRecord',
                _returns=AnyDict
        )

        def AddEntry(ctx, data):

                data = get_object_as_dict(data)
                try :
                        ctx.app.db_tool.set_args(data)
                        res = ctx.app.db_tool.insert_data()
                        
                        return res

                except Exception as e:
                        logging.exception(e) 
                        return  {'state' : 'failed',
                                'err_msg' : 'Nastala chyba'}

应用声明代码

application = MyApplication([AddEntryEC], 'http://localhost/nusoap', in_protocol=Soap11(validator='soft'), out_protocol=Soap11())

解决方案

方案1:用ComplexModel替代AnyDict(推荐)

AnyDict属于动态类型,Spyne不会为其字段自动生成明确的类型属性。最规范的做法是定义一个ComplexModel来明确字段类型,框架会自动处理xsi:type属性:

from spyne import ComplexModel, Unicode

# 定义返回结果的模型
class EResponsRecord(ComplexModel):
    __namespace__ = 'http://localhost/nusoap'  # 与服务命名空间保持一致
    state = Unicode
    err_msg = Unicode

# 修改服务代码
class AddEntryEC(ServiceBase):
        EntryObject.__namespace__ = 'Entry.soap'
        __out_header__ = EntryObject

        @rpc(
                AnyDict,
                _out_message_name = 'ERespons',
                _out_variable_name = 'EResponsRecord',
                _returns=EResponsRecord  # 替换为自定义模型
        )
        def AddEntry(ctx, data):
                data = get_object_as_dict(data)
                try :
                        ctx.app.db_tool.set_args(data)
                        res = ctx.app.db_tool.insert_data()
                        # 将字典转换为模型实例返回
                        return EResponsRecord(**res)
                except Exception as e:
                        logging.exception(e) 
                        # 返回模型实例而非字典
                        return EResponsRecord(state='failed', err_msg='Nastala chyba')

方案2:自定义SOAP序列化器(应急方案)

如果无法替换AnyDict,可以自定义序列化器,强制为指定字段添加xsi:type属性:

from spyne.protocol.soap import Soap11
from lxml import etree

class CustomSoap11(Soap11):
    def serialize(self, ctx):
        super().serialize(ctx)
        # 定义命名空间
        xsi_ns = "http://www.w3.org/2001/XMLSchema-instance"
        xsd_ns = "http://www.w3.org/2001/XMLSchema"
        # 为信封添加xsd命名空间声明
        ctx.out_document.attrib["xmlns:xsd"] = xsd_ns
        
        # 遍历目标标签添加属性
        for elem in ctx.out_document.xpath('//state | //err_msg'):
            elem.set(f"{{{xsi_ns}}}type", "xsd:string")

# 修改应用声明,使用自定义协议
application = MyApplication(
    [AddEntryEC], 
    'http://localhost/nusoap', 
    in_protocol=Soap11(validator='soft'), 
    out_protocol=CustomSoap11()
)

说明

  • 方案1符合SOAP规范,通过明确的模型定义让框架自动处理类型逻辑,后续维护更简单。
  • 方案2属于临时 workaround,适合无法修改返回类型的场景,需要注意XPath匹配的准确性,避免影响其他字段。

内容的提问来源于stack exchange,提问作者Vova

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 11:35:23