Python读取xml文件

1、加载包

import chardet
import xml.etree.ElementTree as ET
import csv

2、确定xml文件内数据的格式

with open('20250320081954.xml', 'rb') as f:
    raw_data = f.read()
    result = chardet.detect(raw_data)
    encoding = result['encoding']
    print(f"文件编码: {encoding}")
    tree = ET.parse('yourfile.xml', encoding=encoding)

如果成功读取数据,万事大吉,若失败,显示BOM报错,是因为Python的 xml.etree.ElementTree 模块期望该文件以BOM(字节顺序标记)开头,用于指示其字节顺序。
我的数据比较奇怪,chardet显示是ascii格式,但是文件内部显示是utf-16的格式🤣🤣

3、读取文件

# 读取XML文件
xml_file = '20250320081954.xml'  # 请替换为你的XML文件路径
with open(xml_file, 'rb') as file:  # 以二进制模式打开文件
    xml_content = file.read().decode('ascii')  # 解码为ascii字符串,更适合无BOM的情况,上一个代码怎么都无法读取成功,但是这个可以,玄学

# 解析XML内容
root = ET.fromstring(xml_content)

# 获取风速数据
wind_unit_data = root.find('.//Units')
rows = []
for wind_data in wind_unit_data.findall('WindUnitData'):
    row = {
        'Height': wind_data.find('Height').text,
        'Direction': wind_data.find('Direction').text,
        'SpeedH': wind_data.find('SpeedH').text,
        'SpeedV': wind_data.find('SpeedV').text,
        'CNR': wind_data.find('CNR').text,
        'MinAvgHWS': wind_data.find('MinAvgHWS').text,
        'MinAvgHWD': wind_data.find('MinAvgHWD').text,
        'MinAvgVWS': wind_data.find('MinAvgVWS').text,
        'VWSH': wind_data.find('VWSH').text,
        'VWSE': wind_data.find('VWSE').text,
        'TI': wind_data.find('TI').text,
    }
    rows.append(row)
3.1 数据特殊要求

由于读取数据中有某一结点未能读取成功,由于我只需要部分的数据,对节点进行判断读取

tree = ET.ElementTree(ET.fromstring(xml_content))
root = tree.getroot()

# 获取高度(Height)列表
wind_unit_data = root.find('.//Units')
heights = [int(wind.findtext('Height')) for wind in wind_unit_data.findall('WindUnitData')]

# 初始化字典,用于存储V1和V2数据
radial_velocity_data = {"Height": heights, "V1": [], "V2": []}

# 读取 RadialVelocityDatas 中的数据
radial_velocity_datas = root.find('.//RadialVelocityDatas')
if radial_velocity_datas:
    for velocity_data in radial_velocity_datas.findall('RadialVelocityData'):
        azimuth = velocity_data.findtext('Azimuth')
        moments = velocity_data.find('.//RadialVelocityMoments')
        for moment in moments.findall('RadialVelocityMoment'):
            moment_type = moment.findtext('MomentType')
            # 只处理 MomentType 为 V 的数据
            if moment_type == 'V':
                data = [float(value.text) for value in moment.find('.//Data').findall('float')]
                if azimuth == '1':
                    radial_velocity_data["V1"] = data
                elif azimuth == '2':
                    radial_velocity_data["V2"] = data
3.2 综合读取
# 读取XML文件
xml_file = '20250320081954.xml'  # 请替换为你的XML文件路径
with open(xml_file, 'rb') as file:  # 以二进制模式打开文件
    xml_content = file.read().decode('ascii')  # 解码文件内容

# 解析XML内容
root = ET.fromstring(xml_content)

# 获取风速数据
wind_unit_data = root.find('.//Units')
radial_velocity_data = root.find('.//RadialVelocityDatas')

rows = []

# 获取MomentType为"V"的数据
moment_v_1 = []
moment_v_2 = []

for radial_data in radial_velocity_data.findall('RadialVelocityData'):
    moment = radial_data.find('./RadialVelocityMoments/RadialVelocityMoment[MomentType="V"]')
    if moment is not None:
        azimuth = radial_data.find('Azimuth').text
        data_values = [float(float_value.text) for float_value in moment.findall('./Data/float')]
        if azimuth == "1":  # V1
            moment_v_1 = data_values
        elif azimuth == "2":  # V2
            moment_v_2 = data_values

# 将数据和风速数据对应起来
for idx, wind_data in enumerate(wind_unit_data.findall('WindUnitData')):
    row = {
        'Height': wind_data.find('Height').text,
        'Direction': wind_data.find('Direction').text,
        'SpeedH': wind_data.find('SpeedH').text,
        'SpeedV': wind_data.find('SpeedV').text,
        'CNR': wind_data.find('CNR').text,
        'MinAvgHWS': wind_data.find('MinAvgHWS').text,
        'MinAvgHWD': wind_data.find('MinAvgHWD').text,
        'MinAvgVWS': wind_data.find('MinAvgVWS').text,
        'VWSH': wind_data.find('VWSH').text,
        'VWSE': wind_data.find('VWSE').text,
        'TI': wind_data.find('TI').text,
        'V1': moment_v_1[idx] if idx < len(moment_v_1) else None,  # 填充V1
        'V2': moment_v_2[idx] if idx < len(moment_v_2) else None,  # 填充V2
    }
    rows.append(row)

4、保存为csv

# 输出为CSV文件
csv_file = 'wind_data.csv'  # 输出文件名
with open(csv_file, mode='w', newline='', encoding='utf-8') as file:
    writer = csv.DictWriter(file, fieldnames=rows[0].keys())
    writer.writeheader()
    for row in rows:
        writer.writerow(row)

5、批量读取保存

import os 

# XML文件夹路径
xml_folder = '2025032008'  # 请替换为你的XML文件夹路径
# CSV输出文件夹路径
csv_folder = 'CSV/'  # 请替换为你的CSV文件输出路径

# 获取XML文件列表
xml_files = [f for f in os.listdir(xml_folder) if f.endswith('.xml')]

# 遍历每个XML文件
for xml_file in xml_files:
    xml_path = os.path.join(xml_folder, xml_file)

    # 读取XML文件
    with open(xml_path, 'rb') as file:  # 以二进制模式打开文件
        xml_content = file.read().decode('ascii')  # 解码为utf-16字符串,处理可能的错误

    # 解析XML内容
    root = ET.fromstring(xml_content)

    # 获取风速数据
    wind_unit_data = root.find('.//Units')
    rows = []

    # 读取Units部分
    for wind_data in wind_unit_data.findall('WindUnitData'):
        row = {
            'Height': wind_data.find('Height').text,
            'Direction': wind_data.find('Direction').text,
            'SpeedH': wind_data.find('SpeedH').text,
            'SpeedV': wind_data.find('SpeedV').text,
            'CNR': wind_data.find('CNR').text,
            'MinAvgHWS': wind_data.find('MinAvgHWS').text,
            'MinAvgHWD': wind_data.find('MinAvgHWD').text,
            'MinAvgVWS': wind_data.find('MinAvgVWS').text,
            'VWSH': wind_data.find('VWSH').text,
            'VWSE': wind_data.find('VWSE').text,
            'TI': wind_data.find('TI').text,
            'V1': '',  # 初始为空,后续填充
            'V2': '',  # 初始为空,后续填充
        }
        rows.append(row)

    # 获取RadialVelocityDatas数据,仅提取MomentType为"V"的部分
    radial_velocity_datas = root.find('.//RadialVelocityDatas')
    if radial_velocity_datas:
        v1_data = []  # 存储V1数据 (Azimuth=1)
        v2_data = []  # 存储V2数据 (Azimuth=2)

        # 提取数据
        for rv_data in radial_velocity_datas.findall('RadialVelocityData'):
            azimuth = rv_data.find('Azimuth').text
            for moment in rv_data.findall('.//RadialVelocityMoment'):
                if moment.find('MomentType').text == 'V':  # 过滤MomentType=V
                    data = [float(elem.text) for elem in moment.find('Data').findall('float')]
                    if azimuth == '1':  # V1
                        v1_data = data
                    elif azimuth == '2':  # V2
                        v2_data = data

        # 将V1和V2数据对应填入到风速数据表中,仅当数量匹配时
        heights = [float(row['Height']) for row in rows]  # 获取所有高度值
        if len(v1_data) == len(heights):
            for i, row in enumerate(rows):
                row['V1'] = v1_data[i]
        if len(v2_data) == len(heights):
            for i, row in enumerate(rows):
                row['V2'] = v2_data[i]

    # 输出为CSV文件
    csv_file_name = os.path.splitext(xml_file)[0] + '.csv'  # 替换文件扩展名
    csv_file_path = os.path.join(csv_folder, csv_file_name)

    with open(csv_file_path, mode='w', newline='', encoding='utf-8') as file:
        fieldnames = list(rows[0].keys())
        writer = csv.DictWriter(file, fieldnames=fieldnames)
        writer.writeheader()
        for row in rows:
            writer.writerow(row)

    print(f"数据已存储到 {csv_file_path}")

😁😁😁
End!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值