Python:如何根据同级子元素的值为指定元素添加子元素?
Python 基于ElementTree/DOM修改XML:根据Unit值添加指定子元素结构
用ElementTree实现(推荐)
ElementTree是Python标准库中处理XML的轻量工具,代码简洁高效,完全符合你无需导入数据库的需求:
步骤与示例代码
假设你的XML结构大致如下:
<Root> <Apparatus> <Unit>TW29</Unit> <Type>FireTruck</Type> </Apparatus> <Apparatus> <Unit>AB12</Unit> <Type>Ambulance</Type> </Apparatus> </Root>
执行修改的代码:
import xml.etree.ElementTree as ET # 加载XML文件 tree = ET.parse('input.xml') root = tree.getroot() # 遍历所有Apparatus元素 for apparatus in root.findall('.//Apparatus'): # 获取当前Apparatus下的Unit子元素 unit_elem = apparatus.find('Unit') # 检查Unit值是否为TW29(处理空值和空白字符) if unit_elem is not None and unit_elem.text.strip() == 'TW29': # 添加DispatchTime子元素 dispatch_time = ET.SubElement(apparatus, 'DispatchTime') dispatch_time.text = '2024-05-20T14:30:00' # 替换为实际需要的时间值 # 添加ApparatusPersonnelCollection子树 personnel_coll = ET.SubElement(apparatus, 'ApparatusPersonnelCollection') # 第一个人员节点 personnel1 = ET.SubElement(personnel_coll, 'ApparatusPersonnel') name1 = ET.SubElement(personnel1, 'Name') name1.text = 'John Doe' role1 = ET.SubElement(personnel1, 'Role') role1.text = 'Driver' # 第二个人员节点(按需扩展) personnel2 = ET.SubElement(personnel_coll, 'ApparatusPersonnel') name2 = ET.SubElement(personnel2, 'Name') name2.text = 'Jane Smith' role2 = ET.SubElement(personnel2, 'Role') role2.text = 'Operator' # 保存修改后的XML,指定编码和XML声明 tree.write('output.xml', encoding='utf-8', xml_declaration=True)
用DOM实现
如果你更倾向于DOM API,也可以用Python标准库的xml.dom.minidom完成需求:
示例代码
from xml.dom import minidom # 解析XML文件 dom = minidom.parse('input.xml') root = dom.documentElement # 获取所有Apparatus元素 apparatus_list = root.getElementsByTagName('Apparatus') for apparatus in apparatus_list: # 获取Unit元素(取第一个匹配的) unit_elems = apparatus.getElementsByTagName('Unit') if unit_elems: unit_text = unit_elems[0].firstChild.nodeValue.strip() if unit_text == 'TW29': # 创建并添加DispatchTime dispatch_time = dom.createElement('DispatchTime') time_text = dom.createTextNode('2024-05-20T14:30:00') dispatch_time.appendChild(time_text) apparatus.appendChild(dispatch_time) # 创建ApparatusPersonnelCollection及子元素 personnel_coll = dom.createElement('ApparatusPersonnelCollection') # 第一个人员 personnel1 = dom.createElement('ApparatusPersonnel') name1 = dom.createElement('Name') name1.appendChild(dom.createTextNode('John Doe')) role1 = dom.createElement('Role') role1.appendChild(dom.createTextNode('Driver')) personnel1.appendChild(name1) personnel1.appendChild(role1) personnel_coll.appendChild(personnel1) # 第二个人员 personnel2 = dom.createElement('ApparatusPersonnel') name2 = dom.createElement('Name') name2.appendChild(dom.createTextNode('Jane Smith')) role2 = dom.createElement('Role') role2.appendChild(dom.createTextNode('Operator')) personnel2.appendChild(name2) personnel2.appendChild(role2) personnel_coll.appendChild(personnel2) apparatus.appendChild(personnel_coll) # 保存修改后的文件 with open('output_dom.xml', 'w', encoding='utf-8') as f: dom.writexml(f, encoding='utf-8')
关键注意事项
- 命名空间处理:如果你的XML包含命名空间(比如根元素带有
xmlns属性),需要在find/findall时指定命名空间映射。例如:ns = {'ns': 'http://example.com/your-schema'} for apparatus in root.findall('.//ns:Apparatus', namespaces=ns): unit_elem = apparatus.find('ns:Unit', namespaces=ns) - 子元素位置控制:如果需要将新元素插入到指定位置(而非末尾),可以使用
insert方法。比如找到某个已有元素的索引,再插入新元素:# 假设要插入到Type元素之后 type_elem = apparatus.find('Type') if type_elem is not None: index = list(apparatus).index(type_elem) + 1 apparatus.insert(index, dispatch_time) - 避免重复添加:如果需要防止重复添加相同结构,可以先检查目标元素是否已存在,比如:
if apparatus.find('DispatchTime') is None: # 才创建并添加DispatchTime
内容的提问来源于stack exchange,提问作者buckyswider
相关产品推荐
相关产品推荐

