Python生成XML文件:如何将元素属性多行显示
解决XML属性单独换行的可行方案
方案1:使用lxml库定制格式化输出
lxml的etree模块支持更灵活的XML格式化,能实现每个属性单独换行的需求。步骤如下:
- 安装lxml(未安装时执行):
pip install lxml
- 手动构建XML元素并自定义格式化输出:
from lxml import etree # 创建根元素 root = etree.Element("EVFM") # 添加子元素及属性 child = etree.SubElement(root, "SampleElement") child.set("attr1", "value1") child.set("attr2", "value2") child.set("attr3", "value3") # 自定义格式化函数:每个属性单独换行,缩进为4个空格 def format_element(elem, indent=0): indent_str = " " * indent attr_str = "" if elem.attrib: # 每个属性单独一行,缩进比元素多4格 attr_lines = [f'\n{" "*(indent+4)}{k}="{v}"' for k, v in elem.attrib.items()] attr_str = "".join(attr_lines) # 拼接开始标签 result = f"{indent_str}<{elem.tag}{attr_str}>" # 处理子元素 if len(elem) > 0: result += "\n" for child in elem: result += format_element(child, indent + 4) result += f"{indent_str}</{elem.tag}>\n" else: # 自闭合标签 result += "/>\n" return result # 生成XML字符串并写入文件 xml_str = format_element(root) with open("output.xml", "w", encoding="utf-8") as f: f.write(xml_str)
方案2:对xmltodict输出的XML字符串做后处理
如果不想更换现有库,可以先让xmltodict生成基础XML,再用正则表达式替换属性的空格为换行+缩进,实现每行一个属性:
import xmltodict import re # 你的原始字典数据 data = { "EVFM": { "SampleElement": { "@attr1": "value1", "@attr2": "value2", "@attr3": "value3" } } } # 用xmltodict生成初始XML字符串 xml_str = xmltodict.unparse(data, pretty=True, indent=" ") # 正则替换:将元素标签后的属性列表拆分为每行一个 pattern = r'<(\w+)\s+([^>]+)>' def replace_attrs(match): tag = match.group(1) attrs = match.group(2) # 拆分单个属性 attr_list = re.findall(r'(\w+="[^"]+")', attrs) # 拼接成换行缩进格式 indented_attrs = '\n ' + '\n '.join(attr_list) return f'<{tag}{indented_attrs}>' # 执行替换并写入文件 formatted_xml = re.sub(pattern, replace_attrs, xml_str) with open("output.xml", "w", encoding="utf-8") as f: f.write(formatted_xml)
注意:该方法依赖XML的标准格式(属性间用空格分隔),若属性值含特殊字符,需微调正则表达式。
方案3:ElementTree自定义输出函数
ElementTree默认的格式化不支持属性换行,但可以自行编写递归函数遍历元素,手动生成符合要求的XML:
import xml.etree.ElementTree as ET def pretty_print_with_attr_newlines(elem, indent=0, indent_str=" "): result = [] # 拼接开始标签与属性 start_tag = f"{indent_str*indent}<{elem.tag}" if elem.attrib: # 每个属性单独一行,缩进+1 for key, value in elem.attrib.items(): start_tag += f"\n{indent_str*(indent+1)}{key}=\"{value}\"" # 判断是否有子元素 if len(elem) > 0: start_tag += ">" result.append(start_tag) # 递归处理子元素 for child in elem: result.append(pretty_print_with_attr_newlines(child, indent+1)) # 拼接闭合标签 result.append(f"{indent_str*indent}</{elem.tag}>") else: # 自闭合标签 start_tag += "/>" result.append(start_tag) return "\n".join(result) # 构建元素示例 root = ET.Element("EVFM") child = ET.SubElement(root, "SampleElement", attr1="value1", attr2="value2", attr3="value3") # 生成格式化XML并写入文件 xml_str = pretty_print_with_attr_newlines(root) with open("output.xml", "w", encoding="utf-8") as f: f.write(xml_str)
内容的提问来源于stack exchange,提问作者Luca Pizzuto
相关产品推荐
相关产品推荐

