xmlifApi.py
Go to the documentation of this file.
00001 #
00002 # genxmlif, Release 0.9.0
00003 # file: xmlifapi.py
00004 #
00005 # API (interface) classes for generic interface package
00006 #
00007 # history:
00008 # 2007-06-29 rl   created, classes extracted from xmlifbase.py
00009 #
00010 # Copyright (c) 2005-2008 by Roland Leuthe.  All rights reserved.
00011 #
00012 # --------------------------------------------------------------------
00013 # The generic XML interface is
00014 #
00015 # Copyright (c) 2005-2008 by Roland Leuthe
00016 #
00017 # By obtaining, using, and/or copying this software and/or its
00018 # associated documentation, you agree that you have read, understood,
00019 # and will comply with the following terms and conditions:
00020 #
00021 # Permission to use, copy, modify, and distribute this software and
00022 # its associated documentation for any purpose and without fee is
00023 # hereby granted, provided that the above copyright notice appears in
00024 # all copies, and that both that copyright notice and this permission
00025 # notice appear in supporting documentation, and that the name of
00026 # the author not be used in advertising or publicity
00027 # pertaining to distribution of the software without specific, written
00028 # prior permission.
00029 #
00030 # THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
00031 # TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
00032 # ABILITY AND FITNESS.  IN NO EVENT SHALL THE AUTHOR
00033 # BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
00034 # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
00035 # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
00036 # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
00037 # OF THIS SOFTWARE.
00038 # --------------------------------------------------------------------
00039 
00040 __author__  = "Roland Leuthe <roland@leuthe-net.de>"
00041 __date__    = "08. August 2008"
00042 __version__ = "0.9.0"
00043 
00044 import string
00045 import os
00046 import re
00047 import copy
00048 from types      import TupleType, StringTypes
00049 from xml.dom    import EMPTY_PREFIX, EMPTY_NAMESPACE
00050 from xmlifUtils import processWhitespaceAction, NsNameTupleFactory, splitQName, nsNameToQName, escapeCdata, escapeAttribute
00051 
00052 
00053 ########################################
00054 # XML interface base class
00055 # All not implemented methods have to be overloaded by the derived class!!
00056 #
00057 
00058 class XmlInterfaceBase:
00059     """XML interface base class.
00060     
00061     All not implemented methods have to be overloaded by the derived class!!
00062     """
00063 
00064     def __init__(self, verbose, useCaching, processXInclude):
00065         """Constructor of class XmlInterfaceBase.
00066         
00067         Input parameter:
00068             'verbose':         0 or 1: controls verbose print output for module genxmlif
00069             'useCaching':      0 or 1: controls usage of caching for module genxmlif
00070             'processXInclude': 0 or 1: controls XInclude processing during parsing
00071         """
00072         
00073         self.verbose         = verbose
00074         self.useCaching      = useCaching
00075         self.processXInclude = processXInclude
00076 
00077         # set default wrapper classes
00078         self.setTreeWrapperClass (XmlTreeWrapper)
00079         self.setElementWrapperClass (XmlElementWrapper)
00080 
00081 
00082     def createXmlTree (self, namespace, xmlRootTagName, attributeDict={}, publicId=None, systemId=None):
00083         """Create a new XML TreeWrapper object (wrapper for DOM document or elementtree).
00084         
00085         Input parameter:
00086             'namespace':      not yet handled (for future use)
00087             'xmlRootTagName': specifies the tag name of the root element
00088             'attributeDict':  contains the attributes of the root node (optional)
00089             'publicId':       forwarded to contained DOM tree (unused for elementtree)
00090             'systemId':       forwarded to contained DOM tree (unused for elementtree)
00091         Returns the created XML tree wrapper object.
00092         Method has to be implemented by derived classes!
00093         """
00094          
00095         raise NotImplementedError
00096 
00097 
00098     def parse (self, filePath, baseUrl="", ownerDoc=None):
00099         """Call the XML parser for 'file'.
00100         
00101         Input parameter:
00102             'filePath': a file path or an URI
00103             'baseUrl':  if specified, it is used e.g. as base path for schema files referenced inside the XML file.
00104             'ownerDoc': only used in case of 4DOM (forwarded to 4DOM parser). 
00105         Returns the respective XML tree wrapper object for the parsed XML file.
00106         Method has to be implemented by derived classes!
00107         """
00108         
00109         raise NotImplementedError
00110 
00111 
00112     def parseString (self, text, baseUrl="", ownerDoc=None):
00113         """Call the XML parser for 'text'.
00114 
00115         Input parameter:
00116             'text':     contains the XML string to be parsed
00117             'baseUrl':  if specified, it is used e.g. as base path for schema files referenced inside the XML string.
00118             'ownerDoc': only used in case of 4DOM (forwarded to 4DOM parser). 
00119         Returns the respective XML tree wrapper object for the parsed XML 'text' string.
00120         Method has to be implemented by derived classes!
00121         """
00122         raise NotImplementedError
00123 
00124 
00125     def setTreeWrapperClass (self, treeWrapperClass):
00126         """Set the tree wrapper class which shall be used by this interface.
00127 
00128         Input parameter:
00129             treeWrapperClass:     tree wrapper class
00130         """
00131         self.treeWrapperClass = treeWrapperClass
00132 
00133 
00134     def setElementWrapperClass (self, elementWrapperClass):
00135         """Set the element wrapper classes which shall be used by this interface.
00136 
00137         Input parameter:
00138             elementWrapperClass:  element wrapper class
00139         """
00140         self.elementWrapperClass = elementWrapperClass
00141         
00142 
00143     def getXmlIfType (self):
00144         """Retrieve the type of the XML interface."""
00145         return self.xmlIfType
00146     
00147 
00148 ########################################
00149 # Tree wrapper API (interface class)
00150 #
00151 
00152 class XmlTreeWrapper:
00153     """XML tree wrapper API.
00154 
00155     Contains a DOM tree or an elementtree (depending on used XML parser)
00156     """
00157 
00158     def __init__(self, xmlIf, tree, useCaching):
00159         """Constructor of wrapper class XmlTreeWrapper.
00160         
00161         Input parameter:
00162             'xmlIf':      used XML interface class
00163             'tree':       DOM tree or elementtree which is wrapped by this object
00164             'useCaching': 1 if caching shall be used inside genxmlif, otherwise 0
00165         """
00166         self.xmlIf                   = xmlIf
00167         self.__tree                  = tree
00168         self.__useCaching            = useCaching
00169 
00170 
00171     def createElement (self, tupleOrLocalName, attributeDict=None, curNs=[]):
00172         """Create an ElementWrapper object.
00173         
00174         Input parameter:
00175             tupleOrLocalName: tag name of element node to be created 
00176                               (tuple of namespace and localName or only localName if no namespace is used)
00177             attributeDict:    attributes for this elements
00178             curNs:            namespaces for scope of this element
00179         Returns an ElementWrapper object containing the created element node.
00180         """
00181         nsName = NsNameTupleFactory(tupleOrLocalName)
00182         elementNode    = self.__tree.xmlIfExtCreateElement(nsName, attributeDict, curNs)
00183         return self.xmlIf.elementWrapperClass(elementNode, self, curNs)
00184 
00185 
00186     def cloneTree (self):
00187         """Creates a copy of a whole XML DOM tree."""
00188         rootElementWrapperCopy = self.getRootNode().cloneNode(deep=1)
00189         treeWrapperCopy = self.__class__(self.xmlIf, 
00190                                          self.__tree.xmlIfExtCloneTree(rootElementWrapperCopy.element), 
00191                                          self.__useCaching)
00192         for elementWrapper in rootElementWrapperCopy.getIterator():
00193             elementWrapper.treeWrapper = treeWrapperCopy
00194         return treeWrapperCopy
00195         
00196     
00197     def getRootNode (self):
00198         """Retrieve the wrapper object of the root element of the contained XML tree.
00199         
00200         Returns the ElementWrapper object of the root element.
00201         """
00202         return self.__tree.xmlIfExtGetRootNode().xmlIfExtElementWrapper
00203 
00204 
00205     def getTree (self):
00206         """Retrieve the contained XML tree.
00207         
00208         Returns the contained XML tree object (internal DOM tree wrapper or elementtree).
00209         """
00210         return self.__tree
00211 
00212     
00213     def printTree (self, prettyPrint=0, printElementValue=1, encoding=None):
00214         """Return the string representation of the contained XML tree.
00215         
00216         Input parameter:
00217             'prettyPrint':        aligns the columns of the attributes of childNodes
00218             'printElementValue':  controls if the lement values are printed or not.
00219         Returns a string with the string representation of the whole XML tree.
00220         """
00221         if not encoding:
00222             encoding = "utf-8"
00223         if encoding != "utf-8" and encoding != "us-ascii":
00224             text = "<?xml version='1.0' encoding='%s'?>\n" % encoding
00225         else:
00226             text = ""
00227         return text + self.getRootNode().printNode(deep=1, prettyPrint=prettyPrint, printElementValue=printElementValue, encoding=encoding)
00228 
00229 
00230     def useCaching (self):
00231         """Return 1 if caching should be used for the contained XML tree."""
00232         return self.__useCaching
00233 
00234 
00235     def setExternalCacheUsage (self, used):
00236         """Set external cache usage for the whole tree
00237            unlink commands are ignored if used by an external cache
00238 
00239            Input parameter:
00240                used:       0 or 1 (used by external cache)
00241         """
00242         self.getRootNode().setExternalCacheUsage (used, deep=1)
00243 
00244     
00245     def unlink (self):
00246         """Break circular references of the complete XML tree.
00247         
00248         To be called if the XML tree is not longer used => garbage collection!
00249         """
00250         self.getRootNode().unlink()
00251         
00252 
00253     def __str__ (self):
00254         """Return the string representation of the contained XML tree."""
00255         return self.printTree()
00256 
00257 
00258 
00259 ########################################
00260 # Element wrapper API (interface class)
00261 #
00262 
00263 class XmlElementWrapper:
00264     """XML element wrapper API.
00265 
00266     Contains a XML element node
00267     All not implemented methods have to be overloaded by the derived class!!
00268     """
00269 
00270     def __init__(self, element, treeWrapper, curNs=[], initAttrSeq=1):
00271         """Constructor of wrapper class XmlElementWrapper.
00272         
00273         Input parameter:
00274             element:       XML element node which is wrapped by this object
00275             treeWrapper:   XML tree wrapper class the current element belongs to
00276             curNs:         namespaces for scope of this element
00277         """
00278         self.element                        = element
00279         self.element.xmlIfExtElementWrapper = self
00280         self.treeWrapper                    = treeWrapper
00281         self.nodeUsedByExternalCache        = 0
00282         
00283         if self.__useCaching():
00284             self.__childrenCache = {}
00285             self.__firstChildCache = {}
00286             self.__qNameAttrCache = {}
00287 
00288         self.baseUrl = None
00289         self.absUrl = None
00290         self.filePath = None
00291         self.startLineNumber = None
00292         self.endLineNumber = None
00293         self.curNs = curNs[:]
00294         self.attributeSequence = []
00295 
00296         if initAttrSeq:
00297             self.attributeSequence = self.getAttributeDict().keys()
00298 
00299 
00300     def unlink (self):
00301         """Break circular references of this element and its children."""
00302         for childWrapper in self.getChildren():
00303             childWrapper.unlink()
00304         if not self.isUsedByExternalCache():
00305             self.element.xmlIfExtUnlink()
00306 
00307         
00308     def cloneNode (self, deep, cloneCallback=None):
00309         """Create a copy of the current element wrapper.
00310            The reference to the parent node is set to None!"""
00311         elementCopy = self.element.xmlIfExtCloneNode()
00312         elementWrapperCopy = self.__class__(elementCopy, self.treeWrapper, initAttrSeq=0)
00313         elementWrapperCopy.treeWrapper = None
00314         elementWrapperCopy.baseUrl = self.baseUrl
00315         elementWrapperCopy.absUrl = self.absUrl
00316         elementWrapperCopy.filePath = self.filePath
00317         elementWrapperCopy.startLineNumber = self.startLineNumber
00318         elementWrapperCopy.endLineNumber = self.endLineNumber
00319         elementWrapperCopy.curNs = self.curNs[:]
00320         elementWrapperCopy.attributeSequence = self.attributeSequence[:]
00321         if cloneCallback: cloneCallback(elementWrapperCopy)
00322         if deep:
00323             for childElement in self.element.xmlIfExtGetChildren():
00324                 childWrapperElementCopy = childElement.xmlIfExtElementWrapper.cloneNode(deep, cloneCallback)
00325                 childWrapperElementCopy.element.xmlIfExtSetParentNode(elementWrapperCopy.element)
00326                 elementWrapperCopy.element.xmlIfExtAppendChild(childWrapperElementCopy.element)
00327         return elementWrapperCopy
00328     
00329     
00330     def clearNodeCache (self):
00331         """Clear all caches used by this element wrapper which contains element wrapper references."""
00332         self.__clearChildrenCache()
00333 
00334 
00335     def isUsedByExternalCache (self):
00336         """Check if this node is used by an external cache.
00337            unlink commands are ignored if used by an external cache"""
00338         return self.nodeUsedByExternalCache
00339     
00340     
00341     def setExternalCacheUsage (self, used, deep=1):
00342         """Set external cache usage for this node and its children
00343            unlink commands are ignored if used by an external cache
00344 
00345            Input parameter:
00346                used:       0 or 1 (used by external cache)
00347                deep:       0 or 1: controls if the child elements are also marked as used by external cache
00348         """
00349         self.nodeUsedByExternalCache = used
00350         if deep:
00351             for childWrapper in self.getChildren():
00352                 childWrapper.setExternalCacheUsage (used, deep)
00353         
00354 
00355 
00356     ##########################################################
00357     #  attributes of the current node can be accessed via key operator
00358     
00359     def __getitem__(self, tupleOrAttrName):
00360         """Attributes of the contained element node can be accessed via key operator.
00361         
00362         Input parameter:
00363             tupleOrAttrName: name of the attribute (tuple of namespace and attributeName or only attributeName)
00364         Returns the attribute value.
00365         """
00366         attrValue = self.getAttribute (tupleOrAttrName)
00367         if attrValue != None:
00368             return attrValue
00369         else:
00370             raise AttributeError, "Attribute %s not found!" %(repr(tupleOrAttrName))
00371 
00372 
00373     def __setitem__(self, tupleOrAttrName, attributeValue):
00374         """Attributes of the contained element node can be accessed via key operator.
00375         
00376         Input parameter:
00377             tupleOrAttrName: name of the attribute (tuple of namespace and attributeName or only attributeName)
00378             attributeValue:  attribute value to be set
00379         """
00380         self.setAttribute (tupleOrAttrName, attributeValue)
00381 
00382 
00383 #++++++++++++ methods concerning the tag name ++++++++++++++++++++++++
00384 
00385     def getTagName (self):
00386         """Retrieve the (complete) tag name of the contained element node
00387         
00388         Returns the (complete) tag name of the contained element node
00389         """
00390         return self.element.xmlIfExtGetTagName()
00391 
00392 
00393     def getLocalName (self):
00394         """Retrieve the local name (without namespace) of the contained element node
00395         
00396         Returns the local name (without namespace) of the contained element node
00397         """
00398         
00399         try:
00400             return self.__localNameCache
00401         except:
00402             prefix, localName = splitQName (self.getTagName())
00403             if self.__useCaching():
00404                 self.__localNameCache = localName
00405         return localName
00406 
00407 
00408     def getNamespaceURI (self):
00409         """Retrieve the namespace URI of the contained element node
00410         
00411         Returns the namespace URI of the contained element node (None if no namespace is used).
00412         """
00413         try:
00414             return self.__nsUriCache
00415         except:
00416             prefix = self.element.xmlIfExtGetNamespaceURI()
00417             if self.__useCaching():
00418                 self.__nsUriCache = prefix 
00419             return prefix
00420 
00421 
00422     def getNsName (self):
00423         """Retrieve a tuple (namespace, localName) of the contained element node
00424         
00425         Returns a tuple (namespace, localName) of the contained element node (namespace is None if no namespace is used).
00426         """
00427         try:
00428             return self.__nsNameCache
00429         except:
00430             nsName = NsNameTupleFactory( (self.getNamespaceURI(), self.getLocalName()) )
00431             if self.__useCaching():
00432                 self.__nsNameCache = nsName
00433             return nsName
00434 
00435 
00436     def getQName (self):
00437         """Retrieve a string prefix and localName of the contained element node
00438 
00439         Returns a string "prefix:localName" of the contained element node
00440         """
00441         return self.nsName2QName(self.getNsName())
00442 
00443 
00444     def getPrefix (self):
00445         """Retrieve the namespace prefix of the contained element node
00446         
00447         Returns the namespace prefix of the contained element node (None if no namespace is used).
00448         """
00449         return self.getNsPrefix(self.getNsName())
00450 
00451 
00452 #++++++++++++ methods concerning print support ++++++++++++++++++++++++
00453 
00454     def __str__ (self):
00455         """Retrieve the textual representation of the contained element node."""
00456         return self.printNode()
00457 
00458 
00459     def printNode (self, indent="", deep=0, prettyPrint=0, attrMaxLengthDict={}, printElementValue=1, encoding=None):
00460         """Retrieve the textual representation of the contained element node.
00461         
00462         Input parameter:
00463             indent:             indentation to be used for string representation
00464             deep:               0 or 1: controls if the child element nodes are also printed
00465             prettyPrint:        aligns the columns of the attributes of childNodes
00466             attrMaxLengthDict:  dictionary containing the length of the attribute values (used for prettyprint)
00467             printElementValue:  0 or 1: controls if the element value is printed
00468         Returns the string representation
00469         """
00470         patternXmlTagShort = '''\
00471 %(indent)s<%(qName)s%(attributeString)s/>%(tailText)s%(lf)s'''
00472 
00473         patternXmlTagLong = '''\
00474 %(indent)s<%(qName)s%(attributeString)s>%(elementValueString)s\
00475 %(lf)s%(subTreeString)s\
00476 %(indent)s</%(qName)s>%(tailText)s%(lf)s'''
00477         
00478         subTreeStringList = []
00479         tailText = ""
00480         addIndent = ""
00481         lf = ""
00482         if deep:
00483             childAttrMaxLengthDict = {}
00484             if prettyPrint:
00485                 for childNode in self.getChildren():
00486                     childNode.__updateAttrMaxLengthDict(childAttrMaxLengthDict)
00487                 lf = "\n"
00488                 addIndent = "    "
00489             for childNode in self.getChildren():
00490                 subTreeStringList.append (childNode.printNode(indent + addIndent, deep, prettyPrint, childAttrMaxLengthDict, printElementValue))
00491             tailText = escapeCdata(self.element.xmlIfExtGetElementTailText(), encoding)
00492         
00493         attributeStringList = []
00494         for attrName in self.getAttributeList():
00495             attrValue = escapeAttribute(self.getAttribute(attrName), encoding)
00496             if prettyPrint:
00497                 try:
00498                     align = attrMaxLengthDict[attrName]
00499                 except:
00500                     align = len(attrValue)
00501             else:
00502                 align = len(attrValue)
00503             qName = self.nsName2QName(attrName)
00504             attributeStringList.append (' %s="%s"%*s' %(qName, attrValue, align - len(attrValue), ""))
00505         attributeString = string.join (attributeStringList, "")
00506 
00507         qName = self.getQName()
00508         if printElementValue:
00509             if deep:
00510                 elementValueString = escapeCdata(self.element.xmlIfExtGetElementText(), encoding)
00511             else:
00512                 elementValueString = escapeCdata(self.getElementValue(ignoreEmtpyStringFragments=1), encoding)
00513         else:
00514             elementValueString = ""
00515 
00516         if subTreeStringList == [] and elementValueString == "":
00517             printPattern = patternXmlTagShort
00518         else:
00519             if subTreeStringList != []:
00520                 subTreeString = string.join (subTreeStringList, "")
00521             else:
00522                 subTreeString = ""
00523             printPattern = patternXmlTagLong
00524         return printPattern % vars()
00525 
00526 
00527 #++++++++++++ methods concerning the parent of the current node ++++++++++++++++++++++++
00528 
00529     def getParentNode (self):
00530         """Retrieve the ElementWrapper object of the parent element node.
00531 
00532         Returns the ElementWrapper object of the parent element node.
00533         """
00534         parent = self.element.xmlIfExtGetParentNode()
00535         if parent != None:
00536             return parent.xmlIfExtElementWrapper
00537         else:
00538             return None
00539 
00540 
00541 #++++++++++++ methods concerning the children of the current node ++++++++++++++++++++++++
00542 
00543 
00544     def getChildren (self, tagFilter=None):
00545         """Retrieve the ElementWrapper objects of the children element nodes.
00546         
00547         Input parameter:
00548             tagFilter: retrieve only the children with this tag name ('*' or None returns all children)
00549         Returns all children of this element node which match 'tagFilter' (list)
00550         """
00551         if tagFilter in (None, '*', (None, '*')):
00552             children = self.element.xmlIfExtGetChildren()
00553         elif tagFilter[1] == '*':
00554             # handle (namespace, '*')
00555             children = filter(lambda child:child.xmlIfExtElementWrapper.getNamespaceURI() == tagFilter[0], 
00556                               self.element.xmlIfExtGetChildren())
00557         else:
00558             nsNameFilter = NsNameTupleFactory(tagFilter)
00559             try:
00560                 children = self.__childrenCache[nsNameFilter]
00561             except:
00562                 children = self.element.xmlIfExtGetChildren(nsNameFilter)
00563                 if self.__useCaching():
00564                     self.__childrenCache[nsNameFilter] = children
00565 
00566         return map(lambda child: child.xmlIfExtElementWrapper, children)
00567 
00568 
00569     def getChildrenNS (self, namespaceURI, tagFilter=None):
00570         """Retrieve the ElementWrapper objects of the children element nodes using a namespace.
00571         
00572         Input parameter:
00573             namespaceURI: the namespace URI of the children or None
00574             tagFilter:    retrieve only the children with this localName ('*' or None returns all children)
00575         Returns all children of this element node which match 'namespaceURI' and 'tagFilter' (list)
00576         """
00577         return self.getChildren((namespaceURI, tagFilter))
00578 
00579 
00580     def getChildrenWithKey (self, tagFilter=None, keyAttr=None, keyValue=None):
00581         """Retrieve the ElementWrapper objects of the children element nodes.
00582         
00583         Input parameter:
00584             tagFilter: retrieve only the children with this tag name ('*' or None returns all children)
00585             keyAttr:   name of the key attribute
00586             keyValue:  value of the key
00587         Returns all children of this element node which match 'tagFilter' (list)
00588         """
00589         children = self.getChildren(tagFilter)
00590         return filter(lambda child:child[keyAttr]==keyValue, children)
00591     
00592     
00593     def getFirstChild (self, tagFilter=None):
00594         """Retrieve the ElementWrapper objects of the first child element node.
00595         
00596         Input parameter:
00597             tagFilter: retrieve only the first child with this tag name ('*' or None: no filter)
00598         Returns the first child of this element node which match 'tagFilter'
00599         or None if no suitable child element was found
00600         """
00601         if tagFilter in (None, '*', (None, '*')):
00602             element = self.element.xmlIfExtGetFirstChild()
00603         elif tagFilter[1] == '*':
00604             # handle (namespace, '*')
00605             children = filter(lambda child:child.xmlIfExtElementWrapper.getNamespaceURI() == tagFilter[0], 
00606                               self.element.xmlIfExtGetChildren())
00607             try:
00608                 element = children[0]
00609             except:
00610                 element = None
00611         else:
00612             nsNameFilter = NsNameTupleFactory(tagFilter)
00613             try:
00614                 element = self.__firstChildCache[nsNameFilter]
00615             except:
00616                 element = self.element.xmlIfExtGetFirstChild(nsNameFilter)
00617                 if self.__useCaching():
00618                     self.__firstChildCache[nsNameFilter] = element
00619 
00620         if element != None:
00621             return element.xmlIfExtElementWrapper
00622         else:
00623             return None
00624 
00625 
00626     def getFirstChildNS (self, namespaceURI, tagFilter=None):
00627         """Retrieve the ElementWrapper objects of the first child element node using a namespace.
00628         
00629         Input parameter:
00630             namespaceURI: the namespace URI of the children or None
00631             tagFilter:    retrieve only the first child with this localName ('*' or None: no filter)
00632         Returns the first child of this element node which match 'namespaceURI' and 'tagFilter'
00633         or None if no suitable child element was found
00634         """
00635         return self.getFirstChild ((namespaceURI, tagFilter))
00636 
00637 
00638     def getFirstChildWithKey (self, tagFilter=None, keyAttr=None, keyValue=None):
00639         """Retrieve the ElementWrapper objects of the children element nodes.
00640         
00641         Input parameter:
00642             tagFilter: retrieve only the children with this tag name ('*' or None returns all children)
00643             keyAttr:   name of the key attribute
00644             keyValue:  value of the key
00645         Returns all children of this element node which match 'tagFilter' (list)
00646         """
00647         children = self.getChildren(tagFilter)
00648         childrenWithKey = filter(lambda child:child[keyAttr]==keyValue, children)
00649         if childrenWithKey != []:
00650             return childrenWithKey[0]
00651         else:
00652             return None
00653 
00654     
00655     def getElementsByTagName (self, tagFilter=None):
00656         """Retrieve all descendant ElementWrapper object of current node whose tag name match 'tagFilter'.
00657 
00658         Input parameter:
00659             tagFilter: retrieve only the children with this tag name ('*' or None returns all descendants)
00660         Returns all descendants of this element node which match 'tagFilter' (list)
00661         """
00662         if tagFilter in (None, '*', (None, '*'), (None, None)):
00663             descendants = self.element.xmlIfExtGetElementsByTagName()
00664             
00665         elif tagFilter[1] == '*':
00666             # handle (namespace, '*')
00667             descendants = filter(lambda desc:desc.xmlIfExtElementWrapper.getNamespaceURI() == tagFilter[0], 
00668                                  self.element.xmlIfExtGetElementsByTagName())
00669         else:
00670             nsNameFilter = NsNameTupleFactory(tagFilter)
00671             descendants = self.element.xmlIfExtGetElementsByTagName(nsNameFilter)
00672 
00673         return map(lambda descendant: descendant.xmlIfExtElementWrapper, descendants)
00674 
00675 
00676     def getElementsByTagNameNS (self, namespaceURI, tagFilter=None):
00677         """Retrieve all descendant ElementWrapper object of current node whose tag name match 'namespaceURI' and 'tagFilter'.
00678         
00679         Input parameter:
00680             namespaceURI: the namespace URI of the descendants or None
00681             tagFilter:    retrieve only the descendants with this localName ('*' or None returns all descendants)
00682         Returns all descendants of this element node which match 'namespaceURI' and 'tagFilter' (list)
00683         """
00684         return self.getElementsByTagName((namespaceURI, tagFilter))
00685 
00686 
00687     def getIterator (self, tagFilter=None):
00688         """Creates a tree iterator.  The iterator loops over this element
00689            and all subelements, in document order, and returns all elements
00690            whose tag name match 'tagFilter'.
00691 
00692         Input parameter:
00693             tagFilter: retrieve only the children with this tag name ('*' or None returns all descendants)
00694         Returns all element nodes which match 'tagFilter' (list)
00695         """
00696         if tagFilter in (None, '*', (None, '*'), (None, None)):
00697             matchingElements = self.element.xmlIfExtGetIterator()
00698         elif tagFilter[1] == '*':
00699             # handle (namespace, '*')
00700             matchingElements = filter(lambda desc:desc.xmlIfExtElementWrapper.getNamespaceURI() == tagFilter[0], 
00701                                       self.element.xmlIfExtGetIterator())
00702         else:
00703             nsNameFilter = NsNameTupleFactory(tagFilter)
00704             matchingElements = self.element.xmlIfExtGetIterator(nsNameFilter)
00705 
00706         return map(lambda e: e.xmlIfExtElementWrapper, matchingElements)
00707 
00708 
00709     def appendChild (self, tupleOrLocalNameOrElement, attributeDict={}):
00710         """Append an element node to the children of the current node.
00711 
00712         Input parameter:
00713             tupleOrLocalNameOrElement: (namespace, localName) or tagName or ElementWrapper object of the new child
00714             attributeDict:             attribute dictionary containing the attributes of the new child (optional)
00715         If not an ElementWrapper object is given, a new ElementWrapper object is created with tupleOrLocalName
00716         Returns the ElementWrapper object of the new child.
00717         """
00718         if not isinstance(tupleOrLocalNameOrElement, self.__class__):
00719             childElementWrapper = self.__createElement (tupleOrLocalNameOrElement, attributeDict)
00720         else:
00721             childElementWrapper = tupleOrLocalNameOrElement
00722         self.element.xmlIfExtAppendChild (childElementWrapper.element)
00723         self.__clearChildrenCache(childElementWrapper.getNsName())
00724         return childElementWrapper
00725 
00726 
00727     def insertBefore (self, tupleOrLocalNameOrElement, refChild, attributeDict={}):
00728         """Insert an child element node before the given reference child of the current node.
00729 
00730         Input parameter:
00731             tupleOrLocalNameOrElement: (namespace, localName) or tagName or ElementWrapper object of the new child
00732             refChild:                  reference child ElementWrapper object
00733             attributeDict:             attribute dictionary containing the attributes of the new child (optional)
00734         If not an ElementWrapper object is given, a new ElementWrapper object is created with tupleOrLocalName
00735         Returns the ElementWrapper object of the new child.
00736         """
00737         if not isinstance(tupleOrLocalNameOrElement, self.__class__):
00738             childElementWrapper = self.__createElement (tupleOrLocalNameOrElement, attributeDict)
00739         else:
00740             childElementWrapper = tupleOrLocalNameOrElement
00741         if refChild == None:
00742             self.appendChild (childElementWrapper)
00743         else:
00744             self.element.xmlIfExtInsertBefore(childElementWrapper.element, refChild.element)
00745             self.__clearChildrenCache(childElementWrapper.getNsName())
00746         return childElementWrapper
00747 
00748 
00749     def removeChild (self, childElementWrapper):
00750         """Remove the given child element node from the children of the current node.
00751 
00752         Input parameter:
00753             childElementWrapper:  ElementWrapper object to be removed
00754         """
00755         self.element.xmlIfExtRemoveChild(childElementWrapper.element)
00756         self.__clearChildrenCache(childElementWrapper.getNsName())
00757 
00758 
00759     def insertSubtree (self, refChildWrapper, subTreeWrapper, insertSubTreeRootNode=1):
00760         """Insert the given subtree before 'refChildWrapper' ('refChildWrapper' is not removed!)
00761         
00762         Input parameter:
00763             refChildWrapper:       reference child ElementWrapper object
00764             subTreeWrapper:        subtree wrapper object which contains the subtree to be inserted
00765             insertSubTreeRootNode: if 1, root node of subtree is inserted into parent tree, otherwise not
00766         """ 
00767         if refChildWrapper != None:
00768             self.element.xmlIfExtInsertSubtree (refChildWrapper.element, subTreeWrapper.getTree(), insertSubTreeRootNode)
00769         else:
00770             self.element.xmlIfExtInsertSubtree (None, subTreeWrapper.getTree(), insertSubTreeRootNode)
00771         self.__clearChildrenCache()
00772 
00773 
00774 
00775     def replaceChildBySubtree (self, childElementWrapper, subTreeWrapper, insertSubTreeRootNode=1):
00776         """Replace child element node by XML subtree (e.g. expanding included XML files)
00777 
00778         Input parameter:
00779             childElementWrapper:   ElementWrapper object to be replaced
00780             subTreeWrapper:        XML subtree wrapper object to  be inserted
00781             insertSubTreeRootNode: if 1, root node of subtree is inserted into parent tree, otherwise not
00782         """
00783         self.insertSubtree (childElementWrapper, subTreeWrapper, insertSubTreeRootNode)
00784         self.removeChild(childElementWrapper)
00785 
00786 
00787 #++++++++++++ methods concerning the attributes of the current node ++++++++++++++++++++++++
00788 
00789     def getAttributeDict (self):
00790         """Retrieve a dictionary containing all attributes of the current element node.
00791         
00792         Returns a dictionary (copy) containing all attributes of the current element node.
00793         """
00794         return self.element.xmlIfExtGetAttributeDict()
00795 
00796 
00797     def getAttributeList (self):
00798         """Retrieve a list containing all attributes of the current element node
00799            in the sequence specified in the input XML file.
00800         
00801         Returns a list (copy) containing all attributes of the current element node
00802         in the sequence specified in the input XML file (TODO: does currently not work for 4DOM/pyXML interface).
00803         """
00804         attrList = map(lambda a: NsNameTupleFactory(a), self.attributeSequence)
00805         return attrList
00806 
00807 
00808     def getAttribute (self, tupleOrAttrName):
00809         """Retrieve an attribute value of the current element node.
00810         
00811         Input parameter:
00812             tupleOrAttrName:  tuple '(namespace, attributeName)' or 'attributeName' if no namespace is used
00813         Returns the value of the specified attribute.
00814         """
00815         nsName = NsNameTupleFactory(tupleOrAttrName)
00816         return self.element.xmlIfExtGetAttribute(nsName)
00817 
00818 
00819     def getAttributeOrDefault (self, tupleOrAttrName, defaultValue):
00820         """Retrieve an attribute value of the current element node or the given default value if the attribute doesn't exist.
00821         
00822         Input parameter:
00823             tupleOrAttrName:  tuple '(namespace, attributeName)' or 'attributeName' if no namespace is used
00824         Returns the value of the specified attribute or the given default value if the attribute doesn't exist.
00825         """
00826         attributeValue = self.getAttribute (tupleOrAttrName)
00827         if attributeValue == None:
00828             attributeValue = defaultValue
00829         return attributeValue
00830 
00831 
00832     def getQNameAttribute (self, tupleOrAttrName):
00833         """Retrieve a QName attribute value of the current element node.
00834         
00835         Input parameter:
00836             tupleOrAttrName:  tuple '(namespace, attributeName)' or 'attributeName' if no namespace is used
00837         Returns the value of the specified QName attribute as tuple (namespace, localName),
00838         i.e. the prefix is converted into the corresponding namespace value.
00839         """
00840         nsNameAttrName = NsNameTupleFactory(tupleOrAttrName)
00841         try:
00842             return self.__qNameAttrCache[nsNameAttrName]
00843         except:
00844             qNameValue = self.getAttribute (nsNameAttrName)
00845             nsNameValue = self.qName2NsName(qNameValue, useDefaultNs=1)
00846             if self.__useCaching():
00847                 self.__qNameAttrCache[nsNameAttrName] = nsNameValue
00848             return nsNameValue
00849 
00850 
00851     def hasAttribute (self, tupleOrAttrName):
00852         """Checks if the requested attribute exist for the current element node.
00853         
00854         Returns 1 if the attribute exists, otherwise 0.
00855         """
00856         nsName = NsNameTupleFactory(tupleOrAttrName)
00857         attrValue = self.element.xmlIfExtGetAttribute(nsName)
00858         if attrValue != None:
00859             return 1
00860         else:
00861             return 0
00862 
00863 
00864     def setAttribute (self, tupleOrAttrName, attributeValue):
00865         """Sets an attribute value of the current element node. 
00866         If the attribute does not yet exist, it will be created.
00867                
00868         Input parameter:
00869             tupleOrAttrName:  tuple '(namespace, attributeName)' or 'attributeName' if no namespace is used
00870             attributeValue:   attribute value to be set
00871         """
00872         if not isinstance(attributeValue, StringTypes):
00873             raise TypeError, "%s (attribute %s) must be a string!" %(repr(attributeValue), repr(tupleOrAttrName))
00874 
00875         nsNameAttrName = NsNameTupleFactory(tupleOrAttrName)
00876         if nsNameAttrName not in self.attributeSequence:
00877             self.attributeSequence.append(nsNameAttrName)
00878 
00879         if self.__useCaching():
00880             if self.__qNameAttrCache.has_key(nsNameAttrName):
00881                 del self.__qNameAttrCache[nsNameAttrName]
00882 
00883         self.element.xmlIfExtSetAttribute(nsNameAttrName, attributeValue, self.getCurrentNamespaces())
00884 
00885 
00886     def setAttributeDefault (self, tupleOrAttrName, defaultValue):
00887         """Create attribute and set value to default if it does not yet exist for the current element node. 
00888         If the attribute is already existing nothing is done.
00889                
00890         Input parameter:
00891             tupleOrAttrName:  tuple '(namespace, attributeName)' or 'attributeName' if no namespace is used
00892             defaultValue:     default attribute value to be set
00893         """
00894         if not self.hasAttribute(tupleOrAttrName):
00895             self.setAttribute(tupleOrAttrName, defaultValue)
00896 
00897 
00898     def removeAttribute (self, tupleOrAttrName):
00899         """Removes an attribute from the current element node. 
00900         No exception is raised if there is no matching attribute.
00901                
00902         Input parameter:
00903             tupleOrAttrName:  tuple '(namespace, attributeName)' or 'attributeName' if no namespace is used
00904         """
00905         nsNameAttrName = NsNameTupleFactory(tupleOrAttrName)
00906 
00907         if self.__useCaching():
00908             if self.__qNameAttrCache.has_key(nsNameAttrName):
00909                 del self.__qNameAttrCache[nsNameAttrName]
00910 
00911         self.element.xmlIfExtRemoveAttribute(nsNameAttrName)
00912 
00913 
00914     def processWsAttribute (self, tupleOrAttrName, wsAction):
00915         """Process white space action for the specified attribute according to requested 'wsAction'.
00916         
00917         Input parameter:
00918             tupleOrAttrName:  tuple '(namespace, attributeName)' or 'attributeName' if no namespace is used
00919             wsAction:         'collapse':  substitute multiple whitespace characters by a single ' '
00920                               'replace':   substitute each whitespace characters by a single ' '
00921         """
00922         attributeValue = self.getAttribute(tupleOrAttrName)
00923         newValue = processWhitespaceAction (attributeValue, wsAction)
00924         if newValue != attributeValue:
00925             self.setAttribute(tupleOrAttrName, newValue)
00926         return newValue
00927     
00928 
00929 #++++++++++++ methods concerning the content of the current node ++++++++++++++++++++++++
00930 
00931     def getElementValue (self, ignoreEmtpyStringFragments=0):
00932         """Retrieve the content of the current element node.
00933         
00934         Returns the content of the current element node as string.
00935         The content of multiple text nodes / CDATA nodes are concatenated to one string.
00936 
00937         Input parameter:
00938             ignoreEmtpyStringFragments:   if 1, text nodes containing only whitespaces are ignored
00939         """
00940         return "".join (self.getElementValueFragments(ignoreEmtpyStringFragments))
00941 
00942 
00943     def getElementValueFragments (self, ignoreEmtpyStringFragments=0):
00944         """Retrieve the content of the current element node as value fragment list.
00945         
00946         Returns the content of the current element node as list of string fragments.
00947         Each list element represents one text nodes / CDATA node.
00948 
00949         Input parameter:
00950             ignoreEmtpyStringFragments:   if 1, text nodes containing only whitespaces are ignored
00951         
00952         Method has to be implemented by derived classes!
00953         """
00954         return self.element.xmlIfExtGetElementValueFragments (ignoreEmtpyStringFragments)
00955 
00956 
00957     def setElementValue (self, elementValue):
00958         """Set the content of the current element node.
00959         
00960         Input parameter:
00961             elementValue:   string containing the new element value
00962         If multiple text nodes / CDATA nodes are existing, 'elementValue' is set 
00963         for the first text node / CDATA node. All other text nodes /CDATA nodes are set to ''. 
00964         """
00965         self.element.xmlIfExtSetElementValue(elementValue)
00966 
00967 
00968     def processWsElementValue (self, wsAction):
00969         """Process white space action for the content of the current element node according to requested 'wsAction'.
00970         
00971         Input parameter:
00972             wsAction:         'collapse':  substitute multiple whitespace characters by a single ' '
00973                               'replace':   substitute each whitespace characters by a single ' '
00974         """
00975         self.element.xmlIfExtProcessWsElementValue(wsAction)
00976         return self.getElementValue()
00977         
00978 
00979 #++++++++++++ methods concerning the info about the current node in the XML file ++++++++++++++++++++
00980 
00981 
00982     def getStartLineNumber (self):
00983         """Retrieve the start line number of the current element node.
00984         
00985         Returns the start line number of the current element node in the XML file
00986         """
00987         return self.startLineNumber
00988 
00989 
00990     def getEndLineNumber (self):
00991         """Retrieve the end line number of the current element node.
00992         
00993         Returns the end line number of the current element node in the XML file
00994         """
00995         return self.endLineNumber
00996 
00997 
00998     def getAbsUrl (self):
00999         """Retrieve the absolute URL of the XML file the current element node belongs to.
01000         
01001         Returns the absolute URL of the XML file the current element node belongs to.
01002         """
01003         return self.absUrl
01004 
01005 
01006     def getBaseUrl (self):
01007         """Retrieve the base URL of the XML file the current element node belongs to.
01008         
01009         Returns the base URL of the XML file the current element node belongs to.
01010         """
01011         return self.baseUrl
01012 
01013 
01014     def getFilePath (self):
01015         """Retrieve the file path of the XML file the current element node belongs to.
01016         
01017         Returns the file path of the XML file the current element node belongs to.
01018         """
01019         return self.filePath
01020 
01021 
01022     def getLocation (self, end=0, fullpath=0):
01023         """Retrieve a string containing file name and line number of the current element node.
01024         
01025         Input parameter:
01026             end:      1 if end line number shall be shown, 0 for start line number
01027             fullpath: 1 if the full path of the XML file shall be shown, 0 for only the file name
01028         Returns a string containing file name and line number of the current element node.
01029         (e.g. to be used for traces or error messages)
01030         """
01031         lineMethod = (self.getStartLineNumber, self.getEndLineNumber)
01032         pathFunc = (os.path.basename, os.path.abspath)
01033         return "%s, %d" % (pathFunc[fullpath](self.getFilePath()), lineMethod[end]())
01034 
01035 
01036 #++++++++++++ miscellaneous methods concerning namespaces ++++++++++++++++++++
01037 
01038 
01039     def getCurrentNamespaces (self):
01040         """Retrieve the namespace prefixes visible for the current element node
01041         
01042         Returns a list of the namespace prefixes visible for the current node.
01043         """
01044         return self.curNs
01045 
01046 
01047     def qName2NsName (self, qName, useDefaultNs):
01048         """Convert a qName 'prefix:localName' to a tuple '(namespace, localName)'.
01049         
01050         Input parameter:
01051             qName:         qName to be converted
01052             useDefaultNs:  1 if default namespace shall be used
01053         Returns the corresponding tuple '(namespace, localName)' for 'qName'.
01054         """
01055         if qName != None:
01056             qNamePrefix, qNameLocalName = splitQName (qName)
01057             for prefix, namespaceURI in self.getCurrentNamespaces():
01058                 if qNamePrefix == prefix:
01059                     if prefix != EMPTY_PREFIX or useDefaultNs:
01060                         nsName = (namespaceURI, qNameLocalName)
01061                         break
01062             else:
01063                 if qNamePrefix == None:
01064                     nsName = (EMPTY_NAMESPACE, qNameLocalName)
01065                 else:
01066                     raise ValueError, "Namespace prefix '%s' not bound to a namespace!" % (qNamePrefix)
01067         else:
01068             nsName = (None, None)
01069         return NsNameTupleFactory(nsName)
01070 
01071 
01072     def nsName2QName (self, nsLocalName):
01073         """Convert a tuple '(namespace, localName)' to a string 'prefix:localName'
01074         
01075         Input parameter:
01076             nsLocalName:   tuple '(namespace, localName)' to be converted
01077         Returns the corresponding string 'prefix:localName' for 'nsLocalName'.
01078         """
01079         qName = nsNameToQName (nsLocalName, self.getCurrentNamespaces())
01080         if qName == "xmlns:None": qName = "xmlns"
01081         return qName
01082 
01083 
01084     def getNamespace (self, qName):
01085         """Retrieve namespace for a qName 'prefix:localName'.
01086         
01087         Input parameter:
01088             qName:         qName 'prefix:localName'
01089         Returns the corresponding namespace for the prefix of 'qName'.
01090         """
01091         if qName != None:
01092             qNamePrefix, qNameLocalName = splitQName (qName)
01093             for prefix, namespaceURI in self.getCurrentNamespaces():
01094                 if qNamePrefix == prefix:
01095                     namespace = namespaceURI
01096                     break
01097             else:
01098                 if qNamePrefix == None:
01099                     namespace = EMPTY_NAMESPACE
01100                 else:
01101                     raise LookupError, "Namespace for QName '%s' not found!" % (qName)
01102         else:
01103             namespace = EMPTY_NAMESPACE
01104         return namespace
01105 
01106 
01107     def getNsPrefix (self, nsLocalName):
01108         """Retrieve prefix for a tuple '(namespace, localName)'.
01109         
01110         Input parameter:
01111             nsLocalName:     tuple '(namespace, localName)'
01112         Returns the corresponding prefix for the namespace of 'nsLocalName'.
01113         """
01114         ns = nsLocalName[0]
01115         for prefix, namespace in self.getCurrentNamespaces():
01116             if ns == namespace:
01117                 return prefix
01118         else:
01119             if ns == None:
01120                 return None
01121             else:
01122                 raise LookupError, "Prefix for namespaceURI '%s' not found!" % (ns)
01123 
01124 
01125 #++++++++++++ limited XPath support ++++++++++++++++++++
01126 
01127     def getXPath (self, xPath, namespaceRef=None, useDefaultNs=1, attrIgnoreList=[]):
01128         """Retrieve node list or attribute list for specified XPath
01129         
01130         Input parameter:
01131             xPath:           string containing xPath specification
01132             namespaceRef:    scope for namespaces (default is own element node)
01133             useDefaultNs:    1, if default namespace shall be used if no prefix is available
01134             attrIgnoreList:  list of attributes to be ignored if wildcard is specified for attributes
01135 
01136         Returns all nodes which match xPath specification or
01137         list of attribute values if xPath specifies an attribute
01138         """
01139         return self.getXPathList(xPath, namespaceRef, useDefaultNs, attrIgnoreList)[0]
01140 
01141 
01142     def getXPathList (self, xPath, namespaceRef=None, useDefaultNs=1, attrIgnoreList=[]):
01143         """Retrieve node list or attribute list for specified XPath
01144         
01145         Input parameter:
01146             xPath:           string containing xPath specification
01147             namespaceRef:    scope for namespaces (default is own element node)
01148             useDefaultNs:    1, if default namespace shall be used if no prefix is available
01149             attrIgnoreList:  list of attributes to be ignored if wildcard is specified for attributes
01150 
01151         Returns tuple (completeChildList, attrNodeList, attrNsNameFirst).
01152         completeChildList: contains all child node which match xPath specification or
01153                            list of attribute values if xPath specifies an attribute
01154         attrNodeList:      contains all child nodes where the specified attribute was found
01155         attrNsNameFirst:   contains the name of the first attribute which was found
01156         TODO: Re-design namespace and attribute handling of this method
01157         """
01158         reChild     = re.compile('child *::')
01159         reAttribute = re.compile('attribute *::')
01160         if namespaceRef == None: namespaceRef = self
01161         xPath = reChild.sub('./', xPath)
01162         xPath = reAttribute.sub('@', xPath)
01163         xPathList = string.split (xPath, "|")
01164         completeChildDict = {}
01165         completeChildList = []
01166         attrNodeList = []
01167         attrNsNameFirst = None
01168         for xRelPath in xPathList:
01169             xRelPath = string.strip(xRelPath)
01170             descendantOrSelf = 0
01171             if xRelPath[:3] == ".//":
01172                 descendantOrSelf = 1
01173                 xRelPath = xRelPath[3:]
01174             xPathLocalStepList = string.split (xRelPath, "/")
01175             childList = [self, ]
01176             for localStep in xPathLocalStepList:
01177                 localStep = string.strip(localStep)
01178                 stepChildList = []
01179                 if localStep == "":
01180                     raise IOError ("Invalid xPath '%s'!" %(xRelPath))
01181                 elif localStep == ".":
01182                     continue
01183                 elif localStep[0] == '@':
01184                     if len(localStep) == 1:
01185                         raise ValueError ("Attribute name is missing in xPath!")
01186                     if descendantOrSelf:
01187                         childList = self.getElementsByTagName()
01188                     attrName = localStep[1:]
01189                     for childNode in childList:
01190                         if attrName == '*':
01191                             attrNodeList.append (childNode)
01192                             attrDict = childNode.getAttributeDict()
01193                             for attrIgnore in attrIgnoreList:
01194                                 if attrDict.has_key(attrIgnore):
01195                                     del attrDict[attrIgnore]
01196                             stepChildList.extend(attrDict.values())
01197                             try:
01198                                 attrNsNameFirst = attrDict.keys()[0]
01199                             except:
01200                                 pass
01201                         else:
01202                             attrNsName = namespaceRef.qName2NsName (attrName, useDefaultNs=0)
01203                             if attrNsName[1] == '*':
01204                                 for attr in childNode.getAttributeDict().keys():
01205                                     if attr[0] == attrNsName[0]:
01206                                         if attrNodeList == []:
01207                                             attrNsNameFirst = attrNsName
01208                                         attrNodeList.append (childNode)
01209                                         stepChildList.append (childNode.getAttribute(attr))
01210                             elif childNode.hasAttribute(attrNsName):
01211                                 if attrNodeList == []:
01212                                     attrNsNameFirst = attrNsName
01213                                 attrNodeList.append (childNode)
01214                                 stepChildList.append (childNode.getAttribute(attrNsName))
01215                     childList = stepChildList
01216                 else:
01217                     nsLocalName = namespaceRef.qName2NsName (localStep, useDefaultNs=useDefaultNs)
01218                     if descendantOrSelf:
01219                         descendantOrSelf = 0
01220                         if localStep == "*":
01221                             stepChildList = self.getElementsByTagName()
01222                         else:
01223                             stepChildList = self.getElementsByTagName(nsLocalName)
01224                     else:
01225                         for childNode in childList:
01226                             if localStep == "*":
01227                                 stepChildList.extend (childNode.getChildren())
01228                             else:
01229                                 stepChildList.extend (childNode.getChildrenNS(nsLocalName[0], nsLocalName[1]))
01230                     childList = stepChildList
01231             # filter duplicated childs
01232             for child in childList:
01233                 try:
01234                     childKey = child.element
01235                 except:
01236                     childKey = child
01237                 if not completeChildDict.has_key(childKey):
01238                     completeChildList.append(child)
01239                     completeChildDict[childKey] = 1
01240         return completeChildList, attrNodeList, attrNsNameFirst
01241 
01242 
01243     ###############################################################
01244     # PRIVATE methods
01245     ###############################################################
01246 
01247     def __createElement (self, tupleOrLocalName, attributeDict):
01248         """Create a new ElementWrapper object.
01249         
01250         Input parameter:
01251             tupleOrLocalName: tuple '(namespace, localName)' or 'localName' if no namespace is used
01252             attributeDict:    dictionary which contains the attributes and their values of the element node to be created
01253         Returns the created ElementWrapper object
01254         """
01255         childElementWrapper = self.treeWrapper.createElement (tupleOrLocalName, attributeDict, self.curNs[:]) # TODO: when to be adapted???)
01256         childElementWrapper.element.xmlIfExtSetParentNode(self.element)
01257         return childElementWrapper
01258 
01259 
01260     def __updateAttrMaxLengthDict (self, attrMaxLengthDict):
01261         """Update dictionary which contains the maximum length of node attributes.
01262         
01263         Used for pretty print to align the attributes of child nodes.
01264         attrMaxLengthDict is in/out parameter.
01265         """
01266         for attrName, attrValue in self.getAttributeDict().items():
01267             attrLength = len(attrValue)
01268             if not attrMaxLengthDict.has_key(attrName):
01269                 attrMaxLengthDict[attrName] = attrLength
01270             else:
01271                 attrMaxLengthDict[attrName] = max(attrMaxLengthDict[attrName], attrLength)
01272 
01273 
01274     def __clearChildrenCache (self, childNsName=None):
01275         """Clear children cache.
01276         """
01277         if self.__useCaching():
01278             if childNsName != None:
01279                 if self.__childrenCache.has_key(childNsName):
01280                     del self.__childrenCache[childNsName]
01281                 if self.__firstChildCache.has_key(childNsName):
01282                     del self.__firstChildCache[childNsName]
01283             else:
01284                 self.__childrenCache.clear()
01285                 self.__firstChildCache.clear()
01286                 
01287 
01288     def __useCaching(self):
01289         return self.treeWrapper.useCaching()
01290     
01291 


mavlink
Author(s): Lorenz Meier
autogenerated on Sun May 22 2016 04:05:43