@@ -25,19 +25,35 @@ class Element(_base.Node):
2525def __init__ (self ,element ,soup ):
2626_base .Node .__init__ (self ,element .name )
2727self .element = element
28- self .soup = soup
28+ self .soup = soup
29+
30+ def _nodeIndex (self ,node ,refNode ):
31+ # Finds a node by identity rather than equality
32+ for index in range (len (self .element .contents )):
33+ if id (self .element .contents [index ])== id (refNode .element ):
34+ return index
35+ return None
2936
3037def appendChild (self ,node ):
3138if (node .element .__class__ == NavigableString and self .element .contents
3239and self .element .contents [- 1 ].__class__ == NavigableString ):
33- newNode = TextNode (NavigableString (
34- self .element .contents [- 1 ]+ node .element ),self .soup )
35- self .element .contents [- 1 ].extract ()
36- self .appendChild (newNode )
40+ # Concatenate new text onto old text node
41+ # (TODO: This has O(n^2) performance, for input like "a</a>a</a>a</a>...")
42+ newStr = NavigableString (self .element .contents [- 1 ]+ node .element )
43+
44+ # Remove the old text node
45+ # (Can't simply use .extract() by itself, because it fails if
46+ # an equal text node exists within the parent node)
47+ oldElement = self .element .contents [- 1 ]
48+ del self .element .contents [- 1 ]
49+ oldElement .parent = None
50+ oldElement .extract ()
51+
52+ self .element .insert (len (self .element .contents ),newStr )
3753else :
3854self .element .insert (len (self .element .contents ),node .element )
3955node .parent = self
40-
56+
4157def getAttributes (self ):
4258return AttrList (self .element )
4359
@@ -56,18 +72,25 @@ def insertText(self, data, insertBefore=None):
5672self .appendChild (text )
5773
5874def insertBefore (self ,node ,refNode ):
59- index = self .element . contents . index ( refNode . element )
75+ index = self ._nodeIndex ( node , refNode )
6076if (node .element .__class__ == NavigableString and self .element .contents
6177and self .element .contents [index - 1 ].__class__ == NavigableString ):
62- newNode = TextNode (NavigableString (
63- self .element .contents [index - 1 ]+ node .element ),self .soup )
64- self .element .contents [index - 1 ].extract ()
65- self .insertBefore (newNode ,refNode )
78+ # (See comments in appendChild)
79+ newStr = NavigableString (self .element .contents [index - 1 ]+ node .element )
80+ oldNode = self .element .contents [index - 1 ]
81+ del self .element .contents [index - 1 ]
82+ oldNode .parent = None
83+ oldNode .extract ()
84+
85+ self .element .insert (index - 1 ,newStr )
6686else :
6787self .element .insert (index ,node .element )
6888node .parent = self
6989
7090def removeChild (self ,node ):
91+ index = self ._nodeIndex (node .parent ,node )
92+ del node .parent .element .contents [index ]
93+ node .element .parent = None
7194node .element .extract ()
7295node .parent = None
7396
@@ -93,7 +116,7 @@ class TextNode(Element):
93116def __init__ (self ,element ,soup ):
94117_base .Node .__init__ (self ,None )
95118self .element = element
96- self .soup = soup
119+ self .soup = soup
97120
98121def cloneNode (self ):
99122raise NotImplementedError