[lxml-dev] Bug in objectify node[:].index

Christian Zagrodnick cz at gocept.com
Wed May 23 15:27:19 CEST 2007


On 2007-05-23 09:44:25 +0200, jholg at gmx.de said:

> 
>> Hi,
>> 
> 
>> following little script fails at the last assert:
>> 
> 
>> ----------------------------
>> import lxml.objectify
>> 
> 
>> 
> 
>> tree = lxml.objectify.fromstring(
>> """\
>> <root>
>> <a name="car">foo</a>
>> <a name="car">bar</a>
>> <a name="tree">foo</a>
>> <a name="tree">bar</a>
>> </root>
>> """)
>> 
> 
>> trees = tree.findall('//a[@name="tree"]')
>> print trees
>> 
> 
>> foo_tree = trees[0]
>> assert foo_tree.get('name') == 'tree'
>> 
> 
>> parent = foo_tree.getparent()
>> assert parent.tag == 'root'
>> 
> 
>> 
> 
>> node_list = parent[foo_tree.tag]
>> import pdb; pdb.set_trace()
>> foo_index = node_list[:].index(foo_tree)
>> assert foo_index == 3, foo_index  # FAILS: foo_index is 0
>> 
> 
>> ----------------------------
>> 
> 
>> So, fo_index == 0. Which is <a name="car">foo</a>. Apparently the
> 
>> .index only looks at the text or something?!
> 
> Note that you use [].index, not ObjectifiedElement.index, with the
> slice you apply:
> 
>>>> node_list[:].index
> <built-in method index of list object at 0x2dd558>
>>>> parent.index
> <built-in method index of objectify.ObjectifiedElement object at 0x1b28f0>
>>>> node_list[:].index(foo_tree)
> 0
>>>> parent.index(foo_tree)
> 2
>>>> 
> 
> 
> Seems like [].index returns the first list item that compares equal to
> its argument. As StringElements behave much like strings, this is what
> happens here, as the first element in your list also has the element.text
> "foo":
>>>> node_list[:][0] == foo_tree
> True
>>>> node_list[:][1] == foo_tree
> False
>>>> node_list[:][2] == foo_tree
> True
>>>> 
>>>> print foo_tree.text
> foo
>>>> print node_list[:][0].text
> foo
>>>> 
> 
> 
> So I'd rather not say this is a bug...

Oh I see. Actually I was trying to see if they [0] was equal to [2]. In 
my case there were not but I probably did something wrong. And as I 
indeed thought they should be wrong I haven't looked closer.


> 
>> Anyway, all I *actually* want is to remove the nodes found by the
> 
>> xpath. The way you'd think it would be 'normal' doesn't work
> 
>> unfortunately:
>> 
> 
>> 
> 
>> (Pdb) p parent.index(foo_tree)
>> 2
>> (Pdb) del parent[2]
>> *** TypeError: deleting items not supported by root element
>> 
> 
>> This is obviously because of the sort fo strange list/attribute
> 
>> handling (i.e. parent is parent[0])
> 
> It is different from the lxml.etree (ElementTree) API but clearly stated
> in the docs: Indexed access returns siblings (aka "neighbour" elements 
> with  the same name) rather than children, and every ObjectifiedElement 
> has list  behaviour; unindexed access is just a *shortcut* to retrieve 
> the first sib ling.

Yeah. In general I even know that. All I'm saying is that if feels strange.

Thanks by the way :)

-- 
Christian Zagrodnick

gocept gmbh & co. kg  ·  forsterstrasse 29 · 06112 halle/saale
www.gocept.com · fon. +49 345 12298894 · fax. +49 345 12298891





More information about the lxml-dev mailing list