[XML-SIG] no parent?

Andrew Clover and-xml at doxdesk.com
Wed Oct 13 01:55:47 CEST 2004

Matthias Teege <matthias-gmane at mteege.de> schrieb:

 >     elements = document.getElementsByTagName("text:placeholder")
 >     for element in elements:
 >         parent   = element.parentNode
 >         children = parent.childNodes
 >         i = len(children)-1
 >         while (i >= 0):
 >             if (children[i].nodeName == "text:placeholder"):
 >                 parent.removeChild( children[i] )
 >                 # not remove, replace with text
 >             i = i - 1

I'm not sure what your inner 'while' loop is trying to do here. Having 
got hold of a placeholder element, you then try to find all its siblings 
that are placeholder elements too, and replace *them*? However because 
they're also placeholder elements they will already be in the list used 
by the outer 'for' loop.

Remove one of the placeholder elements from the document and it will 
still be in the list used by the outer loop.(*) So when the outer loop 
gets to its next element you could well have already removed it from the 
document - thus it will have no parent and parentNode will be None as 
you encountered.

 > Is there a better way to replace the complete placeholder tag with
 > useful text?

Well, at a guess:

   placeholders= document.getElementsByTagName('text:placeholder')
   for placeholder in list(placeholders):
     text= document.createTextNode('Hello!') # or whatever
     placeholder.parentNode.replaceChild(text, placeholder)

(assuming you don't have any nested placeholder elements!)

(*) - this is actually a slight misbehaviour from minidom. When you do a 
getElementsByTagName, the DOM standard says you're supposed to get a 
'live' list back, so that when you remove the elements from the document 
they disappear from that list too. minidom (and 4DOM) instead return a 
plain static list that does not change. HOWEVER: even on a 
fully-compliant implementation the original code wouldn't work properly, 
because the list index used by the 'for' loop would miss out elements as 
you removed their siblings from the list.

When you are iterating a NodeList in a way that may be destructive, it's 
a good idea to make a copy, whether it's a childNodes NodeList, which is 
always 'live', or a getElementsByTagName one, which may or may not be, 
depending on the DOM implementation you are using; the list() 
constructor or a slice-copy [:] operation can be used to do this.

Andrew Clover
mailto:and at doxdesk.com

More information about the XML-SIG mailing list