[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