如何获取文本节点的所有者元素?

How to get owner element of a text node?

我有这个数据:

<data>
  <foo>foo text</foo>
  data text
    <bar>
      bar text
      <baz>text</baz>
      <baz>text</baz>
      bar text
    </bar>
   data text
</data>

我需要按顺序获取所有文本值,修改 "baz" 标签内的文本并打印。我的代码是:

text = []
for element in etree.xpath("./*"):
    text.extend(element.xpath("./text()"))
    if element.tag == 'bar':
        text.extend(["baz " + s for s in element.xpath("./baz/text()")])
print '\n'.join([s.strip() for s in text if s.strip()])

输出为:

foo text
bar text
bar text
baz text
baz text

但我需要:

foo text
data text
bar text
baz text
baz text
bar text
data text

如何按顺序获取节点的 text() 而不会丢失 data text 文本?

编辑 我知道 etree.xpath(".//text()") 可以按顺序给我所有文本,但是 我需要修改 baz 标签内的文本。这是一个要点。如何获取 .//text() XPath 的每个元素的标记值?

假设您正在使用 lxml,您可以调用 getparent() 函数来获取文本节点的所有者元素,例如:

import lxml.etree
etree = lxml.etree.fromstring('''
<data>
  <foo>foo text</foo>
  data text
    <bar>
      bar text
      <baz>text</baz>
      <baz>text</baz>
      bar text
    </bar>
   data text
</data>
''')

for text in etree.xpath("//text()[normalize-space()]"):
    parenttag = text.getparent().tag
    print(parenttag, text)

XPath 表达式 //text()[normalize-space()] 仅表示 return 非空 文档中的所有 XML 文本节点。

输出:

('foo', 'foo text')
('foo', '\n  data text\n    ')
('bar', '\n      bar text\n      ')
('baz', 'text')
('baz', 'text')
('baz', '\n      bar text\n    ')
('bar', '\n   data text\n')