如何使用Python将字符串格式XML响应解析为pandas DataFrame
问题背景
- 对接TSETMC站点老旧SOAP服务,放弃耗时的响应对象化解析方案,已将响应内容存储为字符串类型
- 需求为从XML格式的响应字符串中仅提取
InsCode、DEven、PriceYesterday三个字段,构建指定结构的pandas DataFrame - 直接调用
xml.etree.ElementTree.fromstring()方法解析未得到预期结果
失败原因
TSETMC的SOAP响应默认带自定义命名空间,直接传入字符串解析后,不带命名空间前缀匹配标签会返回空结果,这是解析失败的核心原因。
可运行解决方案
两种实现方案均可满足需求,根据场景选择即可:
方案1:显式匹配命名空间(性能最优,适合结构固定的响应)
提前提取响应中的默认命名空间,匹配标签时带上命名空间前缀定位节点:
import xml.etree.ElementTree as ET import pandas as pd # 替换为实际存储的XML响应字符串 my_xml_string = """ <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <soap:Body> <GetTradeLastResponse xmlns="http://tsetmc.com/"> <GetTradeLastResult> <InsCode>35425587644337450</InsCode> <DEven>20240520</DEven> <PriceYesterday>12540</PriceYesterday> <!-- 其余无关字段已省略 --> </GetTradeLastResult> </GetTradeLastResponse> </soap:Body> </soap:Envelope> """ # 绑定TSETMC接口默认命名空间 ns = {"tsetmc": "http://tsetmc.com/"} root = ET.fromstring(my_xml_string) # 定位到字段所在的结果节点 result_node = root.find(".//tsetmc:GetTradeLastResult", ns) # 提取目标字段,数值类字段可提前做类型转换 parsed_data = [{ "InsCode": result_node.findtext("tsetmc:InsCode", namespaces=ns), "DEven": result_node.findtext("tsetmc:DEven", namespaces=ns), "PriceYesterday": float(result_node.findtext("tsetmc:PriceYesterday", namespaces=ns)) }] # 构建DataFrame df = pd.DataFrame(parsed_data)
方案2:忽略命名空间全局匹配(适配性强,无需核对命名空间地址)
如果接口返回的命名空间经常变动,可以直接递归遍历所有节点,忽略命名空间前缀按标签名匹配:
import xml.etree.ElementTree as ET import pandas as pd def get_field_value(root_node, target_tag): for elem in root_node.iter(): # 去掉标签里的命名空间前缀,只保留标签名本身 current_tag = elem.tag.split("}")[-1] if current_tag == target_tag: return elem.text return None # 替换为实际存储的XML响应字符串 my_xml_string = "你的XML响应字符串" root = ET.fromstring(my_xml_string) parsed_data = [{ "InsCode": get_field_value(root, "InsCode"), "DEven": get_field_value(root, "DEven"), "PriceYesterday": float(get_field_value(root, "PriceYesterday")) }] df = pd.DataFrame(parsed_data)
注意事项
- 如果接口返回的是多组交易记录,只需要遍历所有匹配到的结果节点,逐个提取字段后存入
parsed_data列表,再传入DataFrame即可,核心提取逻辑无需修改 PriceYesterday字段可根据业务需求保留字符串格式,示例中转为float是为了方便后续数值计算
预期输出格式
| InsCode | DEven | PriceYesterday |
|---|---|---|
| 35425587644337450 | 20240520 | 12540.0 |
内容的提问来源于stack exchange,提问作者Hadi Rahjoo
相关产品推荐
相关产品推荐

