1
##############################################################################
3
# Copyright (c) 2001 Zope Foundation and Contributors.
5
# This software is subject to the provisions of the Zope Public License,
6
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10
# FOR A PARTICULAR PURPOSE
12
##############################################################################
13
"""DOM implementation in StructuredText: read-only methods
16
string_types = (str, unicode)
26
CDATA_SECTION_NODE = 4
27
ENTITY_REFERENCE_NODE = 5
29
PROCESSING_INSTRUCTION_NODE = 7
32
DOCUMENT_TYPE_NODE = 10
33
DOCUMENT_FRAGMENT_NODE = 11
40
DOMSTRING_SIZE_ERR = 2
41
HIERARCHY_REQUEST_ERR = 3
42
WRONG_DOCUMENT_ERR = 4
43
INVALID_CHARACTER_ERR = 5
44
NO_DATA_ALLOWED_ERR = 6
45
NO_MODIFICATION_ALLOWED_ERR = 7
48
INUSE_ATTRIBUTE_ERR = 10
53
class DOMException(Exception):
55
class IndexSizeException(DOMException):
57
class DOMStringSizeException(DOMException):
58
code = DOMSTRING_SIZE_ERR
59
class HierarchyRequestException(DOMException):
60
code = HIERARCHY_REQUEST_ERR
61
class WrongDocumentException(DOMException):
62
code = WRONG_DOCUMENT_ERR
63
class InvalidCharacterException(DOMException):
64
code = INVALID_CHARACTER_ERR
65
class NoDataAllowedException(DOMException):
66
code = NO_DATA_ALLOWED_ERR
67
class NoModificationAllowedException(DOMException):
68
code = NO_MODIFICATION_ALLOWED_ERR
69
class NotFoundException(DOMException):
71
class NotSupportedException(DOMException):
72
code = NOT_SUPPORTED_ERR
73
class InUseAttributeException(DOMException):
74
code = INUSE_ATTRIBUTE_ERR
81
A node that can have children, or, more precisely, that implements
82
the child access methods of the DOM.
85
def getChildNodes(self, type=type, sts=string_types):
87
Returns a NodeList that contains all children of this node.
88
If there are no children, this is a empty NodeList
91
for n in self.getChildren():
94
r.append(n.__of__(self))
98
def getFirstChild(self, type=type, sts=string_types):
100
The first child of this node. If there is no such node
103
children = self.getChildren()
113
return n.__of__(self)
115
def getLastChild(self, type=type, sts=string_types):
117
The last child of this node. If there is no such node
120
children = self.getChildren()
126
return n.__of__(self)
129
class NodeWrapper(ParentNode):
131
This is an acquisition-like wrapper that provides parent access for
132
DOM sans circular references!
135
def __init__(self, aq_self, aq_parent):
137
self.aq_parent=aq_parent
139
def __getattr__(self, name):
140
return getattr(self.aq_self, name)
142
def getParentNode(self):
144
The parent of this node. All nodes except Document
145
DocumentFragment and Attr may have a parent
147
return self.aq_parent
149
def _getDOMIndex(self, children, getattr=getattr):
152
for child in children:
153
if getattr(child, 'aq_self', child) is self:
159
def getPreviousSibling(self):
161
The node immediately preceding this node. If
162
there is no such node, this returns None.
165
children = self.aq_parent.getChildren()
169
index=getattr(self, '_DOMIndex', None)
171
index=self._getDOMIndex(children)
172
if index is None: return None
175
if index < 0: return None
176
try: n=children[index]
177
except IndexError: return None
179
if type(n) in string_types:
182
return n.__of__(self)
185
def getNextSibling(self):
187
The node immediately preceding this node. If
188
there is no such node, this returns None.
190
children = self.aq_parent.getChildren()
194
index=getattr(self, '_DOMIndex', None)
196
index=self._getDOMIndex(children)
201
try: n=children[index]
205
if type(n) in string_types:
208
return n.__of__(self)
210
def getOwnerDocument(self):
212
The Document object associated with this node, if any.
214
return self.aq_parent.getOwnerDocument()
216
class Node(ParentNode):
220
# Get a DOM wrapper with a parent link
221
def __of__(self, parent):
222
return NodeWrapper(self, parent)
226
def getNodeName(self):
227
"""The name of this node, depending on its type
230
def getNodeValue(self):
231
"""The value of this node, depending on its type
235
def getParentNode(self):
237
The parent of this node. All nodes except Document
238
DocumentFragment and Attr may have a parent
241
def getChildren(self):
242
"""Get a Python sequence of children
246
def getPreviousSibling(self):
248
The node immediately preceding this node. If
249
there is no such node, this returns None.
252
def getNextSibling(self):
254
The node immediately preceding this node. If
255
there is no such node, this returns None.
258
def getAttributes(self):
260
Returns a NamedNodeMap containing the attributes
261
of this node (if it is an element) or None otherwise.
265
def getOwnerDocument(self):
266
"""The Document object associated with this node, if any.
272
def hasChildNodes(self):
274
Returns true if the node has any children, false
277
return len(self.getChildren())
279
class TextNode(Node):
281
def __init__(self, str): self._value=str
283
def getNodeType(self):
286
def getNodeName(self):
289
def getNodeValue(self):
299
def getTagName(self):
300
"""The name of the element"""
301
return self.__class__.__name__
303
def getNodeName(self):
304
"""The name of this node, depending on its type"""
305
return self.__class__.__name__
307
def getNodeType(self):
308
"""A code representing the type of the node."""
311
def getNodeValue(self):
313
for c in self.getChildren():
314
if type(c) not in string_types:
319
def getParentNode(self):
321
The parent of this node. All nodes except Document
322
DocumentFragment and Attr may have a parent
330
def getAttribute(self, name): return getattr(self, name, None)
331
def getAttributeNode(self, name):
332
if hasattr(self, name):
333
return Attr(name, getattr(self, name))
335
def getAttributes(self):
337
for a in self._attributes:
338
d[a]=getattr(self, a, '')
339
return NamedNodeMap(d)
341
def getAttribute(self, name):
342
"""Retrieves an attribute value by name."""
345
def getAttributeNode(self, name):
346
""" Retrieves an Attr node by name or None if
347
there is no such attribute. """
350
def getElementsByTagName(self, tagname):
352
Returns a NodeList of all the Elements with a given tag
353
name in the order in which they would be encountered in a
354
preorder traversal of the Document tree. Parameter: tagname
355
The name of the tag to match (* = all tags). Return Value: A new
356
NodeList object containing all the matched Elements.
359
for child in self.getChildren():
360
if not hasattr(child, 'getNodeType'): continue
361
if (child.getNodeType()==ELEMENT_NODE and \
362
child.getTagName()==tagname or tagname== '*'):
364
nodeList.append(child)
366
if hasattr(child, 'getElementsByTagName'):
367
n1 = child.getElementsByTagName(tagname)
368
nodeList = nodeList + n1._data
369
return NodeList(nodeList)
372
"""NodeList interface - Provides the abstraction of an ordered
375
Python extensions: can use sequence-style 'len', 'getitem', and
376
'for..in' constructs.
379
def __init__(self,list=None):
380
self._data = list or []
382
def __getitem__(self, index, type=type, sts=string_types):
383
return self._data[index]
385
def __getslice__(self, i, j):
386
return self._data[i:j]
388
def item(self, index):
389
"""Returns the index-th item in the collection
391
return self._data.get(index, None)
394
"""The length of the NodeList
396
return len(self._data)
402
NamedNodeMap interface - Is used to represent collections
403
of nodes that can be accessed by name. NamedNodeMaps are not
404
maintained in any particular order.
406
Python extensions: can use sequence-style 'len', 'getitem', and
407
'for..in' constructs, and mapping-style 'getitem'.
410
def __init__(self, data=None):
415
def item(self, index):
416
"""Returns the index-th item in the map
418
return self._data.values().get(index, None)
421
def __getitem__(self, key):
422
if isinstance(key, int):
423
return self.item(key)
425
return self._data[key]
429
The length of the NodeList
431
return len(self._data)
435
def getNamedItem(self, name):
437
Retrieves a node specified by name. Parameters:
438
name Name of a node to retrieve. Return Value A Node (of any
439
type) with the specified name, or None if the specified name
440
did not identify any node in the map.
442
return self._data.get(name, None)
446
Attr interface - The Attr interface represents an attriubte in an
447
Element object. Attr objects inherit the Node Interface
450
def __init__(self, name, value, specified=1):
453
self.specified = specified
455
def getNodeName(self):
457
The name of this node, depending on its type
463
Returns the name of this attribute.
467
def getNodeValue(self):
469
The value of this node, depending on its type
473
def getNodeType(self):
475
A code representing the type of the node.
477
return ATTRIBUTE_NODE
479
def getSpecified(self):
481
If this attribute was explicitly given a value in the
482
original document, this is true; otherwise, it is false.
484
return self.specified