python - 是否可以使用 lxml 将文本视为 xml 元素?
问题描述
我想过滤元素树以删除重复的元素条目。简而言之,我正在尝试将 xml 输出清理为可以由其他工具解析的内容。
例如
<p>
<p>
Text node 1
<ul>
<li>asdasd</li>
</ul>
<p>
Text node 2 <span>Som text</span>
</p>
Text node 3
</p>
<p>Text node 4</p>
</p>
将转换为:
<p>
Text node 1
<ul>
<li>asdasd</li>
</ul>
</p>
<p>Text node 2 <span>Som text</span></p>
<p>Text node 3</p>
<p>Text node 4</p>
在 lxml 中,getchildren
似乎只返回 xml 元素。因此,当我在p
包含ul
. 它会像想的那样返回一个列表[ul, p]
,我想要一个包含以下内容的列表:
[Text, Ul, P, Text]
所以我可以轻松地在树上走下或上走,以减少多余的元素。
解决方案
lxml 的文档表明它们没有文本节点,并且该文本将是通过 .text 访问的该元素的一部分,或者将是通过 .tail 访问的结束标记的尾部。
<html><body>Hello<br/>World</body></html>
在这里,
<br/>
标签被文本包围。这通常称为文档样式或混合内容 XML。元素通过其 tail 属性支持这一点。它包含直接跟随元素的文本,直到 XML 树中的下一个元素。.text 和 .tail 这两个属性足以表示 XML 文档中的任何文本内容。这样,除了 Element 类之外,ElementTree API 不需要任何特殊的文本节点,这些节点往往会经常妨碍(正如您可能从经典的 DOM API 中知道的那样)。
我不能说下面的内容很漂亮或完全符合您的要求,但至少可能会让您走得更近。
from lxml import etree
tree = etree.parse("test.dat").getroot()
main_p = tree[0]
elements = [main_p.text]
for child in main_p:
elements.append(child.tag)
elements.append(child.tail)
print(f"TAG: {child.tag} has tail: #{child.tail}#")
print(elements)
输出
TAG: ul has tail: #
#
TAG: p has tail: #
Text node 3
#
['\n Text node 1\n ', 'ul', '\n ', 'p', '\n Text node 3\n ']
所以“Text node 1”就是主p的文本。但是“文本节点 3”,而它在主 p 内部实际上是内部 p 的尾标记。
除此之外,您可以迭代主元素,如果子元素是 ap 标签,您可以将其移出主 p 并将其添加到根标签中。下面再次只是一个例子。
from lxml import etree
tree = etree.parse("test.dat").getroot()
main_p = tree[0]
elements = [main_p.text]
for child in main_p[::-1]:
if child.tag == 'p':
tree.insert(tree.index(main_p) + 1, child)
new_p = etree.Element('p')
new_p.text = child.tail
tree.insert(tree.index(child)+1, new_p)
child.tail = "\n"
tree.tag = 'something_else'
print(etree.tostring(tree, pretty_print=True).decode('utf-8'))
输出
<something_else>
<p>
Text node 1
<ul>
<li>asdasd</li>
</ul>
</p>
<p>
Text node 2
<span>Som text</span>
</p>
<p>Text node 3</p>
<p>Text node 4</p>
</something_else>
推荐阅读
- android - 在 AndroidX 中膨胀 SlidingPaneLayout 类时出错
- ruby-on-rails - 将 Rails 5.2 升级到 6.0.0 后内存泄漏
- android - 如何修复 Java (android) 中的“无法找到空闲端口”错误
- python - 从 python timeit 函数保存返回值
- wordpress - 主题幻灯片错误,解析错误 wordpress
- android - 让 TalkBack 以编程方式读取按钮内容说明
- python-3.x - 将文本文件打印为两个单独的列表
- javascript - Microsoft Edge 中的 beforeunload 未触发
- jenkins - Jenkins Build Pipeline View-用户缺少作业/创建权限
- python - 尝试函数调用的变化,直到完成而不抛出异常