使用Python / lxml和XPath检索属性名称和值

凯文·吉尔

我将XPath与Python lxml(Python 2)结合使用。我对数据进行了两次遍历,一次遍历选择了感兴趣的记录,一次遍历从数据中提取值。这是代码类型的示例。

from lxml import etree

xml = """
  <records>
    <row id="1" height="160" weight="80" />
    <row id="2" weight="70" />
    <row id="3" height="140" />
  </records>
"""

parsed = etree.fromstring(xml)
nodes = parsed.xpath('/records/row')
for node in nodes:
    print node.xpath("@id|@height|@weight")

当我运行此脚本时,输出为:

['1', '160', '80']
['2', '70']
['3', '140']

从结果中可以看到,缺少一个属性的地方,其他属性的位置发生了变化,因此我无法在第2行和第3行中分辨出这是身高还是体重。

有没有办法获取从etree / lxml返回的属性的名称?理想情况下,我应该以以下格式查看结果:

[('@id', '1'), ('@height', '160'), ('@weight', '80')]

我认识到我可以使用elementtree和Python解决此特定情况。但是,我希望使用XPath(以及相对简单的XPath)解决此问题,而不是使用python处理数据。

凯文·吉尔

我不打算使用Python的主张是错误的。我发现lxml / etree实现很容易扩展为可以修改使用XPath DSL。

我注册了功能“ dictify”。我将XPath表达式更改为:

dictify('@id|@height|@weight|weight|height')

新的代码是:

from lxml import etree

xml = """
<records>
    <row id="1" height="160" weight="80" />
    <row id="2" weight="70" ><height>150</height></row>
    <row id="3" height="140" />
</records>
"""

def dictify(context, names):
    node = context.context_node
    rv = []
    rv.append('__dictify_start_marker__')
    names = names.split('|')
    for n in names:
        if n.startswith('@'):
            val =  node.attrib.get(n[1:])
            if val != None:
                rv.append(n)
                rv.append(val)
        else:
            children = node.findall(n)
            for child_node in children:
                rv.append(n)
                rv.append(child_node.text)
    rv.append('__dictify_end_marker__')
    return rv

etree_functions = etree.FunctionNamespace(None)
etree_functions['dictify'] = dictify


parsed = etree.fromstring(xml)
nodes = parsed.xpath('/records/row')
for node in nodes:
    print node.xpath("dictify('@id|@height|@weight|weight|height')")

这将产生以下输出:

['__dictify_start_marker__', '@id', '1', '@height', '160', '@weight', '80', '__dictify_end_marker__']
['__dictify_start_marker__', '@id', '2', '@weight', '70', 'height', '150', '__dictify_end_marker__']
['__dictify_start_marker__', '@id', '3', '@height', '140', '__dictify_end_marker__']

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章