Предположим, у меня есть следующий пример XML
<a>some <b>text</b> example</a>
Использование l xml позвольте мне запросить текстовые узлы несколькими различными способами:
>>> xml.xpath("//text()")
['some ', 'text', ' example']
>>> xml.xpath("//a/text()")
['some ', ' example']
>>> xml.xpath("//b/text()")
['text']
Пока все хорошо (все это хорошо напечатанные lxml.etree._ElementUnicodeResult
объекты). Но теперь я хотел бы перейти к родительским узлам этих текстовых узлов:
>>> xml.xpath("//text()/parent::*")
[<Element a at 0x10aa383c0>, <Element b at 0x10aa38410>]
>>> xml.xpath("//a/text()/parent::*")
[<Element a at 0x10aa383c0>]
>>> xml.xpath("//b/text()/parent::*")
[<Element b at 0x10aa38410>]
>>> xml.xpath("//*/text()/parent::*")
[<Element a at 0x10aa383c0>, <Element b at 0x10aa38410>]
Как обычные операции XPath, они работают, и я получаю наборы результатов родительских узлов обратно. Но я бы хотел перебрать текстовые узлы и , а затем получить их соответствующих родителей:
>>> for e in xml.xpath("//text()"):
... print(e.xpath("./parent::*"))
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
AttributeError: 'lxml.etree._ElementUnicodeResult' object has no attribute 'xpath'
Хм, ладно, похоже, это деталь реализации l xml или даже базовый libxml2 ? Но getparent()
на помощь ... или?
>>> for e in xml.xpath("//text()"):
... print(f"'{e}'", e.getparent())
...
'some ' <Element a at 0x10aa383c0>
'text' <Element b at 0x10aa38410>
' example' <Element b at 0x10aa38410>
И вот что меня озадачивает: хотя во время поиска сверху вниз родительские узлы имели смысл для всех текстовых узлов, если снизу вверх, то они разные: текстовый узел ' example'
имеет родителя a
или b
, в зависимости от того, как я запрашиваю его родителя.
Я что-то упустил или это ошибка ( возможно, из-за .text
и .tail
узлов элементов ?
Добавление
После рассмотрения соответствующих l xml исходный код Я думаю, что внутреннее _elementStringResultFactory
необходимо исправить, см. Ошибку 1859435 . Между тем, следующий обходной путь дает ожидаемые результаты:
>>> for e in xml.xpath("//text()"):
... p = e.getparent()
... print(f"'{e}'", p.getparent() if e.is_tail else p)
...
'some ' <Element a at 0x110799460>
'text' <Element b at 0x1100ad230>
' example' <Element a at 0x110799460>