Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > ElementTree and clone element toot

Reply
Thread Tools

ElementTree and clone element toot

 
 
m.banaouas
Guest
Posts: n/a
 
      02-02-2009
Hi all,
Working with the ElementTree module, I looked for clone element function but not
found such tool:

def CloneElment(fromElem, destRoot = None)
fromElem is the element to clone
destRoot is the parent element of the new element ; if None so the new element
will be child of fromElem parent. The clone operation is recursive to make it
process all subtree of the element to clone.

here is my first implementation:

def CloneElement(fromElem, destRoot = None):
if destRoot == None:
fromRoot = ET.ElementTree(fromElem).getroot()
destRoot = fromRoot
destElem = destRoot.makeelement(fromElem.tag, fromElem.attrib)
destRoot.append(destElem)
destElem.text = fromElem.text
for e in fromElem.findall('*'):
CloneElement(e, destElem)
#
this function works fine only if destRoot parameter is defined by the caller
context. The problem is about retreiving parent element: I didn't found any way
to determine the parent element of an element "elem" by asking elem itself!
and ET.ElementTree(fromElem).getroot() is wrong because it returns fromElem
itself, not its parent.

Thanks for any help.
 
Reply With Quote
 
 
 
 
Gerard Flanagan
Guest
Posts: n/a
 
      02-02-2009
m.banaouas wrote:
> Hi all,
> Working with the ElementTree module, I looked for clone element function but not
> found such tool:
>
> def CloneElment(fromElem, destRoot = None)
> fromElem is the element to clone
> destRoot is the parent element of the new element ; if None so the new element
> will be child of fromElem parent. The clone operation is recursive to make it
> process all subtree of the element to clone.
>
> here is my first implementation:
>
> def CloneElement(fromElem, destRoot = None):
> if destRoot == None:
> fromRoot = ET.ElementTree(fromElem).getroot()
> destRoot = fromRoot
> destElem = destRoot.makeelement(fromElem.tag, fromElem.attrib)
> destRoot.append(destElem)
> destElem.text = fromElem.text
> for e in fromElem.findall('*'):
> CloneElement(e, destElem)
> #
> this function works fine only if destRoot parameter is defined by the caller
> context. The problem is about retreiving parent element: I didn't found any way
> to determine the parent element of an element "elem" by asking elem itself!
> and ET.ElementTree(fromElem).getroot() is wrong because it returns fromElem
> itself, not its parent.
>
> Thanks for any help.
> --
> http://mail.python.org/mailman/listinfo/python-list
>



Maybe `dest = ET.fromstring(ET.tostring(src))` would do?

Or as follows:

from xml.etree import ElementTree as ET

s = '''
<root>
<a name="A">text
<b name="B"><bb name="BB">BBtext
</bb></b>
</a>
<c />
<d name="D" />
<e>EEText</e>
</root>
'''

e = ET.fromstring(s)

def clone(elem):
ret = elem.makeelement(elem.tag, elem.attrib)
ret.text = elem.text
for child in elem:
ret.append(clone(child))
return ret

f = clone(e)

assert ''.join(ET.tostring(e).split()) == ''.join(ET.tostring(f).split())

assert f[0].get('name') == e[0].get('name')

f[0].set('name', 'NEWNAME')

assert f[0].get('name') == 'NEWNAME'
assert f[0].get('name') != e[0].get('name')

 
Reply With Quote
 
 
 
 
Gabriel Genellina
Guest
Posts: n/a
 
      02-02-2009
En Mon, 02 Feb 2009 12:37:36 -0200, Gerard Flanagan <(E-Mail Removed)>
escribió:

> e = ET.fromstring(s)
>
> def clone(elem):
> ret = elem.makeelement(elem.tag, elem.attrib)
> ret.text = elem.text
> for child in elem:
> ret.append(clone(child))
> return ret
>
> f = clone(e)


You forget the tail attribute, and you also should use the SubElement
factory instead of makeelement as documented; doing that fixes the
"parent" issue too.

--
Gabriel Genellina

 
Reply With Quote
 
Gerard Flanagan
Guest
Posts: n/a
 
      02-02-2009
Gabriel Genellina wrote:
> En Mon, 02 Feb 2009 12:37:36 -0200, Gerard Flanagan
> <(E-Mail Removed)> escribió:
>
>> e = ET.fromstring(s)
>>
>> def clone(elem):
>> ret = elem.makeelement(elem.tag, elem.attrib)
>> ret.text = elem.text
>> for child in elem:
>> ret.append(clone(child))
>> return ret
>>
>> f = clone(e)

>
> You forget the tail attribute,


I did, thanks.

and you also should use the SubElement
> factory instead of makeelement as documented; doing that fixes the
> "parent" issue too.
>


I suppose I would have just used the Element factory if the OP hadn't
otherwise:

def clone(elem):
ret = ET.Element(elem.tag, elem.attrib)
ret.text = elem.text
ret.tail = elem.tail
for child in elem:
ret.append(clone(child))
return ret

Not sure what SubElement gains you, in the context of the above function?

 
Reply With Quote
 
m.banaouas
Guest
Posts: n/a
 
      02-02-2009
My python version is 2.4.4

def SubElement(parent, tag, attrib={}, **extra):

Can you tell me how does "parent" issue could be solved by SubElement ?
I'm looking for how to determine element parent just by asking element it self.
It seems like element doesn't know witch is its parent, while any parent knows
well witch are its childs.

My goal is to clone an element and attach it to a specified parent or to parant
of original element to clone.

may be better implementation of CloneElement is to let the caller context make
the attachement between the clone and its parent.

Gabriel Genellina a écrit :
> En Mon, 02 Feb 2009 12:37:36 -0200, Gerard Flanagan
> <(E-Mail Removed)> escribió:
>
>> e = ET.fromstring(s)
>>
>> def clone(elem):
>> ret = elem.makeelement(elem.tag, elem.attrib)
>> ret.text = elem.text
>> for child in elem:
>> ret.append(clone(child))
>> return ret
>>
>> f = clone(e)

>
> You forget the tail attribute, and you also should use the SubElement
> factory instead of makeelement as documented; doing that fixes the
> "parent" issue too.
>

 
Reply With Quote
 
Gabriel Genellina
Guest
Posts: n/a
 
      02-03-2009
En Mon, 02 Feb 2009 14:21:29 -0200, m.banaouas
<(E-Mail Removed)> escribió:

> My python version is 2.4.4
>
> def SubElement(parent, tag, attrib={}, **extra):
>
> Can you tell me how does "parent" issue could be solved by SubElement ?


Simply because you *have* to pass a parent to the function...

> I'm looking for how to determine element parent just by asking element
> it self.


There isn't a way -- and there are good reasons. One is memory management
(it would create reference cycles, and they aren't efficiently removed).
Another one is that it prevents an element to be shared between containers.

> My goal is to clone an element and attach it to a specified parent or to
> parant of original element to clone.


Then pass the desired parent as the "parent" argument.

En Mon, 02 Feb 2009 13:52:59 -0200, Gerard Flanagan <(E-Mail Removed)>
escribió:

> Not sure what SubElement gains you, in the context of the above function?


Just because Element and SubElement are documented as the recommended way
to create Element instances. Also, I was under the impression that
makeelement did not make a copy of its "attrib" argument, so it would end
being shared by other instances too -- but it isn't the case actually.

--
Gabriel Genellina

 
Reply With Quote
 
Aahz
Guest
Posts: n/a
 
      02-08-2009
In article <4986bfd7$0$9385$(E-Mail Removed)>,
m.banaouas <(E-Mail Removed)> wrote:
>
>Working with the ElementTree module, I looked for clone element
>function but not found such tool:


Have you tried using copy.deepcopy()?
--
Aahz ((E-Mail Removed)) <*> http://www.pythoncraft.com/

Weinberg's Second Law: If builders built buildings the way programmers wrote
programs, then the first woodpecker that came along would destroy civilization.
 
Reply With Quote
 
Stefan Behnel
Guest
Posts: n/a
 
      02-09-2009
Aahz wrote:
> In article <4986bfd7$0$9385$(E-Mail Removed)>,
> m.banaouas <(E-Mail Removed)> wrote:
>> Working with the ElementTree module, I looked for clone element
>> function but not found such tool:

>
> Have you tried using copy.deepcopy()?


While being the most obvious solution, calling deepcopy() on an Element is
surprisingly slow in ElementTree.

http://codespeak.net/lxml/performance.html#deepcopy

It's actually multiple times faster to rebuild the tree manually through
the API than to let deepcopy() do it. Fredrik also has written a little
factory for mass reproduction of Element trees.

http://effbot.python-hosting.com/fil...ntlib/clone.py

Stefan
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
ElementTree.XML(string XML) and ElementTree.fromstring(string XML)not working Kee Nethery Python 12 06-27-2009 06:06 AM
C++ syntax expressed in toot-toot diagrams? Ole Nielsby C++ 4 09-12-2007 12:16 AM
ElementTree: namespace declaration in each element? cyberco Python 3 11-19-2006 08:18 PM
To clone or not to clone.. lordy Java 3 07-07-2006 04:30 PM
wxPython toot andrea valle Python 0 10-08-2004 05:47 PM



Advertisments