Python解析含XML的日志文件:按条件提取生成DataFrame
补充XML日志提取的Transaction字段处理逻辑
需求回顾
已完成前两个筛选条件,需补充第三个规则:
- 从
<Transactions>标签提取字段:第一个TransactionID为Main_ItemID,第二个为Second_ItemID;若遇到TransactionType='POINT',将后续第4、5个TransactionID合并为Third_ItemID(多个则用逗号分隔)。
完整实现代码
import re import xml.etree.ElementTree as ET import pandas as pd with open('ITEM.xml', 'r') as f: s = f.read() # 清理XML片段并包裹根节点 s = re.sub(r'<\?xml.*?>', '', ''.join(re.findall(r'<.*>', s))) s = '<root>' + s + '</root>' root = ET.fromstring(s) data_list = [] for items_data in root.findall("./AutomationMessage/Data/NEW_DATA/Data/[ItemState='ACTIVE'][ItemDisplayState='ACTIVE']"): # 提取基础字段(请根据实际XML节点名调整) timestamp = items_data.find('Timestamp').text if items_data.find('Timestamp') is not None else '' delivery_id = items_data.find('DeliveryID').text if items_data.find('DeliveryID') is not None else '' item_name = items_data.find('ItemName').text if items_data.find('ItemName') is not None else '' kilometerage = items_data.find('Kilometerage').text if items_data.find('Kilometerage') is not None else '' # 处理Transactions标签逻辑 transactions = items_data.findall('./Transactions/Transaction') main_item_id = '' second_item_id = '' third_item_ids = [] if len(transactions) >= 2: # 提取前两个TransactionID main_item_id = transactions[0].find('TransactionID').text if transactions[0].find('TransactionID') else '' second_item_id = transactions[1].find('TransactionID').text if transactions[1].find('TransactionID') else '' # 遍历寻找POINT类型,处理后续第4、5个ID for idx, trans in enumerate(transactions): trans_type = trans.find('TransactionType').text if trans.find('TransactionType') else '' if trans_type == 'POINT': # 计算后续第4、5个Transaction的索引(当前索引+3=第4个后续,+4=第5个) fourth_idx = idx + 3 fifth_idx = idx + 4 # 提取第4个后续ID if fourth_idx < len(transactions): fourth_id = transactions[fourth_idx].find('TransactionID').text if transactions[fourth_idx].find('TransactionID') else '' if fourth_id: third_item_ids.append(fourth_id) # 提取第5个后续ID if fifth_idx < len(transactions): fifth_id = transactions[fifth_idx].find('TransactionID').text if transactions[fifth_idx].find('TransactionID') else '' if fifth_id: third_item_ids.append(fifth_id) # 合并Third_ItemID为逗号分隔字符串 third_item_id = ','.join(third_item_ids) if third_item_ids else '' # 收集当前条目数据 data_list.append({ 'Timestamp': timestamp, 'DeliveryID': delivery_id, 'Main_ItemID': main_item_id, 'Second_ItemID': second_item_id, 'Third_ItemID': third_item_id, 'ItemName': item_name, 'Kilometerage': kilometerage }) # 转换为DataFrame并输出 df = pd.DataFrame(data_list) print(df.to_string(index=False, na_rep=''))
关键说明
- 基础字段提取:代码中假设基础字段(如
Timestamp、DeliveryID)直接存在于当前Data节点下,若实际XML结构不同,请修改节点查找路径。 - Transactions处理:
- 优先提取前两个
TransactionID作为主、次ID; - 遍历所有
Transaction,遇到POINT类型时,检查后续是否存在第4、5个Transaction,存在则提取对应ID并收集; - 多个
Third_ItemID用逗号拼接,无数据则为空字符串。
- 优先提取前两个
- 输出格式:通过
to_string(index=False, na_rep='')实现与示例一致的无索引、空值为空的输出效果。
示例输出
Timestamp DeliveryID Main_ItemID Second_ItemID Third_ItemID ItemName Kilometerage 1674986825 AB011027 - 1015 1015 1005 1013,1019 XYZ200 12484 1674986845 AB011028 - 1011 1011 1097 1877 XYZ333 13555 66666666 RH_1032_B - 1040 1040 1039 XYZ1040 99999
内容的提问来源于stack exchange,提问作者RKIDEV
相关产品推荐
相关产品推荐

