Как я могу избежать неправильного форматирования, если я не хочу генерировать E.note()?
Сейчас все это работает, когда условие имеет значение True, но когда оно равно False, в xml вводится пробел, что приводит к плохому форматированию.
Одним из решений является использование etree.Subelement(xml, "note"), но я хотел избежать этого, потому что это вынуждает меня продолжать использовать etree для всех последующих элементов.
Питон 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()
Спасибо. Мне очень нравится, что вы показали как версию для добавления, так и версию для вставки. Я приму этот ответ.
Я также думал о том, чтобы reduce()
или [ ... for ... in ... if ...]
удалить ""
перед форматированием, но это не сработало.
Если сгенерированный XML анализируется, красивая печать работает. Таким образом, обходным путем является добавление одной строки кода непосредственно перед кодом, который записывает выходной файл:
xml = et.fromstring(et.tostring(xml))
Если хотите, вы также можете упростить код, записывающий выходной файл:
xml.getroottree().write("result.xml",
pretty_print=True,
xml_declaration=True,
encoding='utf-8',
standalone=False)
Я думаю, вам придется забыть
... if condition else ...
и использоватьsubelement()
илиif condition: xml.append(E.note("Text I want sometimes"))