如何使用 ElementMaker 的布尔条件漂亮地打印 XML

How to pretty-print XML created using boolean condition with ElementMaker

当我不想生成 E.note() 时,如何避免格式错误?

现在,当条件为 True 时一切正常,但当条件为 False 时,它会将 space 引入 xml,格式错误。

一个解决方案是使用 etree.Subelement(xml, "note"),但我想避免这种情况,因为它迫使我继续对所有后续元素使用 etree。

Python 3
lxml: 4.5.2

from lxml.builder import ElementMaker 
import lxml.etree as et

E = ElementMaker()

condition = False

xml = E.topic(
    E.first("first"),
    E.note("Text I want sometimes") if condition else "",
    E.third("third")
)

with open("result.xml", "wb") as f:
    f.write(et.tostring(xml.getroottree(), 
                          pretty_print=True,
                          xml_declaration=True, 
                          encoding='utf-8', 
                          standalone=False))

我得到的结果:

<?xml version='1.0' encoding='utf-8' standalone='no'?>
<topic><first>first</first><third>third</third></topic>

但我想要的结果是:

<?xml version='1.0' encoding='utf-8' standalone='no'?>
<topic>
  <first>first</first>
  <third>third</third>
</topic>

我认为你不能用 ... if condition else ... 做到这一点,你必须以更传统的方式做到这一点

xml = E.topic()

xml.append(E.first("first"))

if condition:
    xml.append(E.note("Text I want sometimes"))

xml.append(E.third("third"))

最终

xml = E.topic(
    E.first("first"),
    E.third("third")
)

if condition:
    xml.insert(1, E.note('Text I want sometimes'))

完整的工作示例

from lxml.builder import E  # ElementMaker 
import lxml.etree as et

#E = ElementMaker()

# --- functions ---

def display(xml):
    print(et.tostring(xml.getroottree(), 
                          pretty_print=True,
                          xml_declaration=True, 
                          encoding='utf-8', 
                          standalone=False).decode())

def example_0():
    xml = E.topic(
        E.first("first"),
        E.note("Text I want sometimes") if condition else "",
        E.third("third")
    )

    display(xml)
    
def example_1():
    xml = E.topic()

    xml.append(E.first("first"))

    if condition:
        xml.append(E.note("Text I want sometimes"))

    xml.append(E.third("third"))

    display(xml)

def example_2():
    xml = E.topic(
        E.first("first"),
        E.third("third")
    )

    if condition:
        xml.insert(1, E.note('Text I want sometimes'))

    display(xml)
    
# --- main ---

condition = False

example_0()
example_1()
example_2()

如果生成的 XML 被解析,漂亮的打印工作。因此,一种解决方法是在写入输出文件的代码之前添加一行代码:

xml = et.fromstring(et.tostring(xml))

如果你愿意,你也可以简化写入输出文件的代码:

xml.getroottree().write("result.xml",
                        pretty_print=True,
                        xml_declaration=True, 
                        encoding='utf-8', 
                        standalone=False)