更多pythonic方式从标记数据中选择多个元素类型

时间:2012-07-29 21:07:49

标签: python lxml

我有一些使用lxml处理的标记数据。当我打开文件时,如果我有三种类型的元素中的一种或多种(我可以有一个,两个或三个不同的元素以及我拥有的任何类型的多个实例),那么在打开文件之前我不知道。

我需要一些关于元素的子标记中包含的元素的信息

<element_type_1>
        <name>joe smith</name>
</element_type_1>
<element_type_2>
        <name>mary smith</name>
</element_type_2>
<element_type_3>
        <name>patrick smith</name>
</element_type_3>

所以在这种情况下,我有三种类型,但每种类型只有一种,但是任何类型都可能有一些任意大量的数字。

我在函数中使用cssselect 3次获取元素

def get_types(myTree):
    type_dict=defaultdict(list)
    type_dict['type_1']=myTree.cssselect('element_type_1')
    type_dict['type_2']=myTree.cssselect('element_type_2')
    type_dict['type_3']=myTree.cssselect('element_type_3')
    ret type_dict

这似乎过于多余

我是否遗漏了一些可以清理它的东西?

仅供参考我这样做是因为对于每种类型我必须匹配来自相关文档的其他数据

早期的答案表明我需要澄清一点 - 我想避免三次穿过树

4 个答案:

答案 0 :(得分:5)

你可以这样做:

for i in range(1, 4):
    type_dict['type_%d' % i] = myTree.cssselect('element_type_%d' % i)

答案 1 :(得分:1)

取决于你是否知道它的外观。使用变量作为键可能是一个简单的事情,可以帮助您稍微改进它。

def get_types(myTree):
    type_dict=defaultdict(list)
    for i in range(1,4):
      x = 'type_%d' % i
      y = 'element_type_%d' % i
      type_dict[x] = myTree.csselect(y)
    return type_dict

答案 2 :(得分:1)

如果您事先不知道他们的名字,我不知道您如何识别这些“类型”。他们是否遵循您可以搜索的固定模式?

例如,您可以执行以下操作:

d = {}
typeelements = "*[starts-with(local-name(), 'element_type_')]"
for e in myTree.xpath(typeelements)
    typename = e.tag.split('_',1)[1]
    d[typename] = e

或者更简洁:

d = {e.tag.split('_',1)[1]:e for e in myTree.xpath(typeelements)}

或者,您可以根据元素本身的某些条件选择元素。在你的例子中,他们都有name个孩子,所以你可以使用这样的路径:

typeelements = '*[name]'

或者您可以结合两个要求:

typeelements = "*[starts-with(name(), 'element_type_')][name]"

答案 3 :(得分:0)

或者您可以迭代一组已知标记以查找匹配元素。找到元素后,将(标记,值)添加到dict。应该工作正常。