lxml:向父元素添加多个混合内容(文本+元素)子节点

lxml: adding multiple mixed content (text + elements) child nodes to a parent element

使用 lxml.etree,我正在尝试构建一个 XML 文档,其中一些元素可能具有以下形式:

<foo>
  There is some text here
  <bar>and then a nested child element</bar>
  And then some more text
</foo>

我不知道有多少个子节点以及其中哪些是文本节点还是元素。这是通过遍历输入列表并根据列表中每个项目的类型来构建的,决定我是要附加文本节点还是元素。

例如:

parent = etree.Element('foo')
for item in input_data:
    if isinstance(item, str): 
       # Append a text node (???)
       pass
    else:
       parent.append(etree.Element(item['type'], item['text']))

显然设置 .text 不会像我想要的那样混合内容。我知道 lxml.etree 没有我可以附加的“文本节点元素”,我可以使用 .tail 将文本附加到最后一个子元素。然而,为此使用 .tail 似乎非常麻烦,因为我必须跟踪最后一个元素,并检查我是否需要调用 append() 来添加新元素或 .text 来设置第一个文本子节点或在最后一个项目上使用 .tail 以在其后设置一些文本。

lxml 中是否有更简洁的方法将混合内容附加到父元素?

一种方法是使用生成器 API,例如

from lxml import etree as ET
from lxml.builder import E

foo = E.foo(*[item if isinstance(item, str) else E(item['type'], item['text']) for item in ['There is some text here', { 'type' : 'bar', 'text' : 'and then a nested child element'}, 'And then some more text']])

然后 ET.tostring(foo) 给出:b'<foo>There is some text here<bar>and then a nested child element</bar>And then some more text</foo>'.

当然,鉴于您的 input_datafoo 的构造将简单地读取

foo = E.foo(*[item if isinstance(item, str) else E(item['type'], item['text']) for item in input_data])