Python提取XML标签间值时生成空DataFrame的问题排查
解决XML提取值后生成空DataFrame的问题
首先,你的代码生成空DataFrame最可能的原因是XML命名空间未正确处理——这类金融监管类XML(比如DLTINS格式)几乎都带有默认命名空间,直接用标签名查找元素会找不到匹配项,自然不会有数据添加到rows列表里。下面是具体的排查和修复步骤:
1. 检查并处理XML命名空间
打开你的DLTINS_20210117_01of01.xml文件,开头应该会有类似这样的命名空间声明:
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:dlt.001.001.02">
这意味着所有元素都属于这个命名空间,直接用findall("FinInstrmRptgRefDataDltaRpt")是找不到任何元素的,必须在查找时指定命名空间。
修改代码如下,先提取命名空间,再带命名空间前缀查找:
import xml.etree.ElementTree as ET import pandas as pd rows = [] cols = ["Id", "FullNm", "ClssfctnTp", "CmmdtyDerivInd", "NtnlCcy", "Issr"] # 解析XML并提取命名空间 tree = ET.parse("DLTINS_20210117_01of01.xml") root = tree.getroot() # 提取默认命名空间(如果有的话) ns = {} if '}' in root.tag: ns['ns'] = root.tag.split('}')[0].strip('{') # 带命名空间查找元素(用.//递归查找任意层级的目标元素) for i in root.findall(".//ns:FinInstrmRptgRefDataDltaRpt", ns): # 查找FinInstrmGnlAttrbts子元素 j = i.find(".//ns:FinInstrmGnlAttrbts", ns) if j is not None: # 安全获取标签文本(避免找不到元素时报错) Id = j.find("ns:Id", ns).text if j.find("ns:Id", ns) is not None else None FullNm = j.find("ns:FullNm", ns).text if j.find("ns:FullNm", ns) is not None else None ClssfctnTp = j.find("ns:ClssfctnTp", ns).text if j.find("ns:ClssfctnTp", ns) is not None else None CmmdtyDerivInd = j.find("ns:CmmdtyDerivInd", ns).text if j.find("ns:CmmdtyDerivInd", ns) is not None else None NtnlCcy = j.find("ns:NtnlCcy", ns).text if j.find("ns:NtnlCcy", ns) is not None else None Issr = i.find("ns:Issr", ns).text if i.find("ns:Issr", ns) is not None else None rows.append({ "Id": Id, "FullNm": FullNm, "ClssfctnTp": ClssfctnTp, "CmmdtyDerivInd": CmmdtyDerivInd, "NtnlCcy": NtnlCcy, "Issr": Issr }) df = pd.DataFrame(rows, columns=cols) print(df)
2. 其他可能的排查点
- 元素路径是否正确:如果修改命名空间后还是空DataFrame,打印
root.tag看看根元素是什么,确认FinInstrmRptgRefDataDltaRpt是否直接在根元素下,还是嵌套在其他容器(比如<Document>)里。代码中用.//前缀可以递归查找任意层级的元素,避免路径错误。 - BeautifulSoup的正确用法:如果你想用BeautifulSoup,同样需要处理命名空间,示例代码如下:
from bs4 import BeautifulSoup import pandas as pd rows = [] cols = ["Id", "FullNm", "ClssfctnTp", "CmmdtyDerivInd", "NtnlCcy", "Issr"] with open("DLTINS_20210117_01of01.xml", "r") as f: soup = BeautifulSoup(f, "xml") # 获取文档的默认命名空间 ns = soup.find().namespace # 查找所有目标元素 for i in soup.find_all("FinInstrmRptgRefDataDltaRpt", {"xmlns": ns}): j = i.find("FinInstrmGnlAttrbts") if j: Id = j.Id.text if j.Id else None FullNm = j.FullNm.text if j.FullNm else None ClssfctnTp = j.ClssfctnTp.text if j.ClssfctnTp else None CmmdtyDerivInd = j.CmmdtyDerivInd.text if j.CmmdtyDerivInd else None NtnlCcy = j.NtnlCcy.text if j.NtnlCcy else None Issr = i.Issr.text if i.Issr else None rows.append({ "Id": Id, "FullNm": FullNm, "ClssfctnTp": ClssfctnTp, "CmmdtyDerivInd": CmmdtyDerivInd, "NtnlCcy": NtnlCcy, "Issr": Issr }) df = pd.DataFrame(rows, columns=cols) print(df)
3. 快速验证元素是否存在
可以先执行以下代码,确认是否能找到目标元素:
print(len(root.findall(".//ns:FinInstrmRptgRefDataDltaRpt", ns)))
如果结果是0,说明要么命名空间提取错误,要么元素路径和XML实际结构不匹配,需要进一步查看XML的层级结构。
内容的提问来源于stack exchange,提问作者TotalDark
相关产品推荐
相关产品推荐

