【问题标题】:Access the processing-instructions before/after a root element with lxml使用 lxml 在根元素之前/之后访问处理指令
【发布时间】:2019-11-26 14:57:37
【问题描述】:

使用lxml,如何访问/迭代位于根打开标记之前或根关闭标记之后的处理指令?

我已经尝试过了,但是根据文档,它只在根元素内迭代:

import io

from lxml import etree

content = """\
<?before1?>
<?before2?>
<root>text</root>
<?after1?>
<?after2?>
"""

source = etree.parse(io.StringIO(content))

print(etree.tostring(source, encoding="unicode"))
# -> <?before1?><?before2?><root>text</root><?after1?><?after2?>

for node in source.iter():
    print(type(node))
# -> <class 'lxml.etree._Element'>

我唯一的解决方案是用虚拟元素包装 XML:

dummy_content = "<dummy>{}</dummy>".format(etree.tostring(source, encoding="unicode"))
dummy = etree.parse((io.StringIO(dummy_content)))

for node in dummy.iter():
    print(type(node))
# -> <class 'lxml.etree._Element'>
#    <class 'lxml.etree._ProcessingInstruction'>
#    <class 'lxml.etree._ProcessingInstruction'>
#    <class 'lxml.etree._Element'>
#    <class 'lxml.etree._ProcessingInstruction'>
#    <class 'lxml.etree._ProcessingInstruction'>

有没有更好的解决方案?

【问题讨论】:

  • 我不知道为什么会这样,但仅供参考,如果你先from lxml.html import fromstring 然后source = fromstring(content),你的for 循环可以访问根节点以及之后的两个处理指令,但不能之前的两个……
  • 你当然是对的@JackFleeting,但我不想使用 HTML 解析器。我真的很想使用 XML。
  • 我意识到 - 我只是想知道为什么解析器会区分“之前”和“之后”。这是违反直觉的(至少对我而言)。

标签: python lxml processing-instruction


【解决方案1】:

您可以在根元素上使用getprevious()getnext() 方法。

before2 = source.getroot().getprevious()
before1 = before2.getprevious()

after1 = source.getroot().getnext()
after2 = after1.getnext()

https://lxml.de/api/lxml.etree._Element-class.html


也可以使用 XPath(在 ElementTreeElement 实例上):

before = source.xpath("preceding-sibling::node()")  # List of two PIs
after = source.xpath("following-sibling::node()")

【讨论】:

  • 聪明而简单。我错过了文档中的那些方法,在 _ElementTree 而不是 _Element 中搜索。谢谢。
  • 通过使用 xpath 的解决方案,PI 按文档顺序排序,这对我来说更好。好!
猜你喜欢
  • 1970-01-01
  • 2020-05-29
  • 2017-12-26
  • 1970-01-01
  • 2011-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-20
相关资源
最近更新 更多