如何用Python通过属性名解析XML字符串获取对应值
从CSV中的XML字符串提取属性值(Python)
我正在使用Python,需要从CSV文件读取的XML字符串中提取特定值。示例XML字符串如下:
<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'> <System> <Provider Name='Microsoft-Windows' Guid='{aaaa-ss-www-qqq-qeqweqwe}'/> <EventID>4771</EventID> <Version>0</Version> <Level>0</Level> <Task>1000</Task> <Opcode>0</Opcode> <Keywords>0x9110</Keywords> <TimeCreated SystemTime='2022-01-01T00:00:00.000000Z'/> <EventRecordID>123123123</EventRecordID> <Correlation/> <Execution ProcessID='2' ThreadID='11'/> <Channel>Security</Channel> <Computer>pcname</Computer> <Security/> </System> <EventData> <Data Name='TargetUserName'>user</Data> <Data Name='TargetSid'>S-1-5-21-123123-321312-123132-31212</Data> <Data Name='ServiceName'>service/dom</Data> <Data Name='TicketOptions'>0x123123</Data> <Data Name='Status'>0xq</Data> <Data Name='PreAuthType'>0</Data> <Data Name='IpAddress'>::ffff:8.8.8.8</Data> <Data Name='IpPort'>123321</Data> <Data Name='CertIssuerName'></Data> <Data Name='CertSerialNumber'></Data> <Data Name='CertThumbprint'></Data> </EventData> </Event>
我已编写了一段可通过属性路径获取部分值的代码:
import os, csv import xml.etree.ElementTree as ET def cls(): os.system('cls' if os.name=='nt' else 'clear') cls() raw = open('C:/tmp2/data.csv', 'r') reader = csv.reader(raw) line_number = 1 for i, row in enumerate(reader): if i == line_number: break tree = ET.fromstring(''.join(row)) EventID = [literal.text for literal in tree.findall('.//{http://schemas.microsoft.com/win/2004/08/events/event}System/{http://schemas.microsoft.com/win/2004/08/events/event}EventID')] TimeCreated = [literal.text for literal in tree.findall('.//{http://schemas.microsoft.com/win/2004/08/events/event}System/{http://schemas.microsoft.com/win/2004/08/events/event}TimeCreated[@Name="SystemTime"]')] TargetUserName = [literal.text for literal in tree.findall('.//{http://schemas.microsoft.com/win/2004/08/events/event}EventData/{http://schemas.microsoft.com/win/2004/08/events/event}Data[@Name="TargetUserName"]')] ServiceName = [literal.text for literal in tree.findall('.//{http://schemas.microsoft.com/win/2004/08/events/event}EventData/{http://schemas.microsoft.com/win/2004/08/events/event}Data[@Name="ServiceName"]')] print ('EVENT:',''.join(EventID)) print ('TimeCreated:',''.join(TimeCreated)) print ('TargetUserName:',''.join(TargetUserName)) print ('ServiceName:', ''.join(ServiceName))
请问如何通过属性名获取对应的属性值,例如获取类似EventID这类目标的相关值?
解决方案
1. 简化命名空间处理
XML带有固定命名空间,直接写完整URL会冗余,先定义命名空间映射:
ns = {'evt': 'http://schemas.microsoft.com/win/2004/08/events/event'}
之后所有XPath查询用evt:前缀代替长串命名空间URL,代码更简洁。
2. 两种提取场景的处理
- 提取元素文本(如EventID):用
find()定位元素后,直接取.text属性(这类值在标签内部)。 - 提取元素属性值(如TimeCreated的SystemTime):定位元素后,用
.get('属性名')方法获取对应属性值。
3. 优化后的完整代码
import os, csv import xml.etree.ElementTree as ET def cls(): os.system('cls' if os.name=='nt' else 'clear') cls() # 定义命名空间映射 ns = {'evt': 'http://schemas.microsoft.com/win/2004/08/events/event'} # 读取CSV中的目标行XML字符串 with open('C:/tmp2/data.csv', 'r') as raw: reader = csv.reader(raw) line_number = 1 target_row = None for i, row in enumerate(reader): if i == line_number: target_row = ''.join(row) break # 解析XML tree = ET.fromstring(target_row) # 提取元素文本 event_id = tree.find('.//evt:System/evt:EventID', ns).text target_user = tree.find('.//evt:EventData/evt:Data[@Name="TargetUserName"]', ns).text service_name = tree.find('.//evt:EventData/evt:Data[@Name="ServiceName"]', ns).text # 提取属性值 time_created = tree.find('.//evt:System/evt:TimeCreated', ns).get('SystemTime') provider_name = tree.find('.//evt:System/evt:Provider', ns).get('Name') process_id = tree.find('.//evt:System/evt:Execution', ns).get('ProcessID') # 输出结果 print(f'EVENT: {event_id}') print(f'TimeCreated: {time_created}') print(f'TargetUserName: {target_user}') print(f'ServiceName: {service_name}') print(f'Provider Name: {provider_name}') print(f'Process ID: {process_id}')
说明
- 用
with open()代替直接open(),自动处理文件关闭,更安全。 find()返回单个匹配元素(适用于唯一目标),比findall()更高效,无需处理列表。EventData下的Data元素通过[@Name="属性名"]的XPath条件定位,直接提取对应文本。
内容的提问来源于stack exchange,提问作者Peter Asp
相关产品推荐
相关产品推荐

