ElementTree's Element substitution in Python 3

A

André

I have a function to replace the content of an ElementTree Element by
that of another one which works using Python 2 but not with Python 3.
I get an assertion error. The function is as follows:

def replace_element(elem, replacement):
'''replace the content of an ElementTree Element by that of
another
one.
'''
elem.clear()
elem.text = replacement.text
elem.tail = replacement.tail
elem.tag = replacement.tag
elem.attrib = replacement.attrib
elem[:] = replacement[:]

The last line is problematic. For example, if I do the following
program with Python2.5
###
from xml.etree import ElementTree as et

a = et.Element('a')
b = et.SubElement(a, 'b')
c = et.Element('c')

a[:] = c[:]
###
nothing of note happens - however, doing the same with Python 3.1, I
get the following traceback:

Traceback (most recent call last):
File "test.py", line 7, in <module>
a[:] = c[:]
File "/usr/local/py3.1/lib/python3.1/xml/etree/ElementTree.py", line
210, in __setitem__
assert iselement(element)
AssertionError

======
I would gladly welcome any suggestion for writing a replace_element()
function that works with Python 3.1

André
 
A

André

Sorry for replying to myself ... the following seems to be a working
solution to my original problem.
I have a function to replace the content of an ElementTree Element by
that of another one which works using Python 2 but not with Python 3.
I get an assertion error.  The function is as follows:

def replace_element(elem, replacement):
    '''replace the content of an ElementTree Element by that of
another
       one.
    '''
    elem.clear()
    elem.text = replacement.text
    elem.tail = replacement.tail
    elem.tag = replacement.tag
    elem.attrib = replacement.attrib
    elem[:] = replacement[:]

Use instead:

def replace_element(elem, replacement):
'''replace the content of an ElementTree Element by that of
another
one.
'''
elem.clear()
elem.text = replacement.text
elem.tail = replacement.tail
elem.tag = replacement.tag
elem.attrib = replacement.attrib
try:
elem[:] = replacement[:] # works with Python 2.x (fast) but
not 3.x
except AssertionError:
del elem[:]
for child in replacement:
elem.append(child)


André
 
P

Piet van Oostrum

André said:
A> I have a function to replace the content of an ElementTree Element by
A> that of another one which works using Python 2 but not with Python 3.
A> I get an assertion error. The function is as follows:
A> def replace_element(elem, replacement):
A> '''replace the content of an ElementTree Element by that of
A> another
A> one.
A> '''
A> elem.clear()
A> elem.text = replacement.text
A> elem.tail = replacement.tail
A> elem.tag = replacement.tag
A> elem.attrib = replacement.attrib
A> elem[:] = replacement[:]
A> The last line is problematic. For example, if I do the following
A> program with Python2.5
A> ###
A> from xml.etree import ElementTree as et
A> a = et.Element('a')
A> b = et.SubElement(a, 'b')
A> c = et.Element('c')
A> a[:] = c[:]
A> ###
A> nothing of note happens - however, doing the same with Python 3.1, I
A> get the following traceback:
A> Traceback (most recent call last):
A> File "test.py", line 7, in <module>
A> a[:] = c[:]
A> File "/usr/local/py3.1/lib/python3.1/xml/etree/ElementTree.py", line
A> 210, in __setitem__
A> assert iselement(element)
A> AssertionError

This is a Python bug. Please report it. The problem is that in Python 3
slice assignments are done with __setitem__ rather than __setslice__ but
ElementTree has not been adapted to that.
 
T

Terry Reedy

André said:
I have a function to replace the content of an ElementTree Element by
that of another one which works using Python 2 but not with Python 3.
I get an assertion error. The function is as follows:

def replace_element(elem, replacement):
'''replace the content of an ElementTree Element by that of
another
one.
'''
elem.clear()
elem.text = replacement.text
elem.tail = replacement.tail
elem.tag = replacement.tag
elem.attrib = replacement.attrib
elem[:] = replacement[:]

The last line is problematic. For example, if I do the following
program with Python2.5
###
from xml.etree import ElementTree as et

a = et.Element('a')
b = et.SubElement(a, 'b')
c = et.Element('c')

a[:] = c[:]
###
nothing of note happens - however, doing the same with Python 3.1, I
get the following traceback:

Traceback (most recent call last):
File "test.py", line 7, in <module>
a[:] = c[:]
File "/usr/local/py3.1/lib/python3.1/xml/etree/ElementTree.py", line
210, in __setitem__
assert iselement(element)
AssertionError

======
I would gladly welcome any suggestion for writing a replace_element()
function that works with Python 3.1

My guess is that you found a subtle bug in the 3.1 version of
ElementTree, perhap a result of conversion. I would take a look at the
noted line 210 to see whether it is 'a' or 'c' that is not passing as an
element. Assuming that it is 'c', I would look at __getitem__ to see why
not. Is [:] special-cased? Compare the codes for 2.5 and 3.1. Assuming
it still looks like a bug, report it on the tracker using your minimal
example, leaving out your function.

tjr
 
A

André

A> I have a function to replace the content of an ElementTree Element by
A> that of another one which works using Python 2 but not with Python 3.
A> I get an assertion error.
[SNIP]
A> Traceback (most recent call last):
A>   File "test.py", line 7, in <module>
A>     a[:] = c[:]
A>   File "/usr/local/py3.1/lib/python3.1/xml/etree/ElementTree.py", line
A> 210, in __setitem__
A>     assert iselement(element)
A> AssertionError

This is a Python bug. Please report it.
Done.

The problem is that in Python 3
slice assignments are done with __setitem__ rather than __setslice__ but
ElementTree has not been adapted to that.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top