@@ -29,11 +29,19 @@ class Node:
29
29
DOCUMENT_FRAGMENT_NODE = 11
30
30
NOTATION_NODE = 12
31
31
32
- allnodes = []
32
+ allnodes = {}
33
+ _debug = 0
34
+ _makeParentNodes = 1
35
+ debug = None
33
36
34
37
def __init__ ( self ):
35
38
self .childNodes = []
36
- Node .allnodes .append ( repr ( id ( self ))+ repr ( self .__class__ ))
39
+ if Node ._debug :
40
+ index = repr ( id ( self ))+ repr ( self .__class__ )
41
+ Node .allnodes [index ]= repr ( self .__dict__ )
42
+ if Node .debug == None :
43
+ Node .debug = open ( "debug4.out" , "w" )
44
+ Node .debug .write ( "create %s\n " % index )
37
45
38
46
def __getattr__ ( self , key ):
39
47
if key [0 :2 ]== "__" : raise AttributeError
@@ -72,12 +80,39 @@ def hasChildNodes( self ):
72
80
if self .childNodes : return 1
73
81
else : return 0
74
82
83
+ def _get_firstChild ( self ):
84
+ return self .childNodes [0 ]
85
+
86
+ def _get_lastChild ( self ):
87
+ return self .childNodes [- 1 ]
88
+
75
89
def insertBefore ( self , newChild , refChild ):
76
90
index = self .childNodes .index ( refChild )
77
91
self .childNodes .insert ( index , newChild )
92
+ if self ._makeParentNodes :
93
+ newChild .parentNode = self
78
94
79
95
def appendChild ( self , node ):
80
96
self .childNodes .append ( node )
97
+ return node
98
+
99
+ def replaceChild ( self , newChild , oldChild ):
100
+ index = self .childNodes .index ( oldChild )
101
+ self .childNodes [index ]= oldChild
102
+
103
+ def removeChild ( self , oldChild ):
104
+ index = self .childNodes .index ( oldChild )
105
+ del self .childNodes [index ]
106
+
107
+ def cloneNode ( self , deep ):
108
+ import new
109
+ clone = new .instance ( self .__class__ , self .__dict__ )
110
+ clone .attributes = self .attributes .copy ()
111
+ if not deep :
112
+ clone .childNodes = []
113
+ else :
114
+ clone .childNodes = map ( lambda x : x .cloneNode , self .childNodes )
115
+ return clone
81
116
82
117
def unlink ( self ):
83
118
self .parentNode = None
@@ -86,11 +121,14 @@ def unlink( self ):
86
121
del self .childNodes [- 1 ] # probably not most efficient!
87
122
self .childNodes = None
88
123
if self .attributes :
89
- for attr in self .attributes .values ():
90
- attr .unlink ()
91
- self .attributes = None
92
- index = Node .allnodes .index ( repr ( id ( self ))+ repr ( self .__class__ ))
93
- del Node .allnodes [index ]
124
+ for attr in self ._attrs .values ():
125
+ self .removeAttributeNode ( attr )
126
+ assert not len ( self ._attrs )
127
+ assert not len ( self ._attrsNS )
128
+ if Node ._debug :
129
+ index = repr ( id ( self ))+ repr ( self .__class__ )
130
+ self .debug .write ( "Deleting: %s\n " % index )
131
+ del Node .allnodes [index ]
94
132
95
133
def _write_data ( writer , data ):
96
134
"Writes datachars to writer."
@@ -100,11 +138,6 @@ def _write_data( writer, data):
100
138
data = string .replace (data ,">" ,">" )
101
139
writer .write (data )
102
140
103
- def _closeElement ( element ):
104
- del element .parentNode
105
- for node in element .elements :
106
- _closeElement ( node )
107
-
108
141
def _getElementsByTagNameHelper ( parent , name , rc ):
109
142
for node in parent .childNodes :
110
143
if node .nodeType == Node .ELEMENT_NODE and \
@@ -123,17 +156,16 @@ def _getElementsByTagNameNSHelper( parent, nsURI, localName, rc ):
123
156
124
157
class Attr (Node ):
125
158
nodeType = Node .ATTRIBUTE_NODE
126
- def __init__ ( self , qName , namespaceURI = "" , prefix = "" ,
127
- localName = None ):
128
- Node .__init__ ( self )
129
- assert qName
159
+ def __init__ ( self , qName , namespaceURI = "" , localName = None ,
160
+ prefix = None ):
130
161
# skip setattr for performance
131
- self .__dict__ ["nodeName" ] = self .__dict__ ["name" ] = qName
132
162
self .__dict__ ["localName" ]= localName or qName
133
- self .__dict__ ["prefix" ] = prefix
163
+ self .__dict__ ["nodeName" ] = self . __dict__ [ "name" ] = qName
134
164
self .__dict__ ["namespaceURI" ]= namespaceURI
135
- # nodeValue and value are set elsewhere
165
+ self . __dict__ [ "prefix" ] = prefix
136
166
self .attributes = None
167
+ Node .__init__ ( self )
168
+ # nodeValue and value are set elsewhere
137
169
138
170
def __setattr__ ( self , name , value ):
139
171
if name in ("value" , "nodeValue" ):
@@ -142,12 +174,13 @@ def __setattr__( self, name, value ):
142
174
self .__dict__ [name ]= value
143
175
144
176
class AttributeList :
145
- # the attribute list is a transient interface to the underlying dictionaries
146
- # mutations here will change the underlying element's dictionary
177
+ """the attribute list is a transient interface to the underlying
178
+ dictionaries. mutations here will change the underlying element's
179
+ dictionary"""
147
180
def __init__ ( self , attrs , attrsNS ):
148
- self .__attrs = attrs
149
- self .__attrsNS = attrs
150
- self .length = len ( self .__attrs .keys () )
181
+ self ._attrs = attrs
182
+ self ._attrsNS = attrsNS
183
+ self .length = len ( self ._attrs .keys () )
151
184
152
185
def item ( self , index ):
153
186
try :
@@ -157,40 +190,46 @@ def item( self, index ):
157
190
158
191
def items ( self ):
159
192
return map ( lambda node : (node .tagName , node .value ),
160
- self .__attrs .values () )
193
+ self ._attrs .values () )
161
194
162
195
def itemsNS ( self ):
163
196
return map ( lambda node : ((node .URI , node .localName ), node .value ),
164
- self .__attrs .values () )
197
+ self ._attrs .values () )
165
198
166
199
def keys ( self ):
167
- return self .__attrs .keys ()
200
+ return self ._attrs .keys ()
168
201
169
202
def keysNS ( self ):
170
- return self .__attrsNS .keys ()
203
+ return self ._attrsNS .keys ()
171
204
172
205
def values ( self ):
173
- return self .__attrs .values ()
206
+ return self ._attrs .values ()
174
207
175
208
def __len__ ( self ):
176
209
return self .length
177
210
178
211
def __cmp__ ( self , other ):
179
- if self .__attrs is other . __attrs :
212
+ if self ._attrs is getattr ( other , "_attrs" , None ):
180
213
return 0
181
214
else :
182
215
return cmp ( id ( self ), id ( other ) )
183
216
184
217
#FIXME: is it appropriate to return .value?
185
218
def __getitem__ ( self , attname_or_tuple ):
186
- if type ( attname_or_tuple ) == type ( (1 , 2 ) ):
187
- return self .__attrsNS [attname_or_tuple ]. value
219
+ if type ( attname_or_tuple ) == type ( () ):
220
+ return self ._attrsNS [attname_or_tuple ]
188
221
else :
189
- return self .__attrs [attname_or_tuple ]. value
222
+ return self ._attrs [attname_or_tuple ]
190
223
191
224
def __setitem__ ( self , attname ):
192
225
raise TypeError , "object does not support item assignment"
193
-
226
+
227
+ def __delitem__ ( self , attname_or_tuple ):
228
+ node = self [attname_or_tuple ]
229
+ node .unlink ()
230
+ del self ._attrs [node .name ]
231
+ del self ._attrsNS [(node .namespaceURI , node .localName )]
232
+
194
233
class Element ( Node ):
195
234
nodeType = Node .ELEMENT_NODE
196
235
def __init__ ( self , tagName , namespaceURI = "" , prefix = "" ,
@@ -202,18 +241,18 @@ def __init__( self, tagName, namespaceURI="", prefix="",
202
241
self .namespaceURI = namespaceURI
203
242
self .nodeValue = None
204
243
205
- self .__attrs = {} # attributes are double-indexed:
206
- self .__attrsNS = {}# tagName -> Attribute
244
+ self ._attrs = {} # attributes are double-indexed:
245
+ self ._attrsNS = {}# tagName -> Attribute
207
246
# URI,localName -> Attribute
208
247
# in the future: consider lazy generation of attribute objects
209
248
# this is too tricky for now because of headaches
210
249
# with namespaces.
211
250
212
251
def getAttribute ( self , attname ):
213
- return self .__attrs [attname ].value
252
+ return self ._attrs [attname ].value
214
253
215
254
def getAttributeNS ( self , namespaceURI , localName ):
216
- return self .__attrsNS [(namespaceURI , localName )].value
255
+ return self ._attrsNS [(namespaceURI , localName )].value
217
256
218
257
def setAttribute ( self , attname , value ):
219
258
attr = Attr ( attname )
@@ -222,26 +261,37 @@ def setAttribute( self, attname, value ):
222
261
self .setAttributeNode ( attr )
223
262
224
263
def setAttributeNS ( self , namespaceURI , qualifiedName , value ):
225
- attr = createAttributeNS ( namespaceURI , qualifiedName )
264
+ prefix , localname = _nssplit ( qualifiedName )
226
265
# for performance
266
+ attr = Attr ( qualifiedName , namespaceURI , localname , prefix )
227
267
attr .__dict__ ["value" ]= attr .__dict__ ["nodeValue" ]= value
228
268
self .setAttributeNode ( attr )
229
269
270
+ def getAttributeNode ( self , attrname ):
271
+ return self ._attrs .get ( attrname )
272
+
273
+ def getAttributeNodeNS ( self , namespaceURI , localName ):
274
+ return self ._attrsNS [(namespaceURI , localName )]
275
+
230
276
def setAttributeNode ( self , attr ):
231
- self .__attrs [attr .name ]= attr
232
- self .__attrsNS [(attr .namespaceURI ,attr .localName )]= attr
277
+ old = self ._attrs .get ( attr .name , None )
278
+ if old :
279
+ old .unlink ()
280
+ self ._attrs [attr .name ]= attr
281
+ self ._attrsNS [(attr .namespaceURI ,attr .localName )]= attr
233
282
234
283
def removeAttribute ( self , name ):
235
- attr = self .__attrs [name ]
284
+ attr = self ._attrs [name ]
236
285
self .removeAttributeNode ( attr )
237
286
238
287
def removeAttributeNS ( self , namespaceURI , localName ):
239
- attr = self .__attrsNS [( uri , localName )]
288
+ attr = self ._attrsNS [( namespaceURI , localName )]
240
289
self .removeAttributeNode ( attr )
241
290
242
291
def removeAttributeNode ( self , node ):
243
- del self .__attrs [node .name ]
244
- del self .__attrsNS [(node .namespaceURI , node .localName )]
292
+ node .unlink ()
293
+ del self ._attrs [node .name ]
294
+ del self ._attrsNS [(node .namespaceURI , node .localName )]
245
295
246
296
def getElementsByTagName ( self , name ):
247
297
return _getElementsByTagNameHelper ( self , name , [] )
@@ -271,7 +321,7 @@ def writexml(self, writer):
271
321
writer .write ("/>" )
272
322
273
323
def _get_attributes ( self ):
274
- return AttributeList ( self .__attrs , self .__attrsNS )
324
+ return AttributeList ( self ._attrs , self ._attrsNS )
275
325
276
326
class Comment ( Node ):
277
327
nodeType = Node .COMMENT_NODE
@@ -313,15 +363,30 @@ def __repr__(self):
313
363
def writexml ( self , writer ):
314
364
_write_data ( writer , self .data )
315
365
366
+ def _nssplit ( qualifiedName ):
367
+ fields = string .split (qualifiedName , ':' )
368
+ if len (fields ) == 2 :
369
+ return fields
370
+ elif len (fields ) == 1 :
371
+ return ( '' , fields [0 ] )
372
+
316
373
class Document ( Node ):
317
374
nodeType = Node .DOCUMENT_NODE
375
+ documentElement = None
318
376
def __init__ ( self ):
319
377
Node .__init__ ( self )
320
- self .documentElement = None
321
378
self .attributes = None
322
379
self .nodeName = "#document"
323
380
self .nodeValue = None
324
381
382
+ def appendChild ( self , node ):
383
+ if node .nodeType == Node .ELEMENT_NODE and self .documentElement :
384
+ raise TypeError , "Two document elements disallowed"
385
+ else :
386
+ self .documentElement = node
387
+ Node .appendChild ( self , node )
388
+ return node
389
+
325
390
createElement = Element
326
391
327
392
createTextNode = Text
@@ -333,32 +398,16 @@ def __init__( self ):
333
398
createAttribute = Attr
334
399
335
400
def createElementNS (self , namespaceURI , qualifiedName ):
336
- fields = string .split (qualifiedName , ':' )
337
- if len (fields ) == 2 :
338
- prefix = fields [0 ]
339
- localName = fields [1 ]
340
- elif len (fields ) == 1 :
341
- prefix = ''
342
- localName = fields [0 ]
343
- return Element (self , qualifiedName , namespaceURI , prefix , localName )
401
+ prefix ,localName = _nssplit ( qualifiedName )
402
+ return Element (qualifiedName , namespaceURI , prefix , localName )
344
403
345
404
def createAttributeNS (self , namespaceURI , qualifiedName ):
346
- fields = string .split (qualifiedName ,':' )
347
- if len (fields ) == 2 :
348
- localName = fields [1 ]
349
- prefix = fields [0 ]
350
- elif len (fields ) == 1 :
351
- localName = fields [0 ]
352
- prefix = None
353
- return Attr (qualifiedName , namespaceURI , prefix , localName )
405
+ prefix ,localName = _nssplit ( qualifiedName )
406
+ return Attr (namespaceURI , qualifiedName , localName , prefix )
354
407
355
408
def getElementsByTagNameNS (self ,namespaceURI ,localName ):
356
409
_getElementsByTagNameNSHelper ( self , namespaceURI , localName )
357
410
358
- def close ( self ):
359
- for node in self .elements :
360
- _closeElement ( node )
361
-
362
411
def unlink ( self ):
363
412
self .documentElement = None
364
413
Node .unlink ( self )
0 commit comments