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

新手求助:使用Pandas read_xml函数转换XML文件为DataFrame无法获取数据字段

解决Pandas读取带命名空间XML无法提取数据的问题

我之前也碰到过类似的情况,你的问题核心在于XML中存在默认命名空间,导致pd.read_xml没法正确定位到<event>节点。下面给你两种实用的解决办法,都能得到你期望的DataFrame格式:

方法一:指定命名空间,通过XPath定位节点

这是更规范的做法,适合处理复杂的XML结构:

import pandas as pd

xml='''<TimeSeries xmlns="http://www.wldelft.nl/fews/PI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.wldelft.nl/fews/PI http://fews.wldelft.nl/schemas/version1.0/pi-schemas/pi_timeseries.xsd" version="1.26" xmlns:fs="http://www.wldelft.nl/fews/fs">
    <timeZone>1.0</timeZone>
    <series>
        <header>
            <type>instantaneous</type>
            <moduleInstanceId>pr.pompvolumes</moduleInstanceId>
            <locationId>SL000246</locationId>
            <parameterId>Q.B.d</parameterId>
            <timeStep unit="second" multiplier="86400"/>
            <startDate date="2018-01-01" time="00:00:00"/>
            <endDate date="2022-01-01" time="00:00:00"/>
            <missVal>NaN</missVal>
            <stationName>Putten vijzel</stationName>
            <lat>52.263570497449855</lat>
            <lon>5.495717667656339</lon>
            <x>162408.0</x>
            <y>475066.0</y>
            <units>m3/s</units>
        </header>
        <event date="2018-01-01" time="00:00:00" value="1.262" flag="0"/>
        <event date="2018-01-02" time="00:00:00" value="1.456" flag="0"/>
        <event date="2018-01-03" time="00:00:00" value="0.845" flag="0"/>
        <event date="2018-01-04" time="00:00:00" value="1.507" flag="0"/>
        <event date="2018-01-05" time="00:00:00" value="1.083" flag="0"/>
        <event date="2018-01-06" time="00:00:00" value="0.516" flag="0"/>
    </series>
</TimeSeries>'''

# 给XML的默认命名空间定义一个别名(这里用pi)
namespaces = {'pi': 'http://www.wldelft.nl/fews/PI'}
# 使用XPath定位所有<event>节点,自动提取节点属性作为列
df = pd.read_xml(xml, xpath='//pi:event', namespaces=namespaces)

# 筛选并调整列名和数据类型,匹配你的期望格式
df = df[['date', 'value', 'flag']].rename(columns={'date': 'event date'})
df['value'] = df['value'].astype(float)
df['flag'] = df['flag'].astype(int)

print(df)

解释:

  • XML里的xmlns="http://www.wldelft.nl/fews/PI"是默认命名空间,所有节点都属于这个命名空间,必须通过别名才能被XPath识别
  • //pi:event表示匹配所有层级下的<event>节点
  • 最后调整列名和数据类型,就能得到你想要的结果

方法二:移除命名空间声明后读取(简单粗暴版)

如果你的XML结构比较简单,也可以直接去掉命名空间声明,让pd.read_xml直接识别节点:

import pandas as pd
import re

xml='''<TimeSeries xmlns="http://www.wldelft.nl/fews/PI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.wldelft.nl/fews/PI http://fews.wldelft.nl/schemas/version1.0/pi-schemas/pi_timeseries.xsd" version="1.26" xmlns:fs="http://www.wldelft.nl/fews/fs">
    <timeZone>1.0</timeZone>
    <series>
        <header>
            <type>instantaneous</type>
            <moduleInstanceId>pr.pompvolumes</moduleInstanceId>
            <locationId>SL000246</locationId>
            <parameterId>Q.B.d</parameterId>
            <timeStep unit="second" multiplier="86400"/>
            <startDate date="2018-01-01" time="00:00:00"/>
            <endDate date="2022-01-01" time="00:00:00"/>
            <missVal>NaN</missVal>
            <stationName>Putten vijzel</stationName>
            <lat>52.263570497449855</lat>
            <lon>5.495717667656339</lon>
            <x>162408.0</x>
            <y>475066.0</y>
            <units>m3/s</units>
        </header>
        <event date="2018-01-01" time="00:00:00" value="1.262" flag="0"/>
        <event date="2018-01-02" time="00:00:00" value="1.456" flag="0"/>
        <event date="2018-01-03" time="00:00:00" value="0.845" flag="0"/>
        <event date="2018-01-04" time="00:00:00" value="1.507" flag="0"/>
        <event date="2018-01-05" time="00:00:00" value="1.083" flag="0"/>
        <event date="2018-01-06" time="00:00:00" value="0.516" flag="0"/>
    </series>
</TimeSeries>'''

# 用正则表达式移除默认命名空间属性
xml_no_ns = re.sub(r'xmlns="[^"]+"', '', xml)
# 直接定位<event>节点读取
df = pd.read_xml(xml_no_ns, xpath='//event')

# 同样调整列名和数据类型
df = df[['date', 'value', 'flag']].rename(columns={'date': 'event date'})
df['value'] = df['value'].astype(float)
df['flag'] = df['flag'].astype(int)

print(df)

解释:

  • 正则表达式xmlns="[^"]+"匹配并移除默认命名空间的声明
  • 处理后的XML不再有命名空间限制,pd.read_xml可以直接找到<event>节点

两种方法运行后都会输出你期望的DataFrame:

event date  value  flag
0  2018-01-01  1.262     0
1  2018-01-02  1.456     0
2  2018-01-03  0.845     0
3  2018-01-04  1.507     0
4  2018-01-05  1.083     0
5  2018-01-06  0.516     0

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 15:47:28