1 ##############################################################################
3 # Zope Public License (ZPL) Version 1.0
4 # -------------------------------------
6 # Copyright (c) Digital Creations. All rights reserved.
8 # This license has been certified as Open Source(tm).
10 # Redistribution and use in source and binary forms, with or without
11 # modification, are permitted provided that the following conditions are
14 # 1. Redistributions in source code must retain the above copyright
15 # notice, this list of conditions, and the following disclaimer.
17 # 2. Redistributions in binary form must reproduce the above copyright
18 # notice, this list of conditions, and the following disclaimer in
19 # the documentation and/or other materials provided with the
22 # 3. Digital Creations requests that attribution be given to Zope
23 # in any manner possible. Zope includes a "Powered by Zope"
24 # button that is installed by default. While it is not a license
25 # violation to remove this button, it is requested that the
26 # attribution remain. A significant investment has been put
27 # into Zope, and this effort will continue if the Zope community
28 # continues to grow. This is one way to assure that growth.
30 # 4. All advertising materials and documentation mentioning
31 # features derived from or use of this software must display
32 # the following acknowledgement:
34 # "This product includes software developed by Digital Creations
35 # for use in the Z Object Publishing Environment
36 # (http://www.zope.org/)."
38 # In the event that the product being advertised includes an
39 # intact Zope distribution (with copyright and license included)
40 # then this clause is waived.
42 # 5. Names associated with Zope or Digital Creations must not be used to
43 # endorse or promote products derived from this software without
44 # prior written permission from Digital Creations.
46 # 6. Modified redistributions of any form whatsoever must retain
47 # the following acknowledgment:
49 # "This product includes software developed by Digital Creations
50 # for use in the Z Object Publishing Environment
51 # (http://www.zope.org/)."
53 # Intact (re-)distributions of any official Zope release do not
54 # require an external acknowledgement.
56 # 7. Modifications are encouraged but must be packaged separately as
57 # patches to official Zope releases. Distributions that do not
58 # clearly separate the patches from the original work must be clearly
59 # labeled as unofficial distributions. Modifications which do not
60 # carry the name Zope may be packaged in any form, as long as they
61 # conform to all of the clauses above.
66 # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
67 # EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
68 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
69 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
70 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
71 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
72 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
73 # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
74 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
75 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
76 # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
80 # This software consists of contributions made by Digital Creations and
81 # many individuals on behalf of Digital Creations. Specific
82 # attributions are listed in the accompanying credits file.
84 ##############################################################################
86 DOM implementation in StructuredText : Read-Only methods
88 All standard Zope objects support DOM to a limited extent.
99 CDATA_SECTION_NODE
= 4
100 ENTITY_REFERENCE_NODE
= 5
102 PROCESSING_INSTRUCTION_NODE
= 7
105 DOCUMENT_TYPE_NODE
= 10
106 DOCUMENT_FRAGMENT_NODE
= 11
113 DOMSTRING_SIZE_ERR
= 2
114 HIERARCHY_REQUEST_ERR
= 3
115 WRONG_DOCUMENT_ERR
= 4
116 INVALID_CHARACTER_ERR
= 5
117 NO_DATA_ALLOWED_ERR
= 6
118 NO_MODIFICATION_ALLOWED_ERR
= 7
120 NOT_SUPPORTED_ERR
= 9
121 INUSE_ATTRIBUTE_ERR
= 10
126 class DOMException(Exception):
128 class IndexSizeException(DOMException
):
129 code
= INDEX_SIZE_ERR
130 class DOMStringSizeException(DOMException
):
131 code
= DOMSTRING_SIZE_ERR
132 class HierarchyRequestException(DOMException
):
133 code
= HIERARCHY_REQUEST_ERR
134 class WrongDocumentException(DOMException
):
135 code
= WRONG_DOCUMENT_ERR
136 class InvalidCharacterException(DOMException
):
137 code
= INVALID_CHARACTER_ERR
138 class NoDataAllowedException(DOMException
):
139 code
= NO_DATA_ALLOWED_ERR
140 class NoModificationAllowedException(DOMException
):
141 code
= NO_MODIFICATION_ALLOWED_ERR
142 class NotFoundException(DOMException
):
144 class NotSupportedException(DOMException
):
145 code
= NOT_SUPPORTED_ERR
146 class InUseAttributeException(DOMException
):
147 code
= INUSE_ATTRIBUTE_ERR
154 A node that can have children, or, more precisely, that implements
155 the child access methods of the DOM.
158 def getChildNodes(self
, type=type, st
=type('')):
160 Returns a NodeList that contains all children of this node.
161 If there are no children, this is a empty NodeList
165 for n
in self
.getChildren():
166 if type(n
) is st
: n
=TextNode(n
)
167 r
.append(n
.__of
__(self
))
171 def getFirstChild(self
, type=type, st
=type('')):
173 The first child of this node. If there is no such node
176 children
= self
.getChildren()
186 return n
.__of
__(self
)
188 def getLastChild(self
, type=type, st
=type('')):
190 The last child of this node. If there is no such node
193 children
= self
.getChildren()
194 if not children
: return None
196 if type(n
) is st
: n
=TextNode(n
)
197 return n
.__of
__(self
)
200 create aliases for all above functions in the pythony way.
203 def _get_ChildNodes(self
, type=type, st
=type('')):
204 return self
.getChildNodes(type,st
)
206 def _get_FirstChild(self
, type=type, st
=type('')):
207 return self
.getFirstChild(type,st
)
209 def _get_LastChild(self
, type=type, st
=type('')):
210 return self
.getLastChild(type,st
)
212 class NodeWrapper(ParentNode
):
214 This is an acquisition-like wrapper that provides parent access for
215 DOM sans circular references!
218 def __init__(self
, aq_self
, aq_parent
):
220 self
.aq_parent
=aq_parent
222 def __getattr__(self
, name
):
223 return getattr(self
.aq_self
, name
)
225 def getParentNode(self
):
227 The parent of this node. All nodes except Document
228 DocumentFragment and Attr may have a parent
230 return self
.aq_parent
232 def _getDOMIndex(self
, children
, getattr=getattr):
235 for child
in children
:
236 if getattr(child
, 'aq_self', child
) is self
:
242 def getPreviousSibling(self
,
249 The node immediately preceding this node. If
250 there is no such node, this returns None.
253 children
= self
.aq_parent
.getChildren()
257 index
=getattr(self
, '_DOMIndex', None)
259 index
=self
._getDOMIndex
(children
)
260 if index
is None: return None
263 if index
< 0: return None
264 try: n
=children
[index
]
265 except IndexError: return None
270 return n
.__of
__(self
)
273 def getNextSibling(self
, type=type, st
=type('')):
275 The node immediately preceding this node. If
276 there is no such node, this returns None.
278 children
= self
.aq_parent
.getChildren()
282 index
=getattr(self
, '_DOMIndex', None)
284 index
=self
._getDOMIndex
(children
)
289 try: n
=children
[index
]
296 return n
.__of
__(self
)
298 def getOwnerDocument(self
):
300 The Document object associated with this node, if any.
302 return self
.aq_parent
.getOwnerDocument()
305 create aliases for all above functions in the pythony way.
308 def _get_ParentNode(self
):
309 return self
.getParentNode()
311 def _get_DOMIndex(self
, children
, getattr=getattr):
312 return self
._getDOMIndex
(children
,getattr)
314 def _get_PreviousSibling(self
,
320 return self
.getPreviousSibling(type,st
,getattr,None)
322 def _get_NextSibling(self
, type=type, st
=type('')):
323 return self
.getNextSibling(type,st
)
325 def _get_OwnerDocument(self
):
326 return self
.getOwnerDocument()
328 class Node(ParentNode
):
333 # Get a DOM wrapper with a parent link
334 def __of__(self
, parent
):
335 return NodeWrapper(self
, parent
)
340 def getNodeName(self
):
342 The name of this node, depending on its type
345 def getNodeValue(self
):
347 The value of this node, depending on its type
351 def getParentNode(self
):
353 The parent of this node. All nodes except Document
354 DocumentFragment and Attr may have a parent
357 def getChildren(self
):
359 Get a Python sequence of children
363 def getPreviousSibling(self
,
369 The node immediately preceding this node. If
370 there is no such node, this returns None.
373 def getNextSibling(self
, type=type, st
=type('')):
375 The node immediately preceding this node. If
376 there is no such node, this returns None.
379 def getAttributes(self
):
381 Returns a NamedNodeMap containing the attributes
382 of this node (if it is an element) or None otherwise.
386 def getOwnerDocument(self
):
388 The Document object associated with this node, if any.
394 def hasChildNodes(self
):
396 Returns true if the node has any children, false
399 return len(self
.getChildren())
402 create aliases for all above functions in the pythony way.
405 def _get_NodeName(self
):
406 return self
.getNodeName()
408 def _get_NodeValue(self
):
409 return self
.getNodeValue()
411 def _get_ParentNode(self
):
412 return self
.getParentNode()
414 def _get_Children(self
):
415 return self
.getChildren()
417 def _get_PreviousSibling(self
,
423 return self
.getPreviousSibling(type,st
,getattr,None)
425 def _get_NextSibling(self
, type=type, st
=type('')):
426 return self
.getNextSibling()
428 def _get_Attributes(self
):
429 return self
.getAttributes()
431 def _get_OwnerDocument(self
):
432 return self
.getOwnerDocument()
434 def _has_ChildNodes(self
):
435 return self
.hasChildNodes()
438 class TextNode(Node
):
440 def __init__(self
, str): self
._value
=str
442 def getNodeType(self
):
445 def getNodeName(self
):
448 def getNodeValue(self
):
452 create aliases for all above functions in the pythony way.
455 def _get_NodeType(self
):
456 return self
.getNodeType()
458 def _get_NodeName(self
):
459 return self
.getNodeName()
461 def _get_NodeValue(self
):
462 return self
.getNodeValue()
472 def getTagName(self
):
473 """The name of the element"""
474 return self
.__class
__.__name
__
476 def getNodeName(self
):
477 """The name of this node, depending on its type"""
478 return self
.__class
__.__name
__
480 def getNodeType(self
):
481 """A code representing the type of the node."""
484 def getNodeValue(self
, type=type, st
=type('')):
486 for c
in self
.getChildren():
487 if type(c
) is not st
:
490 return string
.join(r
,'')
492 def getParentNode(self
):
494 The parent of this node. All nodes except Document
495 DocumentFragment and Attr may have a parent
503 def getAttribute(self
, name
): return getattr(self
, name
, None)
504 def getAttributeNode(self
, name
):
505 if hasattr(self
, name
):
506 return Attr(name
, getattr(self
, name
))
508 def getAttributes(self
):
510 for a
in self
._attributes
:
511 d
[a
]=getattr(self
, a
, '')
512 return NamedNodeMap(d
)
514 def getAttribute(self
, name
):
515 """Retrieves an attribute value by name."""
518 def getAttributeNode(self
, name
):
519 """ Retrieves an Attr node by name or None if
520 there is no such attribute. """
523 def getElementsByTagName(self
, tagname
):
525 Returns a NodeList of all the Elements with a given tag
526 name in the order in which they would be encountered in a
527 preorder traversal of the Document tree. Parameter: tagname
528 The name of the tag to match (* = all tags). Return Value: A new
529 NodeList object containing all the matched Elements.
532 for child
in self
.getChildren():
533 if (child
.getNodeType()==ELEMENT_NODE
and \
534 child
.getTagName()==tagname
or tagname
== '*'):
536 nodeList
.append(child
)
538 if hasattr(child
, 'getElementsByTagName'):
539 n1
= child
.getElementsByTagName(tagname
)
540 nodeList
= nodeList
+ n1
._data
541 return NodeList(nodeList
)
544 create aliases for all above functions in the pythony way.
547 def _get_TagName(self
):
548 return self
.getTagName()
550 def _get_NodeName(self
):
551 return self
.getNodeName()
553 def _get_NodeType(self
):
554 return self
.getNodeType()
556 def _get_NodeValue(self
, type=type, st
=type('')):
557 return self
.getNodeValue(type,st
)
559 def _get_ParentNode(self
):
560 return self
.getParentNode()
562 def _get_Attribute(self
, name
):
563 return self
.getAttribute(name
)
565 def _get_AttributeNode(self
, name
):
566 return self
.getAttributeNode(name
)
568 def _get_Attributes(self
):
569 return self
.getAttributes()
571 def _get_Attribute(self
, name
):
572 return self
.getAttribute(name
)
574 def _get_AttributeNode(self
, name
):
575 return self
.getAttributeNode(name
)
577 def _get_ElementsByTagName(self
, tagname
):
578 return self
.getElementsByTagName(tagname
)
583 NodeList interface - Provides the abstraction of an ordered
586 Python extensions: can use sequence-style 'len', 'getitem', and
587 'for..in' constructs.
590 def __init__(self
,list=None):
591 self
._data
= list or []
593 def __getitem__(self
, index
, type=type, st
=type('')):
594 return self
._data
[index
]
596 def __getslice__(self
, i
, j
):
597 return self
._data
[i
:j
]
599 def item(self
, index
):
601 Returns the index-th item in the collection
603 try: return self
._data
[index
]
604 except IndexError: return None
608 The length of the NodeList
610 return len(self
._data
)
615 create aliases for all above functions in the pythony way.
618 def _get_Length(self
):
619 return self
.getLength()
623 NamedNodeMap interface - Is used to represent collections
624 of nodes that can be accessed by name. NamedNodeMaps are not
625 maintained in any particular order.
627 Python extensions: can use sequence-style 'len', 'getitem', and
628 'for..in' constructs, and mapping-style 'getitem'.
631 def __init__(self
, data
=None):
636 def item(self
, index
):
638 Returns the index-th item in the map
640 try: return self
._data
.values()[index
]
641 except IndexError: return None
643 def __getitem__(self
, key
):
644 if type(key
)==type(1):
645 return self
._data
.values()[key
]
647 return self
._data
[key
]
651 The length of the NodeList
653 return len(self
._data
)
657 def getNamedItem(self
, name
):
659 Retrieves a node specified by name. Parameters:
660 name Name of a node to retrieve. Return Value A Node (of any
661 type) with the specified name, or None if the specified name
662 did not identify any node in the map.
664 if self
._data
.has_key(name
):
665 return self
._data
[name
]
669 create aliases for all above functions in the pythony way.
671 def _get_Length(self
):
672 return self
.getLength()
674 def _get_NamedItem(self
, name
):
675 return self
.getNamedItem(name
)
679 Attr interface - The Attr interface represents an attriubte in an
680 Element object. Attr objects inherit the Node Interface
683 def __init__(self
, name
, value
, specified
=1):
686 self
.specified
= specified
688 def getNodeName(self
):
690 The name of this node, depending on its type
696 Returns the name of this attribute.
700 def getNodeValue(self
):
702 The value of this node, depending on its type
706 def getNodeType(self
):
708 A code representing the type of the node.
710 return ATTRIBUTE_NODE
712 def getSpecified(self
):
714 If this attribute was explicitly given a value in the
715 original document, this is true; otherwise, it is false.
717 return self
.specified
720 create aliases for all above functions in the pythony way.
723 def _get_NodeName(self
):
724 return self
.getNodeName()
727 return self
.getName()
729 def _get_NodeValue(self
):
730 return self
.getNodeValue()
732 def _get_NodeType(self
):
733 return self
.getNodeType()
735 def _get_Specified(self
):
736 return self
.getSpecified()