Python循环处理XML文件时,如何保留每次修改的结果?
保留XML中指定节点的正确做法
问题描述
需要清理XML文件中不必要的Brand_1的节点。尝试用正则循环替换时,修改无法累积生效,最终达不到预期效果。
当前代码
import re from bs4 import BeautifulSoup as bs filepath = "C://ddd/test.xml" xml = ''' <Images> <EmbeddedImage Name="Brand_1"> <ImageData>/9j/4AAQSkZJB//2Q==</ImageData> </EmbeddedImage> <EmbeddedImage Name="Brand__2XX"> <ImageData>/9j/4AAQSkZJB//2Q==JB//2</ImageData> </EmbeddedImage> <EmbeddedImage Name="Brand___3XX"> <ImageData>/9j/4AAQSkZAAQSkkB//2Q=AAQSk=</ImageData> </EmbeddedImage> <Images>''' Bs_data = bs(xml,'xml') #contant = xml ?? content = xml for item in Bs_data.select ('EmbeddedImage'): #print('Name= ',item.get('Name')) if item.get('Name') != 'Brand_1': wild = '<EmbeddedImage Name="'+item.get('Name')+'">.*</EmbeddedImage>' ##<@><< first </ How??? content = re.sub(wild, '', content , flags=re.DOTALL) print ('------------',wild,'::::',content) print(content) # only Brand_1
问题根源
用正则处理XML是错误思路:XML是结构化文档,标签的换行、空格、属性顺序变化都会导致正则匹配失效;同时你的正则使用.*贪婪匹配,会误删多个连续节点,循环中基于原始字符串的替换逻辑也容易出现覆盖问题。
修复方案:用BeautifulSoup直接操作DOM
BeautifulSoup是专门处理结构化标记语言的工具,直接操作节点比正则可靠得多,步骤如下:
- 解析XML得到DOM树
- 遍历所有
节点,删除不符合条件的节点 - 将修改后的DOM树转为字符串输出
修复后的代码
from bs4 import BeautifulSoup as bs xml = ''' <Images> <EmbeddedImage Name="Brand_1"> <ImageData>/9j/4AAQSkZJB//2Q==</ImageData> </EmbeddedImage> <EmbeddedImage Name="Brand__2XX"> <ImageData>/9j/4AAQSkZJB//2Q==JB//2</ImageData> </EmbeddedImage> <EmbeddedImage Name="Brand___3XX"> <ImageData>/9j/4AAQSkZAAQSkkB//2Q=AAQSk=</ImageData> </EmbeddedImage> </Images>''' # 解析XML soup = bs(xml, 'xml') # 找到所有EmbeddedImage节点 images = soup.select('EmbeddedImage') # 遍历并删除不需要的节点 for img in images: if img.get('Name') != 'Brand_1': img.decompose() # 从DOM树中删除节点 # 输出处理后的XML(prettify用于格式化,也可以直接用str(soup)) print(soup.prettify())
代码说明
img.decompose():直接从BeautifulSoup的DOM树中移除节点,所有修改会实时保留在soup对象中- 如果需要处理本地文件,可以扩展为读写文件的形式:
from bs4 import BeautifulSoup as bs filepath = "C://ddd/test.xml" # 读取原文件 with open(filepath, 'r', encoding='utf-8') as f: xml_content = f.read() soup = bs(xml_content, 'xml') # 清理节点 images = soup.select('EmbeddedImage') for img in images: if img.get('Name') != 'Brand_1': img.decompose() # 写入处理后的内容 with open(filepath, 'w', encoding='utf-8') as f: f.write(str(soup))
内容的提问来源于stack exchange,提问作者Mich28
相关产品推荐
相关产品推荐

