如何用Python获取XML目标元素的父元素并修改其属性
精准定位XML父元素并修改属性的解决方案
针对你遇到的问题——能找到符合OI[@DESCR='RmTmp']/PI[@Name='NOTE2' and @Value='CU008']的子元素,但无法获取父OI元素修改其DESCR属性,这里提供两种实用解决方案,同时结合读取CSV内容的需求:
方法1:通过子元素反向获取父OI元素
原代码已经能定位到目标PI元素,只需利用ElementTree的getparent()方法(标准库)拿到父OI元素,即可直接修改其属性。
修改后的完整代码(含CSV读取):
import xml.etree.ElementTree as ET import csv def update_oi_descr(tag, rom_value, new_descr): tree = ET.parse("your_xml_file.xml") root = tree.getroot() # 遍历符合条件的PI子元素 for pi_elem in root.findall(f".//OI[@DESCR='{tag}']/PI[@Name='NOTE2']"): if pi_elem.attrib.get("Value") == rom_value: # 获取父OI元素并修改DESCR oi_elem = pi_elem.getparent() oi_elem.set("DESCR", new_descr) print(f"已将目标OI的DESCR修改为: {new_descr}") # 保存修改后的XML文件 tree.write( "modified_xml.xml", encoding="utf-8", xml_declaration=True, method="xml" ) return # 找到目标后退出,避免重复处理 # 从CSV读取新的DESCR值(示例:假设CSV第二行第一个字段为目标值) new_descr = "" with open("your_csv_file.csv", "r", encoding="utf-8") as csv_file: reader = csv.reader(csv_file) next(reader) # 跳过表头行 new_descr = next(reader)[0] # 执行修改 update_oi_descr("RmTmp", "CU008", new_descr)
方法2:用XPath直接定位目标OI元素(更高效)
直接构造XPath表达式,一步定位到包含指定PI子元素的OI元素,省去反向查找父节点的步骤,尤其适合大型XML文件,性能更优。
代码示例:
import xml.etree.ElementTree as ET import csv def update_oi_descr(rom_value, new_descr): tree = ET.parse("your_xml_file.xml") root = tree.getroot() # XPath直接定位符合条件的OI元素 xpath = f".//OI[@DESCR='RmTmp' and PI[@Name='NOTE2' and @Value='{rom_value}']]" target_oi = root.find(xpath) if target_oi: target_oi.set("DESCR", new_descr) print(f"修改成功,新DESCR值: {new_descr}") tree.write( "modified_xml.xml", encoding="utf-8", xml_declaration=True ) else: print("未找到符合条件的OI元素") # 读取CSV中的新DESCR值 new_descr = "" with open("your_csv_file.csv", "r", encoding="utf-8") as csv_file: reader = csv.reader(csv_file) next(reader) new_descr = next(reader)[0] update_oi_descr("CU008", new_descr)
处理大型XML的优化建议
如果XML文件体积极大,一次性加载到内存会占用过多资源,建议用iterparse逐行解析并清理已处理元素:
import xml.etree.ElementTree as ET import csv # 先读取CSV中的新值 new_descr = "" with open("your_csv_file.csv", "r", encoding="utf-8") as csv_file: reader = csv.reader(csv_file) next(reader) new_descr = next(reader)[0] # 逐行解析XML context = ET.iterparse("large_xml.xml", events=("start", "end")) context = iter(context) event, root = next(context) for event, elem in context: if event == "end" and elem.tag == "PI": # 检查PI元素是否符合条件 if elem.attrib.get("Name") == "NOTE2" and elem.attrib.get("Value") == "CU008": oi_elem = elem.getparent() if oi_elem.attrib.get("DESCR") == "RmTmp": oi_elem.set("DESCR", new_descr) # 保存修改 tree = ET.ElementTree(root) tree.write("modified_large_xml.xml", encoding="utf-8", xml_declaration=True) break elem.clear() # 清理已处理元素,释放内存
内容的提问来源于stack exchange,提问作者Asgeir Bakke
相关产品推荐
相关产品推荐

