UDDF XML转CSV的Python脚本优化:正则或ElementTree方案咨询
问题
我写了一段将UDDF XML文件转换为CSV格式的Python脚本,目前用拆分浮点数后重新拼接的方式处理数值,方法比较粗糙。想请教:仅用正则表达式,或者借助ElementTree库,有没有更优的实现方案?
我的Python脚本
import re uddf_file = open("c:/temp/python/uddf_to_csv/input.xml", "r") csv_file = open("c:/temp/python/uddf_to_csv/output.csv", "x") while True: uddf_line = uddf_file.readline() uddf_line.rstrip('\r\n') depth_val = re.search("depth", uddf_line) if depth_val: depth_val_num = re.findall(r'\d+', uddf_line) if depth_val: csv_file.write(depth_val_num[0] + "." + depth_val_num[1] + ",") time_val = re.search("divetime", uddf_line) if time_val: time_val_num = re.findall(r'\d+', uddf_line) if time_val: csv_file.write(time_val_num[0] + "." + time_val_num[1] + ",") temp_val = re.search("temperature", uddf_line) if temp_val: temp_val_num = re.findall(r'\d+', uddf_line) if temp_val: csv_file.write(temp_val_num[0] + "." + temp_val_num[1] + "\n") if not uddf_line: break; uddf_file.close() csv_file.close()
示例UDDF文件
<?xml version="1.0" encoding="utf-8"?> <uddf xmlns="http://www.streit.cc/uddf/3.2/" version="3.2.0"> <generator> <name>awu2uddf</name> <manufacturer id="Foghead"> <name>Doug Junkins</name> </manufacturer> <version>1.1(3)</version> </generator> <diver> <owner id="owner"> <personal> <firstname/> <lastname/> </personal> <equipment> <divecomputer id="81333b11"> <name>Apple Watch Ultra</name> <model>Apple Watch Ultra</model> </divecomputer> </equipment> </owner> <buddy/> </diver> <divesite/> <gasdefinitions/> <profiledata> <repetitiongroup id="2023-04-12T17:02:08Z"> <dive id="2023-04-12T17:02:08Z"> <informationbeforedive> <datetime>2023-04-12T10:02:08-0700</datetime> </informationbeforedive> <samples> <waypoint> <depth>2.086</depth> <divetime>2.520</divetime> <temperature>293.3</temperature> </waypoint> <waypoint> <depth>3.322</depth> <divetime>5.150</divetime> <temperature>293.3</temperature> </waypoint> <waypoint> <depth>1.101</depth> <divetime>2263.999</divetime> <temperature>293.2</temperature> </waypoint> </samples> </dive> </repetitiongroup> </profiledata> </uddf>
解决方案
方案一:改进正则表达式实现
原脚本拆分浮点数再拼接的方式容错性差,遇到整数或跨行数值会失效。直接匹配完整数值的正则方案更可靠:
import re # 用with语句自动管理文件,避免手动关闭遗漏 with open("c:/temp/python/uddf_to_csv/input.xml", "r") as uddf_file, open("c:/temp/python/uddf_to_csv/output.csv", "x") as csv_file: current_row = [] # 匹配标签和对应数值,支持整数、浮点数格式 pattern = re.compile(r'<(depth|divetime|temperature)>(\d+\.?\d*|\.\d+)</\1>') for line in uddf_file: matches = pattern.findall(line) for tag, value in matches: current_row.append(value) # 收集到三个字段后写入CSV,确保属于同一个waypoint if len(current_row) == 3: csv_file.write(','.join(current_row) + '\n') current_row = []
核心改进
- 用正则直接提取完整数值,无需拆分拼接,兼容整数和浮点数
- 新增临时列表
current_row,避免字段错位 - 使用
with语句自动处理文件生命周期,代码更简洁安全
方案二:使用ElementTree库(更推荐)
XML是结构化数据,用专门解析库比正则更稳定,尤其能处理UDDF的命名空间和嵌套结构:
import xml.etree.ElementTree as ET import csv # 定义UDDF的命名空间,XML中必须指定才能正确查找节点 NS = {'uddf': 'http://www.streit.cc/uddf/3.2/'} # 解析XML文件 tree = ET.parse("c:/temp/python/uddf_to_csv/input.xml") root = tree.getroot() # 写入CSV文件 with open("c:/temp/python/uddf_to_csv/output.csv", "x", newline='') as csv_file: writer = csv.writer(csv_file) # 遍历所有waypoint节点 for waypoint in root.findall('.//uddf:waypoint', NS): # 提取每个节点的字段值 depth = waypoint.find('uddf:depth', NS).text divetime = waypoint.find('uddf:divetime', NS).text temperature = waypoint.find('uddf:temperature', NS).text # 写入一行数据 writer.writerow([depth, divetime, temperature])
显著优势
- 完全贴合XML结构解析,不会出现正则的误匹配问题
- 自动处理UDDF的命名空间,原正则脚本未处理此情况,若标签带命名空间会失效
- 使用
csv.writer模块规范写入CSV,自动处理潜在的特殊字符问题 - 代码逻辑清晰,直接按节点层级提取数据,维护成本低
内容的提问来源于stack exchange,提问作者IronDevil74
相关产品推荐
相关产品推荐

