新手求助:使用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
相关产品推荐
相关产品推荐

