You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将SCADA生成的嵌套节点XML解析为指定格式的Pandas DataFrame?

解决Pandas读取SCADA XML扁平文件无法展开POSITION子节点的问题

Pandas自带的read_xml无法自动展开POSITION_X节点下的子字段,导致这些列显示为NaN。可以通过lxml手动解析XML结构,提取所有需要的字段并构造目标格式的DataFrame,具体步骤如下:

步骤1:安装依赖库

如果还没安装lxml和pandas,执行以下命令:

pip install lxml pandas

步骤2:解析XML并提取数据

以下代码可直接处理你的SCADA XML文件(包括格式不规范的情况,比如未闭合的<STATUS>标签):

from lxml import etree
import pandas as pd

# 解析XML文件,recover=True忽略格式错误(比如未闭合标签)
tree = etree.parse("scada_data.xml", parser=etree.XMLParser(recover=True))
rows = tree.xpath("//row")

data_records = []
for row in rows:
    record = {}
    # 提取顶层DATE和MS字段
    record["DATE"] = row.findtext("DATE").strip() if row.findtext("DATE") else None
    record["MS"] = int(row.findtext("MS")) if row.findtext("MS") else None
    
    # 遍历所有POSITION_X节点
    position_nodes = row.xpath("./*[starts-with(local-name(), 'POSITION_')]")
    for pos_node in position_nodes:
        pos_name = pos_node.tag
        # 提取子节点内容并按要求命名列
        record[f"{pos_name}.VALUE"] = pos_node.findtext("VALUE").strip() if pos_node.findtext("VALUE") else None
        record[f"{pos_name}.STATUSVALUE"] = int(pos_node.findtext("STATUSVALUE")) if pos_node.findtext("STATUSVALUE") else None
        record[f"{pos_name}.STATUS"] = pos_node.findtext("STATUS").strip() if pos_node.findtext("STATUS") else None
    
    data_records.append(record)

# 构造DataFrame
df = pd.DataFrame(data_records)

# 按Power Query导出的列顺序调整(可选,确保列顺序完全匹配)
target_columns = [
    "DATE", "MS",
    "POSITION_1.VALUE", "POSITION_1.STATUSVALUE", "POSITION_1.STATUS",
    "POSITION_2.VALUE", "POSITION_2.STATUSVALUE", "POSITION_2.STATUS",
    "POSITION_3.VALUE", "POSITION_3.STATUSVALUE", "POSITION_3.STATUS",
    "POSITION_4.VALUE", "POSITION_4.STATUSVALUE", "POSITION_4.STATUS",
    "POSITION_5.VALUE", "POSITION_5.STATUSVALUE", "POSITION_5.STATUS",
    "POSITION_6.VALUE", "POSITION_6.STATUSVALUE", "POSITION_6.STATUS"
]
df = df.reindex(target_columns, axis=1)

# 查看结果
print(df)

关键说明

  • 如果你的XML是字符串而非文件,将etree.parse替换为etree.fromstring(your_xml_string, parser=etree.XMLParser(recover=True))。
  • strip()用于去除字段值前后的空白字符(比如示例中VALUE字段末尾的空格),如果不需要保留原始空白可以去掉。
  • reindex步骤可以确保列顺序和你提供的Power Query格式完全一致,避免因POSITION节点顺序不同导致列乱序。

内容的提问来源于stack exchange,提问作者ChemEnger

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 06:55:59