Почему l xml не разрешает относительные выражения XPath для всего ElementTree? - PullRequest
2 голосов
/ 24 января 2020

Запуск Python 3.7.4 на Windows, я заметил, что оценка XPath отличается от результатов онлайн-оценщиков, таких как здесь или здесь .

Онлайн-оценщики позволяют вводить относительное выражение, которое будет оцениваться по всему документу. Однако с l xml я не получаю совпадений в дереве элементов, если не сделаю его абсолютным выражением, добавив к нему sla sh.

Python 3.7.4 (tags/v3.7.4:e09359112e, Jul  8 2019, 20:34:20) [MSC v.1916 64 bit (AMD64)] on win32
>>> import lxml.etree
>>> root = lxml.etree.fromstring('''
... <TestRootNode>
...   <person personID="person1">
...     <name>James</name>
...   </person>
...   <person personID="person2">
...     <name>Cathy</name>
...   </person>
... </TestRootNode>''')
>>> tree = root.getroottree()
>>> tree.xpath('/TestRootNode/person')
[<Element person at 0x2ceee1f4e88>, <Element person at 0x2ceee1ff048>]
>>> tree.xpath('string(/TestRootNode/person[1])')
'\n    James\n  '
>>> tree.xpath('TestRootNode/person')
[]
>>> tree.xpath('string(TestRootNode/person[1])')
''

У меня два вопроса:

  1. Кто прав, онлайн-оценщики или l xml? Разрешено ли применять относительное выражение в контексте всего документа?

  2. Если онлайн-оценщики правы: есть ли простой способ заставить l xml вести себя в так же? Простое размещение sla sh в начале строки не будет работать, как вы можете видеть из моего примера с функцией string().

1 Ответ

3 голосов
/ 24 января 2020

Кто прав, онлайн-оценщики или l xml?

Для относительных выражений не совсем ясно, в каком контексте их следует оценивать. Различные инструменты имеют разные предположения.

Онлайн-инструменты, которые вы тестировали, вероятно, оценивают относительные выражения в контексте узла документа (который представляет весь документ). Узел документа имеет в качестве своего единственного дочернего элемента самый внешний элемент документа.

lxml утверждает, что придерживается того же соглашения :

Для ElementTree, метод xpath выполняет глобальный запрос XPath к документу (если абсолютный) или к узлу root (если относительный)

Что не совсем верно, так как root узел - это особый вид узла, отличный от узла элемента, в то время как lxml фактически сравнивается с root элементом (, как указал также Даниэль Хейли ).

>>> root = lxml.etree.fromstring('<root><child/></root>')
>>> root.xpath("child")
[<Element child at 0x10c093fc8>]
...