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()