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