Получить XPath для атрибута - PullRequest
0 голосов
/ 06 января 2020

Я хочу получить фактическое выражение XPath в узел атрибута для указанного атрибута c в дереве элементов xml (с использованием l xml).

Предположим, следующее дерево XML .

<foo>
  <bar attrib_name="hello_world"/>
</foo>

Выражение XPath "// @ * [local-name () =" attrib_name "]" создает ['hello_world'], который является значением соответствующих атрибутов, и "// @ * [local-name () = "attrib_name"] / .. "возвращает мне элемент bar, который находится на один уровень выше, мне нужно выражение xpath для самого узла атрибута c, а не его родительского узла xml , в которой есть строка 'attrib_name', которую я хочу сгенерировать'/foo/bar/@attrib_name'.

from lxml import etree
from io import StringIO

f = StringIO('<foo><bar attrib_name="hello_world"></bar></foo>')
tree = etree.parse(f)

print(tree.xpath('//@*[local-name() = "attrib_name"]'))
# --> ['hello_world']
print([tree.getpath(el) for el in tree.xpath('//@*[local-name() = "attrib_name"]/..')])
# --> ['/foo/bar']

В качестве дополнения это должно работать и с пространствами имен.

1 Ответ

2 голосов
/ 06 января 2020

Если вы удалите / .., тогда вы получите _ElementUnicodeResult

Это позволит вам добавить имя атрибута в xpath:

>>> print(['%s/@%s' % (tree.getpath(attrib_result.getparent()), attrib_result.attrname) for attrib_result in tree.xpath('//@*[local-name() = "attrib_name"]')])
['/foo/bar/@attrib_name']

Попытка применить это к пространствам имен приведет к добавлению пространства имен в xpath (что может быть не тем, что вы хотите):

>>> tree = etree.parse(StringIO('<foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><bar xsi:attrib_name="hello_world"></bar></foo>'))
>>> print(['%s/@%s' % (tree.getpath(attrib_result.getparent()), attrib_result.attrname) for attrib_result in tree.xpath('//@*[local-name() = "attrib_name"]')])
['/foo/bar/@{http://www.w3.org/2001/XMLSchema-instance}attrib_name']
...