英文:
Get XPath to attribute
问题
我想获取特定xml元素树中特定属性的实际XPath表达式,使用lxml。
假设以下XML树。
XPath表达式"//@*[local-name() = "attrib_name"]"会产生['hello_world'],这是相关属性的值,而"//@*[local-name() = "attrib_name"]/.."会得到bar元素,这一层级太高了,我需要xpath表达式指向特定的属性节点本身,而不是它的父xml节点,我想生成的是'/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']
作为附加功能,这也适用于命名空间。
英文:
I want to get the actual XPath expression to an attribute node for a specific attribute in an xml element tree (using lxml).
Suppose the following XML tree.
<foo>
<bar attrib_name="hello_world"/>
</foo>
The XPath expression "//@*[local-name() = "attrib_name"]" produces ['hello_world'] which is the values of concerned attributes, and "//@*[local-name() = "attrib_name"]/.." gets me the bar element, which is one level too high, I need the xpath expression to the specific attribute node itself, not its parent xml node, that is having the string 'attrib_name' I want to generate '/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']
As an add-on this should work with namespaces too.
答案1
得分: 2
如果您移除 /..,然后您将获得 _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']
英文:
If you remove the /.. then you will get the _ElementUnicodeResult
This will allow you to append the attribute name to the 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']
Trying to apply that to namespaces will result in the namespace added to the xpath (which may not be what you want):
>>> 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']
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论