You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用lxml的Element实现XML标签属性换行打印?

Answer

Great question! I’ve run into this exact issue with lxml before—its built-in pretty_print is great for indenting elements, but it doesn’t have a native setting to put each attribute on its own line. Let’s break down your options:

1. Use a Third-Party Library (Quickest Solution)

There are a few Python libraries designed specifically for custom XML formatting that can handle attribute-per-line output out of the box. My go-to is xmlformatter:

First, install it via pip:

pip install xmlformatter

Then use it to post-process your lxml output:

import xmlformatter
from lxml import etree

# Create your element as usual
elem = etree.Element("module", name="A", description="abc", type="xyz")
etree.SubElement(elem, "container")

# Convert lxml element to raw XML string
raw_xml = etree.tostring(elem, encoding="unicode")

# Configure formatter to put one attribute per line
formatter = xmlformatter.Formatter(indent="  ", attributes_per_line=1)
formatted_xml = formatter.format_string(raw_xml)

print(formatted_xml)

This will output exactly what you want:

<module
  name="A"
  description="abc"
  type="xyz">
  <container/>
</module>

Another option is the xmlformat command-line tool (which also has a Python API), but xmlformatter is more straightforward for programmatic use.

2. Manual Serialization (No Extra Dependencies)

If you don’t want to add a third-party library, you can write a simple recursive function to serialize the element yourself, with full control over attribute formatting:

from lxml import etree

def format_xml_with_attr_newlines(elem, indent="  ", current_level=0):
    # Start the opening tag
    output = indent * current_level + f"<{elem.tag}"
    
    # Add each attribute on a new line, indented one level deeper
    for attr_name, attr_value in elem.attrib.items():
        output += f"\n{indent * (current_level + 1)}{attr_name}=\"{attr_value}\""
    
    # Handle child elements or self-closing tag
    children = list(elem)
    if children:
        output += ">\n"
        # Recursively format each child
        for child in children:
            output += format_xml_with_attr_newlines(child, indent, current_level + 1)
        # Add closing tag
        output += indent * current_level + f"</{elem.tag}>\n"
    else:
        # Self-closing tag
        output += "/>\n"
    
    return output

# Test it out
elem = etree.Element("module", name="A", description="abc", type="xyz")
etree.SubElement(elem, "container")
print(format_xml_with_attr_newlines(elem).strip())

This function will produce the same formatted output as the library approach, with no external dependencies.

Key Note About lxml

Just to confirm: lxml’s core etree.tostring() method doesn’t support this attribute formatting natively. The pretty_print flag only handles element indentation, not attribute line breaks—so you’ll need one of the above workarounds.

内容的提问来源于stack exchange,提问作者arpp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 10:09:31