如何用Python递归提取SOAP API响应中的指定属性?
从SOAP返回的XML中提取指定属性的最优实现
模拟你的XML响应示例
<response> <queryObject path="/type=NE/ISUKABAITHANDA_279251"> <property name="mainAgentId" value="AGT_12345"/> <property name="otherProp" value="xxx"/> </queryObject> <queryObject path="/type=NE/OTHER_NE"> <property name="mainAgentId" value="AGT_67890"/> </queryObject> <queryObject path="/type=ONT/R1.S1.LT1.PON1.ONT1"> <property name="Bandwidth" value="1000Mbps"/> <property name="status" value="active"/> </queryObject> <queryObject path="/type=ONT/OTHER_ONT"> <property name="Bandwidth" value="500Mbps"/> </queryObject> </response>
方案一:用Python内置xml.etree.ElementTree(无需额外安装)
新手首选,不用折腾第三方库,足够应对你的需求:
import xml.etree.ElementTree as ET # 替换成你从SOAP API获取的XML字符串 soap_xml = """ <response> <queryObject path="/type=NE/ISUKABAITHANDA_279251"> <property name="mainAgentId" value="AGT_12345"/> <property name="otherProp" value="xxx"/> </queryObject> <queryObject path="/type=NE/OTHER_NE"> <property name="mainAgentId" value="AGT_67890"/> </queryObject> <queryObject path="/type=ONT/R1.S1.LT1.PON1.ONT1"> <property name="Bandwidth" value="1000Mbps"/> <property name="status" value="active"/> </queryObject> <queryObject path="/type=ONT/OTHER_ONT"> <property name="Bandwidth" value="500Mbps"/> </queryObject> </response> """ # 解析XML root = ET.fromstring(soap_xml) # 定义要提取的目标:键是queryObject的path,值是要取的属性名 extraction_targets = { "/type=NE/ISUKABAITHANDA_279251": "mainAgentId", "/type=ONT/R1.S1.LT1.PON1.ONT1": "Bandwidth" } extracted_data = {} # 遍历所有queryObject,匹配目标路径 for query_obj in root.findall(".//queryObject"): current_path = query_obj.get("path") if current_path in extraction_targets: # 查找对应属性的property节点 target_prop = query_obj.find(f".//property[@name='{extraction_targets[current_path]}']") if target_prop is not None: extracted_data[current_path] = target_prop.get("value") print(extracted_data) # 输出结果: # {'/type=NE/ISUKABAITHANDA_279251': 'AGT_12345', '/type=ONT/R1.S1.LT1.PON1.ONT1': '1000Mbps'}
方案二:用lxml(更强大的XPath支持)
如果你的XML结构复杂或者有命名空间,lxml的XPath语法更灵活,先安装:
pip install lxml
代码实现:
from lxml import etree soap_xml = """ <response> <queryObject path="/type=NE/ISUKABAITHANDA_279251"> <property name="mainAgentId" value="AGT_12345"/> <property name="otherProp" value="xxx"/> </queryObject> <queryObject path="/type=NE/OTHER_NE"> <property name="mainAgentId" value="AGT_67890"/> </queryObject> <queryObject path="/type=ONT/R1.S1.LT1.PON1.ONT1"> <property name="Bandwidth" value="1000Mbps"/> <property name="status" value="active"/> </queryObject> <queryObject path="/type=ONT/OTHER_ONT"> <property name="Bandwidth" value="500Mbps"/> </queryObject> </response> """ root = etree.fromstring(soap_xml.encode()) extraction_targets = { "/type=NE/ISUKABAITHANDA_279251": "mainAgentId", "/type=ONT/R1.S1.LT1.PON1.ONT1": "Bandwidth" } extracted_data = {} # 直接用XPath精准定位 for target_path, prop_name in extraction_targets.items(): xpath_expr = f".//queryObject[@path='{target_path}']/property[@name='{prop_name}']/@value" # XPath返回列表,取第一个元素(确保唯一匹配) value = root.xpath(xpath_expr) if value: extracted_data[target_path] = value[0] print(extracted_data) # 输出结果同上
关键注意事项
- 命名空间处理:如果你的SOAP XML带命名空间(比如
<soapenv:Envelope>),需要先注册命名空间再使用XPath。比如在xml.etree.ElementTree里用ET.register_namespace('soapenv', 'http://schemas.xmlsoap.org/soap/envelope/'),然后XPath里加上命名空间前缀。 - 异常处理:可以给代码加判断,避免目标路径或属性不存在时报错,比如检查
query_obj或target_prop是否为None,返回默认值或提示信息。 - 扩展性:把提取目标存在字典里,后续要加新的提取规则直接修改字典即可,不用改核心逻辑。
内容的提问来源于stack exchange,提问作者stacktesting
相关产品推荐
相关产品推荐

