Python LXML:如何在resources标签下添加元素并规范格式
Android资源XML添加元素后的格式修复方案
使用Python的xml.etree.ElementTree操作Android资源XML时,添加<string>元素后出现格式问题:新元素无正确缩进,且与</resources>标签挤在一起。以下是问题代码、效果对比及纯Python解决方案:
问题代码
import xml.etree.ElementTree as Et parser = Et.XMLParser(strip_cdata=False) xml_tree = Et.parse(destination_xml_file_full_path, parser=parser) xml_tree_root_element = xml_tree.getroot() string_element = Et.Element('string') string_element.set('name', string_id) string_element.text = '' xml_tree_root_element.append(string_element) xml_tree.write(destination_xml_file_full_path, encoding='UTF-8', xml_declaration=False, pretty_print=True)
预期格式
<resources> <string name="cbp_payment_successful">Payment Successful</string> ... <string name="string id"></string> </resources>
实际错误格式
<resources> <string name="cbp_payment_successful">Payment Successful</string> ... <string name="string id"></string></resources>
解决方案1:手动控制元素的缩进与换行
ElementTree的pretty_print对空文本元素的格式处理存在缺陷,可通过设置元素的tail属性来修正格式:
import xml.etree.ElementTree as Et parser = Et.XMLParser(strip_cdata=False) xml_tree = Et.parse(destination_xml_file_full_path, parser=parser) root = xml_tree.getroot() new_string = Et.Element('string') new_string.set('name', string_id) new_string.text = '' # 定义缩进格式(匹配现有XML的4空格缩进) indent = ' ' # 设置新元素的尾文本,确保</resources>前有换行 new_string.tail = '\n' # 调整最后一个子元素的尾文本,保证新元素有正确缩进 if root: last_child = root[-1] # 确保最后一个原有元素的尾文本是换行+缩进 if not (last_child.tail and last_child.tail.endswith(f'\n{indent}')): last_child.tail = f'\n{indent}' root.append(new_string) xml_tree.write(destination_xml_file_full_path, encoding='UTF-8', xml_declaration=False, pretty_print=True)
解决方案2:插入到最后一个元素之后
找到<resources>下的最后一个<string>元素,用insert方法插入新元素,同步调整缩进:
import xml.etree.ElementTree as Et parser = Et.XMLParser(strip_cdata=False) xml_tree = Et.parse(destination_xml_file_full_path, parser=parser) root = xml_tree.getroot() new_string = Et.Element('string') new_string.set('name', string_id) new_string.text = '' indent = ' ' new_string.tail = '\n' # 查找所有<string>元素 string_elements = root.findall('string') if string_elements: last_string_pos = root.index(string_elements[-1]) # 插入到最后一个<string>的下一位 root.insert(last_string_pos + 1, new_string) # 给最后一个原有<string>设置正确的尾文本 string_elements[-1].tail = f'\n{indent}' else: # 若没有<string>元素,直接追加并设置格式 root.append(new_string) xml_tree.write(destination_xml_file_full_path, encoding='UTF-8', xml_declaration=False, pretty_print=True)
方案3:借助xml.dom.minidom实现完美格式化
如果对格式要求较高,可结合xml.dom.minidom进行二次格式化,规避ElementTree的pretty_print局限:
import xml.etree.ElementTree as Et import xml.dom.minidom as minidom parser = Et.XMLParser(strip_cdata=False) xml_tree = Et.parse(destination_xml_file_full_path, parser=parser) root = xml_tree.getroot() new_string = Et.Element('string') new_string.set('name', string_id) new_string.text = '' root.append(new_string) # 转换为minidom对象并格式化 rough_xml = Et.tostring(root, 'utf-8') dom = minidom.parseString(rough_xml) formatted_xml = dom.toprettyxml(indent=' ', encoding='UTF-8').decode('utf-8') # 移除多余空行(可选) formatted_xml = '\n'.join(line for line in formatted_xml.split('\n') if line.strip()) + '\n' # 写入文件 with open(destination_xml_file_full_path, 'w', encoding='UTF-8') as f: f.write(formatted_xml)
内容的提问来源于stack exchange,提问作者Francis Bacon
相关产品推荐
相关产品推荐

