Glue Python脚本:SOAP API读取XML转Parquet存S3解析失败求助
解决Pandas read_xml解析SOAP XML返回NaN的问题
问题原因
SOAP返回的XML带有命名空间(如soap前缀),且目标数据嵌套在多层节点中,pd.read_xml()默认无法自动定位到深层的结果节点,导致解析后得到空值(NaN)。
解决方案一:利用已解析的xmltodict结果构造DataFrame(最简方案)
你已经通过xmltodict成功提取到了结果值,直接用这个值构造DataFrame即可,无需再用read_xml解析整个SOAP响应:
import requests import xmltodict import pandas as pd import pyarrow url = "https://www.w3schools.com/xml/tempconvert.asmx" payload = """<?xml version="1.0" encoding="utf-8"?> <soap12:Envelope xmlns:xsi="http://w3.org/2002/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/soap/envelope/"> <soap12:Body> <CelsiusToFahrenheit xmlns="https://www.w3schools.com/xml/"> <Celsius>20</Celsius> </CelsiusToFahrenheit> </soap12:Body> </soap12:Envelope>""" headers = { 'Content-Type': 'text/xml; charset=utf-8' } response = requests.request("POST", url, headers=headers, data=payload) # 用xmltodict提取结果 result_dict = xmltodict.parse(response.text)['soap:Envelope']['soap:Body']['CelsiusToFahrenheitResponse'] # 构造DataFrame df = pd.DataFrame([result_dict]) s3_url = 's3://bucket/folder/bucket.parquet' df.to_parquet(s3_url) # 验证输出 print(df)
这个方案直接复用你已有的xmltodict解析逻辑,避免了read_xml的命名空间和节点定位问题,输出的DataFrame会包含CelsiusToFahrenheitResult列和对应的值。
解决方案二:配置read_xml的命名空间与XPath(如果坚持用read_xml)
如果必须使用pd.read_xml(),需要指定SOAP的命名空间,并通过XPath定位到目标节点:
import requests import pandas as pd import pyarrow url = "https://www.w3schools.com/xml/tempconvert.asmx" payload = """<?xml version="1.0" encoding="utf-8"?> <soap12:Envelope xmlns:xsi="http://w3.org/2002/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/soap/envelope/"> <soap12:Body> <CelsiusToFahrenheit xmlns="https://www.w3schools.com/xml/"> <Celsius>20</Celsius> </CelsiusToFahrenheit> </soap12:Body> </soap12:Envelope>""" headers = { 'Content-Type': 'text/xml; charset=utf-8' } response = requests.request("POST", url, headers=headers, data=payload) # 定义命名空间:soap对应SOAP信封的命名空间,ws对应W3Schools的服务命名空间 namespaces = { "soap": "http://schemas.xmlsoap.org/soap/envelope/", "ws": "https://www.w3schools.com/xml/" } # 使用XPath定位到结果节点 df = pd.read_xml( response.text, xpath="//soap:Envelope/soap:Body/ws:CelsiusToFahrenheitResponse", namespaces=namespaces ) s3_url = 's3://bucket/folder/bucket.parquet' df.to_parquet(s3_url) # 验证输出 print(df)
关键说明:
namespaces参数必须匹配XML中的命名空间前缀和URI,这里soap对应SOAP信封的命名空间,ws对应W3Schools服务的自定义命名空间。xpath路径精准定位到包含结果的CelsiusToFahrenheitResponse节点,确保read_xml能正确提取数据。
内容的提问来源于stack exchange,提问作者marie20
相关产品推荐
相关产品推荐

