python-3.x - XML 元素树 - 使用 ET.SubElement() 附加到现有元素和属性?
问题描述
我有以下功能,它建立了一个可重用的 XML SOAP 信封:
def get_xml_soap_envelope():
"""
Returns a generically re-usable SOAP envelope in the following format:
<soapenv:Envelope>
<soapenv:Header/>
<soapenv:Body />
</soapenv:Envelope>
"""
soapenvEnvelope = ET.Element('soapenv:Envelope')
soapenvHeader = ET.SubElement(soapenvEnvelope, 'soapenv:Header')
soapenvBody = ET.SubElement(soapenvEnvelope, 'soapenv:Body')
return soapenvEnvelope
到目前为止相当简单的东西。
我现在想知道,是否可以将属性(例如xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
)附加到soapenv:Envelope
元素?
如果我还想附加以下 XML:
<urn:{AAction} soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<AUserName>{AUserName}</AUserName>
<APassword>{APassword}</APassword>
</urn:{AAction}>
soapenv:Body
这样我就会有这样的事情:
if __name__ == "__main__":
soapenvEnvelope = get_xml_soap_envelope()
actions = {
'AAction': 'UserLogin',
}
soapAAction = ET.Element('urn:{AAction}'.format(**actions))
soapenvEnvelope.AppendElement(soapAAction, 'soapenv:Body')
那么,我可以指定一个目标节点和要附加到的元素吗?
解决方案
让我们从坏消息开始:您创建 SOAP 信封 ( get_xml_soap_envelope ) 的函数是错误的,因为它没有指定至少 xmlns:soapenv="..."。实际上,所有其他要使用的命名空间也应在此处指定。
创建 SOAP 信封的正确函数应该是这样的:
def get_xml_soap_env():
"""
Returns a generically re-usable SOAP envelope in the following format:
<soapenv:Envelope xmlns:soapenv="...", ...>
<soapenv:Header/>
<soapenv:Body />
</soapenv:Envelope>
"""
ns = {'xmlns:soapenv': 'http://schemas.xmlsoap.org/soap/envelope/',
'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
'xmlns:urn': 'http://dummy.urn'}
env = ET.Element('soapenv:Envelope', ns)
ET.SubElement(env, 'soapenv:Header')
ET.SubElement(env, 'soapenv:Body')
return env
注意ns字典还包含其他命名空间,稍后会用到,ao xsi命名空间。
一种可能的替代方法是在此函数之外定义ns并将其作为参数传递(您的选择)。
当我跑的时候:
env = get_xml_soap_env()
print(ET.tostring(env, encoding='unicode', short_empty_elements=True))
打印输出(由我重新格式化以提高可读性)是:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:urn="http://dummy.urn"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header />
<soapenv:Body />
</soapenv:Envelope>
请注意,这次包括了正确的命名空间。
然后,要添加Action元素及其子元素,请定义以下函数:
def addAction(env, action, subelems):
body = env.find('soapenv:Body')
actn = ET.SubElement(body, f'soapenv:{action}')
for k, v in subelems.items():
child = ET.SubElement(actn, k)
child.text = v
当我跑的时候:
subelems = {'AUserName': 'Mark', 'APassword': 'Secret!'}
addAction(env, 'UserLogin', subelems)
并再次打印整个 XML 树,结果是:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:urn="http://dummy.urn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header />
<soapenv:Body>
<soapenv:UserLogin>
<AUserName>Mark</AUserName>
<APassword>Secret!</APassword>
</soapenv:UserLogin>
</soapenv:Body>
</soapenv:Envelope>
推荐阅读
- android - 无法更新 Android 中的任何支持库
- python - 在python中读取json文件
- javascript - JSSOR 滑块 - 如何更改这些属性?
- c++ - C++ 如何说服 constexpr 函数是 constexpr,对于任何类型的参数
- components - angular6 - 将数据从一个组件发送到另一个组件
- django - Bokeh 0.13 使用 django 从组件迁移到 curdoc
- jquery - 代码在加载或保存时添加额外的换行符
- netlink - rtnetlink:如何实现“flush ip addr”
- php - docker-compose up -d 不会启动 php-fpm
- android - Android App Bundle 平台特定模块