• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

contrib/opal/ZSI/build/lib/ZSI/wstools/Utility.py

00001 # Copyright (c) 2003, The Regents of the University of California,
00002 # through Lawrence Berkeley National Laboratory (subject to receipt of
00003 # any required approvals from the U.S. Dept. of Energy).  All rights
00004 # reserved. 
00005 #
00006 # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
00007 #
00008 # This software is subject to the provisions of the Zope Public License,
00009 # Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
00010 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
00011 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00012 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
00013 # FOR A PARTICULAR PURPOSE.
00014 
00015 ident = "$Id: Utility.py 1405 2007-07-10 20:25:44Z boverhof $"
00016 
00017 import sys, types, httplib, urllib, socket, weakref
00018 from os.path import isfile
00019 from string import join, strip, split
00020 from UserDict import UserDict
00021 from cStringIO import StringIO
00022 from TimeoutSocket import TimeoutSocket, TimeoutError
00023 from urlparse import urlparse
00024 from httplib import HTTPConnection, HTTPSConnection
00025 from exceptions import Exception
00026 try:
00027     from ZSI import _get_idstr
00028 except:
00029     def _get_idstr(pyobj):
00030         '''Python 2.3.x generates a FutureWarning for negative IDs, so
00031         we use a different prefix character to ensure uniqueness, and
00032         call abs() to avoid the warning.'''
00033         x = id(pyobj)
00034         if x < 0:
00035             return 'x%x' % abs(x)
00036         return 'o%x' % x
00037 
00038 import xml.dom.minidom
00039 from xml.dom import Node
00040 
00041 import logging
00042 from c14n import Canonicalize
00043 from Namespaces import SCHEMA, SOAP, XMLNS, ZSI_SCHEMA_URI
00044 
00045 
00046 try:
00047     from xml.dom.ext import SplitQName
00048 except:
00049     def SplitQName(qname):
00050         '''SplitQName(qname) -> (string, string)
00051         
00052            Split Qualified Name into a tuple of len 2, consisting 
00053            of the prefix and the local name.  
00054     
00055            (prefix, localName)
00056         
00057            Special Cases:
00058                xmlns -- (localName, 'xmlns')
00059                None -- (None, localName)
00060         '''
00061         
00062         l = qname.split(':')
00063         if len(l) == 1:
00064             l.insert(0, None)
00065         elif len(l) == 2:
00066             if l[0] == 'xmlns':
00067                 l.reverse()
00068         else:
00069             return
00070         return tuple(l)
00071 
00072 #
00073 # python2.3 urllib.basejoin does not remove current directory ./
00074 # from path and this causes problems on subsequent basejoins.
00075 #
00076 basejoin = urllib.basejoin
00077 if sys.version_info[0:2] < (2, 4, 0, 'final', 0)[0:2]:
00078     #basejoin = lambda base,url: urllib.basejoin(base,url.lstrip('./'))
00079     token = './'
00080     def basejoin(base, url): 
00081         if url.startswith(token) is True:
00082             return urllib.basejoin(base,url[2:])
00083         return urllib.basejoin(base,url)
00084 
00085 class NamespaceError(Exception):
00086     """Used to indicate a Namespace Error."""
00087 
00088 
00089 class RecursionError(Exception):
00090     """Used to indicate a HTTP redirect recursion."""
00091 
00092 
00093 class ParseError(Exception):
00094     """Used to indicate a XML parsing error."""
00095 
00096 
00097 class DOMException(Exception):
00098     """Used to indicate a problem processing DOM."""
00099 
00100 
00101 class Base:
00102     """Base class for instance level Logging"""
00103     def __init__(self, module=__name__):
00104         self.logger = logging.getLogger('%s-%s(%s)' %(module, self.__class__, _get_idstr(self)))
00105 
00106 
00107 class HTTPResponse:
00108     """Captures the information in an HTTP response message."""
00109 
00110     def __init__(self, response):
00111         self.status = response.status
00112         self.reason = response.reason
00113         self.headers = response.msg
00114         self.body = response.read() or None
00115         response.close()
00116 
00117 class TimeoutHTTP(HTTPConnection):
00118     """A custom http connection object that supports socket timeout."""
00119     def __init__(self, host, port=None, timeout=20):
00120         HTTPConnection.__init__(self, host, port)
00121         self.timeout = timeout
00122 
00123     def connect(self):
00124         self.sock = TimeoutSocket(self.timeout)
00125         self.sock.connect((self.host, self.port))
00126 
00127 
00128 class TimeoutHTTPS(HTTPSConnection):
00129     """A custom https object that supports socket timeout. Note that this
00130        is not really complete. The builtin SSL support in the Python socket
00131        module requires a real socket (type) to be passed in to be hooked to
00132        SSL. That means our fake socket won't work and our timeout hacks are
00133        bypassed for send and recv calls. Since our hack _is_ in place at
00134        connect() time, it should at least provide some timeout protection."""
00135     def __init__(self, host, port=None, timeout=20, **kwargs):
00136         HTTPSConnection.__init__(self, str(host), port, **kwargs)
00137         self.timeout = timeout
00138 
00139     def connect(self):
00140         sock = TimeoutSocket(self.timeout)
00141         sock.connect((self.host, self.port))
00142         realsock = getattr(sock.sock, '_sock', sock.sock)
00143         ssl = socket.ssl(realsock, self.key_file, self.cert_file)
00144         self.sock = httplib.FakeSocket(sock, ssl)
00145 
00146 
00147 def urlopen(url, timeout=20, redirects=None):
00148     """A minimal urlopen replacement hack that supports timeouts for http.
00149        Note that this supports GET only."""
00150     scheme, host, path, params, query, frag = urlparse(url)
00151 
00152     if not scheme in ('http', 'https'):
00153         return urllib.urlopen(url)
00154     if params: path = '%s;%s' % (path, params)
00155     if query:  path = '%s?%s' % (path, query)
00156     if frag:   path = '%s#%s' % (path, frag)
00157 
00158     if scheme == 'https':
00159         # If ssl is not compiled into Python, you will not get an exception
00160         # until a conn.endheaders() call.   We need to know sooner, so use
00161         # getattr.
00162         try:
00163             import M2Crypto
00164         except ImportError:
00165             if not hasattr(socket, 'ssl'):
00166                 raise RuntimeError, 'no built-in SSL Support'
00167 
00168             conn = TimeoutHTTPS(host, None, timeout)
00169         else:
00170             ctx = M2Crypto.SSL.Context()
00171             ctx.set_session_timeout(timeout)
00172             conn = M2Crypto.httpslib.HTTPSConnection(host, ssl_context=ctx)
00173             conn.set_debuglevel(1)
00174 
00175     else:
00176         conn = TimeoutHTTP(host, None, timeout)
00177 
00178     conn.putrequest('GET', path)
00179     conn.putheader('Connection', 'close')
00180     conn.endheaders()
00181     response = None
00182     while 1:
00183         response = conn.getresponse()
00184         if response.status != 100:
00185             break
00186         conn._HTTPConnection__state = httplib._CS_REQ_SENT
00187         conn._HTTPConnection__response = None
00188 
00189     status = response.status
00190 
00191     # If we get an HTTP redirect, we will follow it automatically.
00192     if status >= 300 and status < 400:
00193         location = response.msg.getheader('location')
00194         if location is not None:
00195             response.close()
00196             if redirects is not None and redirects.has_key(location):
00197                 raise RecursionError(
00198                     'Circular HTTP redirection detected.'
00199                     )
00200             if redirects is None:
00201                 redirects = {}
00202             redirects[location] = 1
00203             return urlopen(location, timeout, redirects)
00204         raise HTTPResponse(response)
00205 
00206     if not (status >= 200 and status < 300):
00207         raise HTTPResponse(response)
00208 
00209     body = StringIO(response.read())
00210     response.close()
00211     return body
00212 
00213 class DOM:
00214     """The DOM singleton defines a number of XML related constants and
00215        provides a number of utility methods for DOM related tasks. It
00216        also provides some basic abstractions so that the rest of the
00217        package need not care about actual DOM implementation in use."""
00218 
00219     # Namespace stuff related to the SOAP specification.
00220 
00221     NS_SOAP_ENV_1_1 = 'http://schemas.xmlsoap.org/soap/envelope/'
00222     NS_SOAP_ENC_1_1 = 'http://schemas.xmlsoap.org/soap/encoding/'
00223 
00224     NS_SOAP_ENV_1_2 = 'http://www.w3.org/2001/06/soap-envelope'
00225     NS_SOAP_ENC_1_2 = 'http://www.w3.org/2001/06/soap-encoding'
00226 
00227     NS_SOAP_ENV_ALL = (NS_SOAP_ENV_1_1, NS_SOAP_ENV_1_2)
00228     NS_SOAP_ENC_ALL = (NS_SOAP_ENC_1_1, NS_SOAP_ENC_1_2)
00229 
00230     NS_SOAP_ENV = NS_SOAP_ENV_1_1
00231     NS_SOAP_ENC = NS_SOAP_ENC_1_1
00232 
00233     _soap_uri_mapping = {
00234         NS_SOAP_ENV_1_1 : '1.1',
00235         NS_SOAP_ENV_1_2 : '1.2',
00236     }
00237 
00238     SOAP_ACTOR_NEXT_1_1 = 'http://schemas.xmlsoap.org/soap/actor/next'
00239     SOAP_ACTOR_NEXT_1_2 = 'http://www.w3.org/2001/06/soap-envelope/actor/next'
00240     SOAP_ACTOR_NEXT_ALL = (SOAP_ACTOR_NEXT_1_1, SOAP_ACTOR_NEXT_1_2)
00241     
00242     def SOAPUriToVersion(self, uri):
00243         """Return the SOAP version related to an envelope uri."""
00244         value = self._soap_uri_mapping.get(uri)
00245         if value is not None:
00246             return value
00247         raise ValueError(
00248             'Unsupported SOAP envelope uri: %s' % uri
00249             )
00250 
00251     def GetSOAPEnvUri(self, version):
00252         """Return the appropriate SOAP envelope uri for a given
00253            human-friendly SOAP version string (e.g. '1.1')."""
00254         attrname = 'NS_SOAP_ENV_%s' % join(split(version, '.'), '_')
00255         value = getattr(self, attrname, None)
00256         if value is not None:
00257             return value
00258         raise ValueError(
00259             'Unsupported SOAP version: %s' % version
00260             )
00261 
00262     def GetSOAPEncUri(self, version):
00263         """Return the appropriate SOAP encoding uri for a given
00264            human-friendly SOAP version string (e.g. '1.1')."""
00265         attrname = 'NS_SOAP_ENC_%s' % join(split(version, '.'), '_')
00266         value = getattr(self, attrname, None)
00267         if value is not None:
00268             return value
00269         raise ValueError(
00270             'Unsupported SOAP version: %s' % version
00271             )
00272 
00273     def GetSOAPActorNextUri(self, version):
00274         """Return the right special next-actor uri for a given
00275            human-friendly SOAP version string (e.g. '1.1')."""
00276         attrname = 'SOAP_ACTOR_NEXT_%s' % join(split(version, '.'), '_')
00277         value = getattr(self, attrname, None)
00278         if value is not None:
00279             return value
00280         raise ValueError(
00281             'Unsupported SOAP version: %s' % version
00282             )
00283 
00284 
00285     # Namespace stuff related to XML Schema.
00286 
00287     NS_XSD_99 = 'http://www.w3.org/1999/XMLSchema'
00288     NS_XSI_99 = 'http://www.w3.org/1999/XMLSchema-instance'    
00289 
00290     NS_XSD_00 = 'http://www.w3.org/2000/10/XMLSchema'
00291     NS_XSI_00 = 'http://www.w3.org/2000/10/XMLSchema-instance'    
00292 
00293     NS_XSD_01 = 'http://www.w3.org/2001/XMLSchema'
00294     NS_XSI_01 = 'http://www.w3.org/2001/XMLSchema-instance'
00295 
00296     NS_XSD_ALL = (NS_XSD_99, NS_XSD_00, NS_XSD_01)
00297     NS_XSI_ALL = (NS_XSI_99, NS_XSI_00, NS_XSI_01)
00298 
00299     NS_XSD = NS_XSD_01
00300     NS_XSI = NS_XSI_01
00301 
00302     _xsd_uri_mapping = {
00303         NS_XSD_99 : NS_XSI_99,
00304         NS_XSD_00 : NS_XSI_00,
00305         NS_XSD_01 : NS_XSI_01,
00306     }
00307 
00308     for key, value in _xsd_uri_mapping.items():
00309         _xsd_uri_mapping[value] = key
00310 
00311 
00312     def InstanceUriForSchemaUri(self, uri):
00313         """Return the appropriate matching XML Schema instance uri for
00314            the given XML Schema namespace uri."""
00315         return self._xsd_uri_mapping.get(uri)
00316 
00317     def SchemaUriForInstanceUri(self, uri):
00318         """Return the appropriate matching XML Schema namespace uri for
00319            the given XML Schema instance namespace uri."""
00320         return self._xsd_uri_mapping.get(uri)
00321 
00322 
00323     # Namespace stuff related to WSDL.
00324 
00325     NS_WSDL_1_1 = 'http://schemas.xmlsoap.org/wsdl/'
00326     NS_WSDL_ALL = (NS_WSDL_1_1,)
00327     NS_WSDL = NS_WSDL_1_1
00328 
00329     NS_SOAP_BINDING_1_1 = 'http://schemas.xmlsoap.org/wsdl/soap/'
00330     NS_HTTP_BINDING_1_1 = 'http://schemas.xmlsoap.org/wsdl/http/'
00331     NS_MIME_BINDING_1_1 = 'http://schemas.xmlsoap.org/wsdl/mime/'
00332 
00333     NS_SOAP_BINDING_ALL = (NS_SOAP_BINDING_1_1,)
00334     NS_HTTP_BINDING_ALL = (NS_HTTP_BINDING_1_1,)
00335     NS_MIME_BINDING_ALL = (NS_MIME_BINDING_1_1,)
00336 
00337     NS_SOAP_BINDING = NS_SOAP_BINDING_1_1
00338     NS_HTTP_BINDING = NS_HTTP_BINDING_1_1
00339     NS_MIME_BINDING = NS_MIME_BINDING_1_1
00340 
00341     NS_SOAP_HTTP_1_1 = 'http://schemas.xmlsoap.org/soap/http'
00342     NS_SOAP_HTTP_ALL = (NS_SOAP_HTTP_1_1,)
00343     NS_SOAP_HTTP = NS_SOAP_HTTP_1_1
00344     
00345 
00346     _wsdl_uri_mapping = {
00347         NS_WSDL_1_1 : '1.1',
00348     }
00349     
00350     def WSDLUriToVersion(self, uri):
00351         """Return the WSDL version related to a WSDL namespace uri."""
00352         value = self._wsdl_uri_mapping.get(uri)
00353         if value is not None:
00354             return value
00355         raise ValueError(
00356             'Unsupported SOAP envelope uri: %s' % uri
00357             )
00358 
00359     def GetWSDLUri(self, version):
00360         attr = 'NS_WSDL_%s' % join(split(version, '.'), '_')
00361         value = getattr(self, attr, None)
00362         if value is not None:
00363             return value
00364         raise ValueError(
00365             'Unsupported WSDL version: %s' % version
00366             )
00367 
00368     def GetWSDLSoapBindingUri(self, version):
00369         attr = 'NS_SOAP_BINDING_%s' % join(split(version, '.'), '_')
00370         value = getattr(self, attr, None)
00371         if value is not None:
00372             return value
00373         raise ValueError(
00374             'Unsupported WSDL version: %s' % version
00375             )
00376 
00377     def GetWSDLHttpBindingUri(self, version):
00378         attr = 'NS_HTTP_BINDING_%s' % join(split(version, '.'), '_')
00379         value = getattr(self, attr, None)
00380         if value is not None:
00381             return value
00382         raise ValueError(
00383             'Unsupported WSDL version: %s' % version
00384             )
00385 
00386     def GetWSDLMimeBindingUri(self, version):
00387         attr = 'NS_MIME_BINDING_%s' % join(split(version, '.'), '_')
00388         value = getattr(self, attr, None)
00389         if value is not None:
00390             return value
00391         raise ValueError(
00392             'Unsupported WSDL version: %s' % version
00393             )
00394 
00395     def GetWSDLHttpTransportUri(self, version):
00396         attr = 'NS_SOAP_HTTP_%s' % join(split(version, '.'), '_')
00397         value = getattr(self, attr, None)
00398         if value is not None:
00399             return value
00400         raise ValueError(
00401             'Unsupported WSDL version: %s' % version
00402             )
00403 
00404 
00405     # Other xml namespace constants.
00406     NS_XMLNS     = 'http://www.w3.org/2000/xmlns/'
00407 
00408 
00409 
00410     def isElement(self, node, name, nsuri=None):
00411         """Return true if the given node is an element with the given
00412            name and optional namespace uri."""
00413         if node.nodeType != node.ELEMENT_NODE:
00414             return 0
00415         return node.localName == name and \
00416                (nsuri is None or self.nsUriMatch(node.namespaceURI, nsuri))
00417 
00418     def getElement(self, node, name, nsuri=None, default=join):
00419         """Return the first child of node with a matching name and
00420            namespace uri, or the default if one is provided."""
00421         nsmatch = self.nsUriMatch
00422         ELEMENT_NODE = node.ELEMENT_NODE
00423         for child in node.childNodes:
00424             if child.nodeType == ELEMENT_NODE:
00425                 if ((child.localName == name or name is None) and
00426                     (nsuri is None or nsmatch(child.namespaceURI, nsuri))
00427                     ):
00428                     return child
00429         if default is not join:
00430             return default
00431         raise KeyError, name
00432 
00433     def getElementById(self, node, id, default=join):
00434         """Return the first child of node matching an id reference."""
00435         attrget = self.getAttr
00436         ELEMENT_NODE = node.ELEMENT_NODE
00437         for child in node.childNodes:
00438             if child.nodeType == ELEMENT_NODE:
00439                 if attrget(child, 'id') == id:
00440                     return child
00441         if default is not join:
00442             return default
00443         raise KeyError, name
00444 
00445     def getMappingById(self, document, depth=None, element=None,
00446                        mapping=None, level=1):
00447         """Create an id -> element mapping of those elements within a
00448            document that define an id attribute. The depth of the search
00449            may be controlled by using the (1-based) depth argument."""
00450         if document is not None:
00451             element = document.documentElement
00452             mapping = {}
00453         attr = element._attrs.get('id', None)
00454         if attr is not None:
00455             mapping[attr.value] = element
00456         if depth is None or depth > level:
00457             level = level + 1
00458             ELEMENT_NODE = element.ELEMENT_NODE
00459             for child in element.childNodes:
00460                 if child.nodeType == ELEMENT_NODE:
00461                     self.getMappingById(None, depth, child, mapping, level)
00462         return mapping        
00463 
00464     def getElements(self, node, name, nsuri=None):
00465         """Return a sequence of the child elements of the given node that
00466            match the given name and optional namespace uri."""
00467         nsmatch = self.nsUriMatch
00468         result = []
00469         ELEMENT_NODE = node.ELEMENT_NODE
00470         for child in node.childNodes:
00471             if child.nodeType == ELEMENT_NODE:
00472                 if ((child.localName == name or name is None) and (
00473                     (nsuri is None) or nsmatch(child.namespaceURI, nsuri))):
00474                     result.append(child)
00475         return result
00476 
00477     def hasAttr(self, node, name, nsuri=None):
00478         """Return true if element has attribute with the given name and
00479            optional nsuri. If nsuri is not specified, returns true if an
00480            attribute exists with the given name with any namespace."""
00481         if nsuri is None:
00482             if node.hasAttribute(name):
00483                 return True
00484             return False
00485         return node.hasAttributeNS(nsuri, name)
00486 
00487     def getAttr(self, node, name, nsuri=None, default=join):
00488         """Return the value of the attribute named 'name' with the
00489            optional nsuri, or the default if one is specified. If
00490            nsuri is not specified, an attribute that matches the
00491            given name will be returned regardless of namespace."""
00492         if nsuri is None:
00493             result = node._attrs.get(name, None)
00494             if result is None:
00495                 for item in node._attrsNS.keys():
00496                     if item[1] == name:
00497                         result = node._attrsNS[item]
00498                         break
00499         else:
00500             result = node._attrsNS.get((nsuri, name), None)
00501         if result is not None:
00502             return result.value
00503         if default is not join:
00504             return default
00505         return ''
00506 
00507     def getAttrs(self, node):
00508         """Return a Collection of all attributes 
00509         """
00510         attrs = {}
00511         for k,v in node._attrs.items():
00512             attrs[k] = v.value
00513         return attrs
00514 
00515     def getElementText(self, node, preserve_ws=None):
00516         """Return the text value of an xml element node. Leading and trailing
00517            whitespace is stripped from the value unless the preserve_ws flag
00518            is passed with a true value."""
00519         result = []
00520         for child in node.childNodes:
00521             nodetype = child.nodeType
00522             if nodetype == child.TEXT_NODE or \
00523                nodetype == child.CDATA_SECTION_NODE:
00524                 result.append(child.nodeValue)
00525         value = join(result, '')
00526         if preserve_ws is None:
00527             value = strip(value)
00528         return value
00529 
00530     def findNamespaceURI(self, prefix, node):
00531         """Find a namespace uri given a prefix and a context node."""
00532         attrkey = (self.NS_XMLNS, prefix)
00533         DOCUMENT_NODE = node.DOCUMENT_NODE
00534         ELEMENT_NODE = node.ELEMENT_NODE
00535         while 1:
00536             if node is None:
00537                 raise DOMException('Value for prefix %s not found.' % prefix)
00538             if node.nodeType != ELEMENT_NODE:
00539                 node = node.parentNode
00540                 continue
00541             result = node._attrsNS.get(attrkey, None)
00542             if result is not None:
00543                 return result.value
00544             if hasattr(node, '__imported__'):
00545                 raise DOMException('Value for prefix %s not found.' % prefix)
00546             node = node.parentNode
00547             if node.nodeType == DOCUMENT_NODE:
00548                 raise DOMException('Value for prefix %s not found.' % prefix)
00549 
00550     def findDefaultNS(self, node):
00551         """Return the current default namespace uri for the given node."""
00552         attrkey = (self.NS_XMLNS, 'xmlns')
00553         DOCUMENT_NODE = node.DOCUMENT_NODE
00554         ELEMENT_NODE = node.ELEMENT_NODE
00555         while 1:
00556             if node.nodeType != ELEMENT_NODE:
00557                 node = node.parentNode
00558                 continue
00559             result = node._attrsNS.get(attrkey, None)
00560             if result is not None:
00561                 return result.value
00562             if hasattr(node, '__imported__'):
00563                 raise DOMException('Cannot determine default namespace.')
00564             node = node.parentNode
00565             if node.nodeType == DOCUMENT_NODE:
00566                 raise DOMException('Cannot determine default namespace.')
00567 
00568     def findTargetNS(self, node):
00569         """Return the defined target namespace uri for the given node."""
00570         attrget = self.getAttr
00571         attrkey = (self.NS_XMLNS, 'xmlns')
00572         DOCUMENT_NODE = node.DOCUMENT_NODE
00573         ELEMENT_NODE = node.ELEMENT_NODE
00574         while 1:
00575             if node.nodeType != ELEMENT_NODE:
00576                 node = node.parentNode
00577                 continue
00578             result = attrget(node, 'targetNamespace', default=None)
00579             if result is not None:
00580                 return result
00581             node = node.parentNode
00582             if node.nodeType == DOCUMENT_NODE:
00583                 raise DOMException('Cannot determine target namespace.')
00584 
00585     def getTypeRef(self, element):
00586         """Return (namespaceURI, name) for a type attribue of the given
00587            element, or None if the element does not have a type attribute."""
00588         typeattr = self.getAttr(element, 'type', default=None)
00589         if typeattr is None:
00590             return None
00591         parts = typeattr.split(':', 1)
00592         if len(parts) == 2:
00593             nsuri = self.findNamespaceURI(parts[0], element)
00594         else:
00595             nsuri = self.findDefaultNS(element)
00596         return (nsuri, parts[1])
00597 
00598     def importNode(self, document, node, deep=0):
00599         """Implements (well enough for our purposes) DOM node import."""
00600         nodetype = node.nodeType
00601         if nodetype in (node.DOCUMENT_NODE, node.DOCUMENT_TYPE_NODE):
00602             raise DOMException('Illegal node type for importNode')
00603         if nodetype == node.ENTITY_REFERENCE_NODE:
00604             deep = 0
00605         clone = node.cloneNode(deep)
00606         self._setOwnerDoc(document, clone)
00607         clone.__imported__ = 1
00608         return clone
00609 
00610     def _setOwnerDoc(self, document, node):
00611         node.ownerDocument = document
00612         for child in node.childNodes:
00613             self._setOwnerDoc(document, child)
00614 
00615     def nsUriMatch(self, value, wanted, strict=0, tt=type(())):
00616         """Return a true value if two namespace uri values match."""
00617         if value == wanted or (type(wanted) is tt) and value in wanted:
00618             return 1
00619         if not strict and value is not None:
00620             wanted = type(wanted) is tt and wanted or (wanted,)
00621             value = value[-1:] != '/' and value or value[:-1]
00622             for item in wanted:
00623                 if item == value or item[:-1] == value:
00624                     return 1
00625         return 0
00626 
00627     def createDocument(self, nsuri, qname, doctype=None):
00628         """Create a new writable DOM document object."""
00629         impl = xml.dom.minidom.getDOMImplementation()
00630         return impl.createDocument(nsuri, qname, doctype)
00631 
00632     def loadDocument(self, data):
00633         """Load an xml file from a file-like object and return a DOM
00634            document instance."""
00635         return xml.dom.minidom.parse(data)
00636 
00637     def loadFromURL(self, url):
00638         """Load an xml file from a URL and return a DOM document."""
00639         if isfile(url) is True:
00640             file = open(url, 'r')
00641         else:
00642             file = urlopen(url)
00643 
00644         try:     
00645             result = self.loadDocument(file)
00646         except Exception, ex:
00647             file.close()
00648             raise ParseError(('Failed to load document %s' %url,) + ex.args)
00649         else:
00650             file.close()
00651         return result
00652 
00653 DOM = DOM()
00654 
00655 
00656 class MessageInterface:
00657     '''Higher Level Interface, delegates to DOM singleton, must 
00658     be subclassed and implement all methods that throw NotImplementedError.
00659     '''
00660     def __init__(self, sw):
00661         '''Constructor, May be extended, do not override.
00662             sw -- soapWriter instance
00663         '''
00664         self.sw = None
00665         if type(sw) != weakref.ReferenceType and sw is not None:
00666             self.sw = weakref.ref(sw)
00667         else:
00668             self.sw = sw
00669 
00670     def AddCallback(self, func, *arglist):
00671         self.sw().AddCallback(func, *arglist)
00672 
00673     def Known(self, obj):
00674         return self.sw().Known(obj)
00675 
00676     def Forget(self, obj):
00677         return self.sw().Forget(obj)
00678 
00679     def canonicalize(self):
00680         '''canonicalize the underlying DOM, and return as string.
00681         '''
00682         raise NotImplementedError, ''
00683 
00684     def createDocument(self, namespaceURI=SOAP.ENV, localName='Envelope'):
00685         '''create Document
00686         '''
00687         raise NotImplementedError, ''
00688 
00689     def createAppendElement(self, namespaceURI, localName):
00690         '''create and append element(namespaceURI,localName), and return
00691         the node.
00692         '''
00693         raise NotImplementedError, ''
00694 
00695     def findNamespaceURI(self, qualifiedName):
00696         raise NotImplementedError, ''
00697 
00698     def resolvePrefix(self, prefix):
00699         raise NotImplementedError, ''
00700 
00701     def setAttributeNS(self, namespaceURI, localName, value):
00702         '''set attribute (namespaceURI, localName)=value
00703         '''
00704         raise NotImplementedError, ''
00705 
00706     def setAttributeType(self, namespaceURI, localName):
00707         '''set attribute xsi:type=(namespaceURI, localName)
00708         '''
00709         raise NotImplementedError, ''
00710 
00711     def setNamespaceAttribute(self, namespaceURI, prefix):
00712         '''set namespace attribute xmlns:prefix=namespaceURI 
00713         '''
00714         raise NotImplementedError, ''
00715 
00716 
00717 class ElementProxy(Base, MessageInterface):
00718     '''
00719     '''
00720     _soap_env_prefix = 'SOAP-ENV'
00721     _soap_enc_prefix = 'SOAP-ENC'
00722     _zsi_prefix = 'ZSI'
00723     _xsd_prefix = 'xsd'
00724     _xsi_prefix = 'xsi'
00725     _xml_prefix = 'xml'
00726     _xmlns_prefix = 'xmlns'
00727 
00728     _soap_env_nsuri = SOAP.ENV
00729     _soap_enc_nsuri = SOAP.ENC
00730     _zsi_nsuri = ZSI_SCHEMA_URI
00731     _xsd_nsuri =  SCHEMA.XSD3
00732     _xsi_nsuri = SCHEMA.XSI3
00733     _xml_nsuri = XMLNS.XML
00734     _xmlns_nsuri = XMLNS.BASE
00735 
00736     standard_ns = {\
00737         _xml_prefix:_xml_nsuri,
00738         _xmlns_prefix:_xmlns_nsuri
00739     }
00740     reserved_ns = {\
00741         _soap_env_prefix:_soap_env_nsuri,
00742         _soap_enc_prefix:_soap_enc_nsuri,
00743         _zsi_prefix:_zsi_nsuri,
00744         _xsd_prefix:_xsd_nsuri,
00745         _xsi_prefix:_xsi_nsuri,
00746     }
00747     name = None
00748     namespaceURI = None
00749 
00750     def __init__(self, sw, message=None):
00751         '''Initialize. 
00752            sw -- SoapWriter
00753         '''
00754         self._indx = 0
00755         MessageInterface.__init__(self, sw)
00756         Base.__init__(self)
00757         self._dom = DOM
00758         self.node = None
00759         if type(message) in (types.StringType,types.UnicodeType):
00760             self.loadFromString(message)
00761         elif isinstance(message, ElementProxy):
00762             self.node = message._getNode()
00763         else:
00764             self.node = message
00765         self.processorNss = self.standard_ns.copy()
00766         self.processorNss.update(self.reserved_ns)
00767 
00768     def __str__(self):
00769         return self.toString()
00770 
00771     def evaluate(self, expression, processorNss=None):
00772         '''expression -- XPath compiled expression
00773         '''
00774         from Ft.Xml import XPath
00775         if not processorNss:
00776             context = XPath.Context.Context(self.node, processorNss=self.processorNss)
00777         else:
00778             context = XPath.Context.Context(self.node, processorNss=processorNss)
00779         nodes = expression.evaluate(context)
00780         return map(lambda node: ElementProxy(self.sw,node), nodes)
00781 
00782     #############################################
00783     # Methods for checking/setting the
00784     # classes (namespaceURI,name) node. 
00785     #############################################
00786     def checkNode(self, namespaceURI=None, localName=None):
00787         '''
00788             namespaceURI -- namespace of element
00789             localName -- local name of element
00790         '''
00791         namespaceURI = namespaceURI or self.namespaceURI
00792         localName = localName or self.name
00793         check = False
00794         if localName and self.node:
00795             check = self._dom.isElement(self.node, localName, namespaceURI)
00796         if not check:
00797             raise NamespaceError, 'unexpected node type %s, expecting %s' %(self.node, localName)
00798 
00799     def setNode(self, node=None):
00800         if node:
00801             if isinstance(node, ElementProxy):
00802                 self.node = node._getNode()
00803             else:
00804                 self.node = node
00805         elif self.node:
00806             node = self._dom.getElement(self.node, self.name, self.namespaceURI, default=None)
00807             if not node:
00808                 raise NamespaceError, 'cant find element (%s,%s)' %(self.namespaceURI,self.name)
00809             self.node = node
00810         else:
00811             #self.node = self._dom.create(self.node, self.name, self.namespaceURI, default=None)
00812             self.createDocument(self.namespaceURI, localName=self.name, doctype=None)
00813         
00814         self.checkNode()
00815 
00816     #############################################
00817     # Wrapper Methods for direct DOM Element Node access
00818     #############################################
00819     def _getNode(self):
00820         return self.node
00821 
00822     def _getElements(self):
00823         return self._dom.getElements(self.node, name=None)
00824 
00825     def _getOwnerDocument(self):
00826         return self.node.ownerDocument or self.node
00827 
00828     def _getUniquePrefix(self):
00829         '''I guess we need to resolve all potential prefixes
00830         because when the current node is attached it copies the 
00831         namespaces into the parent node.
00832         '''
00833         while 1:
00834             self._indx += 1
00835             prefix = 'ns%d' %self._indx
00836             try:
00837                 self._dom.findNamespaceURI(prefix, self._getNode())
00838             except DOMException, ex:
00839                 break
00840         return prefix
00841 
00842     def _getPrefix(self, node, nsuri):
00843         '''
00844         Keyword arguments:
00845             node -- DOM Element Node
00846             nsuri -- namespace of attribute value
00847         '''
00848         try:
00849             if node and (node.nodeType == node.ELEMENT_NODE) and \
00850                 (nsuri == self._dom.findDefaultNS(node)):
00851                 return None
00852         except DOMException, ex:
00853             pass
00854         if nsuri == XMLNS.XML:
00855             return self._xml_prefix
00856         if node.nodeType == Node.ELEMENT_NODE:
00857             for attr in node.attributes.values():
00858                 if attr.namespaceURI == XMLNS.BASE \
00859                    and nsuri == attr.value:
00860                         return attr.localName
00861             else:
00862                 if node.parentNode:
00863                     return self._getPrefix(node.parentNode, nsuri)
00864         raise NamespaceError, 'namespaceURI "%s" is not defined' %nsuri
00865 
00866     def _appendChild(self, node):
00867         '''
00868         Keyword arguments:
00869             node -- DOM Element Node
00870         '''
00871         if node is None:
00872             raise TypeError, 'node is None'
00873         self.node.appendChild(node)
00874 
00875     def _insertBefore(self, newChild, refChild):
00876         '''
00877         Keyword arguments:
00878             child -- DOM Element Node to insert
00879             refChild -- DOM Element Node 
00880         '''
00881         self.node.insertBefore(newChild, refChild)
00882 
00883     def _setAttributeNS(self, namespaceURI, qualifiedName, value):
00884         '''
00885         Keyword arguments:
00886             namespaceURI -- namespace of attribute
00887             qualifiedName -- qualified name of new attribute value
00888             value -- value of attribute
00889         '''
00890         self.node.setAttributeNS(namespaceURI, qualifiedName, value)
00891 
00892     #############################################
00893     #General Methods
00894     #############################################
00895     def isFault(self):
00896         '''check to see if this is a soap:fault message.
00897         '''
00898         return False
00899 
00900     def getPrefix(self, namespaceURI):
00901         try:
00902             prefix = self._getPrefix(node=self.node, nsuri=namespaceURI)
00903         except NamespaceError, ex:
00904             prefix = self._getUniquePrefix() 
00905             self.setNamespaceAttribute(prefix, namespaceURI)
00906         return prefix
00907 
00908     def getDocument(self):
00909         return self._getOwnerDocument()
00910 
00911     def setDocument(self, document):
00912         self.node = document
00913 
00914     def importFromString(self, xmlString):
00915         doc = self._dom.loadDocument(StringIO(xmlString))
00916         node = self._dom.getElement(doc, name=None)
00917         clone = self.importNode(node)
00918         self._appendChild(clone)
00919 
00920     def importNode(self, node):
00921         if isinstance(node, ElementProxy):
00922             node = node._getNode()
00923         return self._dom.importNode(self._getOwnerDocument(), node, deep=1)
00924 
00925     def loadFromString(self, data):
00926         self.node = self._dom.loadDocument(StringIO(data))
00927 
00928     def canonicalize(self):
00929         return Canonicalize(self.node)
00930 
00931     def toString(self):
00932         return self.canonicalize()
00933 
00934     def createDocument(self, namespaceURI, localName, doctype=None):
00935         '''If specified must be a SOAP envelope, else may contruct an empty document.
00936         '''
00937         prefix = self._soap_env_prefix
00938 
00939         if namespaceURI == self.reserved_ns[prefix]:
00940             qualifiedName = '%s:%s' %(prefix,localName)
00941         elif namespaceURI is localName is None:
00942             self.node = self._dom.createDocument(None,None,None)
00943             return
00944         else:
00945             raise KeyError, 'only support creation of document in %s' %self.reserved_ns[prefix]
00946 
00947         document = self._dom.createDocument(nsuri=namespaceURI, qname=qualifiedName, doctype=doctype)
00948         self.node = document.childNodes[0]
00949 
00950         #set up reserved namespace attributes
00951         for prefix,nsuri in self.reserved_ns.items():
00952             self._setAttributeNS(namespaceURI=self._xmlns_nsuri, 
00953                 qualifiedName='%s:%s' %(self._xmlns_prefix,prefix), 
00954                 value=nsuri)
00955 
00956     #############################################
00957     #Methods for attributes
00958     #############################################
00959     def hasAttribute(self, namespaceURI, localName):
00960         return self._dom.hasAttr(self._getNode(), name=localName, nsuri=namespaceURI)
00961 
00962     def setAttributeType(self, namespaceURI, localName):
00963         '''set xsi:type
00964         Keyword arguments:
00965             namespaceURI -- namespace of attribute value
00966             localName -- name of new attribute value
00967 
00968         '''
00969         self.logger.debug('setAttributeType: (%s,%s)', namespaceURI, localName)
00970         value = localName
00971         if namespaceURI:
00972             value = '%s:%s' %(self.getPrefix(namespaceURI),localName)
00973 
00974         xsi_prefix = self.getPrefix(self._xsi_nsuri)
00975         self._setAttributeNS(self._xsi_nsuri, '%s:type' %xsi_prefix, value)
00976 
00977     def createAttributeNS(self, namespace, name, value):
00978         document = self._getOwnerDocument()
00979         attrNode = document.createAttributeNS(namespace, name, value)
00980 
00981     def setAttributeNS(self, namespaceURI, localName, value):
00982         '''
00983         Keyword arguments:
00984             namespaceURI -- namespace of attribute to create, None is for
00985                 attributes in no namespace.
00986             localName -- local name of new attribute
00987             value -- value of new attribute
00988         ''' 
00989         prefix = None
00990         if namespaceURI:
00991             try:
00992                 prefix = self.getPrefix(namespaceURI)
00993             except KeyError, ex:
00994                 prefix = 'ns2'
00995                 self.setNamespaceAttribute(prefix, namespaceURI)
00996         qualifiedName = localName
00997         if prefix:
00998             qualifiedName = '%s:%s' %(prefix, localName)
00999         self._setAttributeNS(namespaceURI, qualifiedName, value)
01000 
01001     def setNamespaceAttribute(self, prefix, namespaceURI):
01002         '''
01003         Keyword arguments:
01004             prefix -- xmlns prefix
01005             namespaceURI -- value of prefix
01006         '''
01007         self._setAttributeNS(XMLNS.BASE, 'xmlns:%s' %prefix, namespaceURI)
01008 
01009     #############################################
01010     #Methods for elements
01011     #############################################
01012     def createElementNS(self, namespace, qname):
01013         '''
01014         Keyword arguments:
01015             namespace -- namespace of element to create
01016             qname -- qualified name of new element
01017         '''
01018         document = self._getOwnerDocument()
01019         node = document.createElementNS(namespace, qname)
01020         return ElementProxy(self.sw, node)
01021 
01022     def createAppendSetElement(self, namespaceURI, localName, prefix=None):
01023         '''Create a new element (namespaceURI,name), append it
01024            to current node, then set it to be the current node.
01025         Keyword arguments:
01026             namespaceURI -- namespace of element to create
01027             localName -- local name of new element
01028             prefix -- if namespaceURI is not defined, declare prefix.  defaults
01029                 to 'ns1' if left unspecified.
01030         '''
01031         node = self.createAppendElement(namespaceURI, localName, prefix=None)
01032         node=node._getNode()
01033         self._setNode(node._getNode())
01034 
01035     def createAppendElement(self, namespaceURI, localName, prefix=None):
01036         '''Create a new element (namespaceURI,name), append it
01037            to current node, and return the newly created node.
01038         Keyword arguments:
01039             namespaceURI -- namespace of element to create
01040             localName -- local name of new element
01041             prefix -- if namespaceURI is not defined, declare prefix.  defaults
01042                 to 'ns1' if left unspecified.
01043         '''
01044         declare = False
01045         qualifiedName = localName
01046         if namespaceURI:
01047             try:
01048                 prefix = self.getPrefix(namespaceURI)
01049             except:
01050                 declare = True
01051                 prefix = prefix or self._getUniquePrefix()
01052             if prefix: 
01053                 qualifiedName = '%s:%s' %(prefix, localName)
01054         node = self.createElementNS(namespaceURI, qualifiedName)
01055         if declare:
01056             node._setAttributeNS(XMLNS.BASE, 'xmlns:%s' %prefix, namespaceURI)
01057         self._appendChild(node=node._getNode())
01058         return node
01059 
01060     def createInsertBefore(self, namespaceURI, localName, refChild):
01061         qualifiedName = localName
01062         prefix = self.getPrefix(namespaceURI)
01063         if prefix: 
01064             qualifiedName = '%s:%s' %(prefix, localName)
01065         node = self.createElementNS(namespaceURI, qualifiedName)
01066         self._insertBefore(newChild=node._getNode(), refChild=refChild._getNode())
01067         return node
01068 
01069     def getElement(self, namespaceURI, localName):
01070         '''
01071         Keyword arguments:
01072             namespaceURI -- namespace of element
01073             localName -- local name of element
01074         '''
01075         node = self._dom.getElement(self.node, localName, namespaceURI, default=None)
01076         if node:
01077             return ElementProxy(self.sw, node)
01078         return None
01079 
01080     def getAttributeValue(self, namespaceURI, localName):
01081         '''
01082         Keyword arguments:
01083             namespaceURI -- namespace of attribute
01084             localName -- local name of attribute
01085         '''
01086         if self.hasAttribute(namespaceURI, localName):
01087             attr = self.node.getAttributeNodeNS(namespaceURI,localName)
01088             return attr.value
01089         return None
01090 
01091     def getValue(self):
01092         return self._dom.getElementText(self.node, preserve_ws=True)    
01093 
01094     #############################################
01095     #Methods for text nodes
01096     #############################################
01097     def createAppendTextNode(self, pyobj):
01098         node = self.createTextNode(pyobj)
01099         self._appendChild(node=node._getNode())
01100         return node
01101 
01102     def createTextNode(self, pyobj):
01103         document = self._getOwnerDocument()
01104         node = document.createTextNode(pyobj)
01105         return ElementProxy(self.sw, node)
01106 
01107     #############################################
01108     #Methods for retrieving namespaceURI's
01109     #############################################
01110     def findNamespaceURI(self, qualifiedName):
01111         parts = SplitQName(qualifiedName)
01112         element = self._getNode()
01113         if len(parts) == 1:
01114             return (self._dom.findTargetNS(element), value)
01115         return self._dom.findNamespaceURI(parts[0], element)
01116 
01117     def resolvePrefix(self, prefix):
01118         element = self._getNode()
01119         return self._dom.findNamespaceURI(prefix, element)
01120 
01121     def getSOAPEnvURI(self):
01122         return self._soap_env_nsuri
01123 
01124     def isEmpty(self):
01125         return not self.node
01126 
01127 
01128 
01129 class Collection(UserDict):
01130     """Helper class for maintaining ordered named collections."""
01131     default = lambda self,k: k.name
01132     def __init__(self, parent, key=None):
01133         UserDict.__init__(self)
01134         self.parent = weakref.ref(parent)
01135         self.list = []
01136         self._func = key or self.default
01137 
01138     def __getitem__(self, key):
01139         if type(key) is type(1):
01140             return self.list[key]
01141         return self.data[key]
01142 
01143     def __setitem__(self, key, item):
01144         item.parent = weakref.ref(self)
01145         self.list.append(item)
01146         self.data[key] = item
01147 
01148     def keys(self):
01149         return map(lambda i: self._func(i), self.list)
01150 
01151     def items(self):
01152         return map(lambda i: (self._func(i), i), self.list)
01153 
01154     def values(self):
01155         return self.list
01156 
01157 
01158 class CollectionNS(UserDict):
01159     """Helper class for maintaining ordered named collections."""
01160     default = lambda self,k: k.name
01161     def __init__(self, parent, key=None):
01162         UserDict.__init__(self)
01163         self.parent = weakref.ref(parent)
01164         self.targetNamespace = None
01165         self.list = []
01166         self._func = key or self.default
01167 
01168     def __getitem__(self, key):
01169         self.targetNamespace = self.parent().targetNamespace
01170         if type(key) is types.IntType:
01171             return self.list[key]
01172         elif self.__isSequence(key):
01173             nsuri,name = key
01174             return self.data[nsuri][name]
01175         return self.data[self.parent().targetNamespace][key]
01176 
01177     def __setitem__(self, key, item):
01178         item.parent = weakref.ref(self)
01179         self.list.append(item)
01180         targetNamespace = getattr(item, 'targetNamespace', self.parent().targetNamespace)
01181         if not self.data.has_key(targetNamespace):
01182             self.data[targetNamespace] = {}
01183         self.data[targetNamespace][key] = item
01184 
01185     def __isSequence(self, key):
01186         return (type(key) in (types.TupleType,types.ListType) and len(key) == 2)
01187 
01188     def keys(self):
01189         keys = []
01190         for tns in self.data.keys():
01191             keys.append(map(lambda i: (tns,self._func(i)), self.data[tns].values()))
01192         return keys
01193 
01194     def items(self):
01195         return map(lambda i: (self._func(i), i), self.list)
01196 
01197     def values(self):
01198         return self.list
01199 
01200 
01201 
01202 # This is a runtime guerilla patch for pulldom (used by minidom) so
01203 # that xml namespace declaration attributes are not lost in parsing.
01204 # We need them to do correct QName linking for XML Schema and WSDL.
01205 # The patch has been submitted to SF for the next Python version.
01206 
01207 from xml.dom.pulldom import PullDOM, START_ELEMENT
01208 if 1:
01209     def startPrefixMapping(self, prefix, uri):
01210         if not hasattr(self, '_xmlns_attrs'):
01211             self._xmlns_attrs = []
01212         self._xmlns_attrs.append((prefix or 'xmlns', uri))
01213         self._ns_contexts.append(self._current_context.copy())
01214         self._current_context[uri] = prefix or ''
01215 
01216     PullDOM.startPrefixMapping = startPrefixMapping
01217 
01218     def startElementNS(self, name, tagName , attrs):
01219         # Retrieve xml namespace declaration attributes.
01220         xmlns_uri = 'http://www.w3.org/2000/xmlns/'
01221         xmlns_attrs = getattr(self, '_xmlns_attrs', None)
01222         if xmlns_attrs is not None:
01223             for aname, value in xmlns_attrs:
01224                 attrs._attrs[(xmlns_uri, aname)] = value
01225             self._xmlns_attrs = []
01226         uri, localname = name
01227         if uri:
01228             # When using namespaces, the reader may or may not
01229             # provide us with the original name. If not, create
01230             # *a* valid tagName from the current context.
01231             if tagName is None:
01232                 prefix = self._current_context[uri]
01233                 if prefix:
01234                     tagName = prefix + ":" + localname
01235                 else:
01236                     tagName = localname
01237             if self.document:
01238                 node = self.document.createElementNS(uri, tagName)
01239             else:
01240                 node = self.buildDocument(uri, tagName)
01241         else:
01242             # When the tagname is not prefixed, it just appears as
01243             # localname
01244             if self.document:
01245                 node = self.document.createElement(localname)
01246             else:
01247                 node = self.buildDocument(None, localname)
01248 
01249         for aname,value in attrs.items():
01250             a_uri, a_localname = aname
01251             if a_uri == xmlns_uri:
01252                 if a_localname == 'xmlns':
01253                     qname = a_localname
01254                 else:
01255                     qname = 'xmlns:' + a_localname
01256                 attr = self.document.createAttributeNS(a_uri, qname)
01257                 node.setAttributeNodeNS(attr)
01258             elif a_uri:
01259                 prefix = self._current_context[a_uri]
01260                 if prefix:
01261                     qname = prefix + ":" + a_localname
01262                 else:
01263                     qname = a_localname
01264                 attr = self.document.createAttributeNS(a_uri, qname)
01265                 node.setAttributeNodeNS(attr)
01266             else:
01267                 attr = self.document.createAttribute(a_localname)
01268                 node.setAttributeNode(attr)
01269             attr.value = value
01270 
01271         self.lastEvent[1] = [(START_ELEMENT, node), None]
01272         self.lastEvent = self.lastEvent[1]
01273         self.push(node)
01274 
01275     PullDOM.startElementNS = startElementNS
01276 
01277 #
01278 # This is a runtime guerilla patch for minidom so
01279 # that xmlns prefixed attributes dont raise AttributeErrors
01280 # during cloning.
01281 #
01282 # Namespace declarations can appear in any start-tag, must look for xmlns
01283 # prefixed attribute names during cloning.
01284 #
01285 # key (attr.namespaceURI, tag)
01286 # ('http://www.w3.org/2000/xmlns/', u'xsd')   <xml.dom.minidom.Attr instance at 0x82227c4>
01287 # ('http://www.w3.org/2000/xmlns/', 'xmlns')   <xml.dom.minidom.Attr instance at 0x8414b3c>
01288 #
01289 # xml.dom.minidom.Attr.nodeName = xmlns:xsd
01290 # xml.dom.minidom.Attr.value =  = http://www.w3.org/2001/XMLSchema 
01291 
01292 if 1:
01293     def _clone_node(node, deep, newOwnerDocument):
01294         """
01295         Clone a node and give it the new owner document.
01296         Called by Node.cloneNode and Document.importNode
01297         """
01298         if node.ownerDocument.isSameNode(newOwnerDocument):
01299             operation = xml.dom.UserDataHandler.NODE_CLONED
01300         else:
01301             operation = xml.dom.UserDataHandler.NODE_IMPORTED
01302         if node.nodeType == xml.dom.minidom.Node.ELEMENT_NODE:
01303             clone = newOwnerDocument.createElementNS(node.namespaceURI,
01304                                                      node.nodeName)
01305             for attr in node.attributes.values():
01306                 clone.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value)
01307 
01308                 prefix, tag = xml.dom.minidom._nssplit(attr.nodeName)
01309                 if prefix == 'xmlns':
01310                     a = clone.getAttributeNodeNS(attr.namespaceURI, tag)
01311                 elif prefix:
01312                     a = clone.getAttributeNodeNS(attr.namespaceURI, tag)
01313                 else:
01314                     a = clone.getAttributeNodeNS(attr.namespaceURI, attr.nodeName)
01315                 a.specified = attr.specified
01316 
01317             if deep:
01318                 for child in node.childNodes:
01319                     c = xml.dom.minidom._clone_node(child, deep, newOwnerDocument)
01320                     clone.appendChild(c)
01321         elif node.nodeType == xml.dom.minidom.Node.DOCUMENT_FRAGMENT_NODE:
01322             clone = newOwnerDocument.createDocumentFragment()
01323             if deep:
01324                 for child in node.childNodes:
01325                     c = xml.dom.minidom._clone_node(child, deep, newOwnerDocument)
01326                     clone.appendChild(c)
01327 
01328         elif node.nodeType == xml.dom.minidom.Node.TEXT_NODE:
01329             clone = newOwnerDocument.createTextNode(node.data)
01330         elif node.nodeType == xml.dom.minidom.Node.CDATA_SECTION_NODE:
01331             clone = newOwnerDocument.createCDATASection(node.data)
01332         elif node.nodeType == xml.dom.minidom.Node.PROCESSING_INSTRUCTION_NODE:
01333             clone = newOwnerDocument.createProcessingInstruction(node.target,
01334                                                                  node.data)
01335         elif node.nodeType == xml.dom.minidom.Node.COMMENT_NODE:
01336             clone = newOwnerDocument.createComment(node.data)
01337         elif node.nodeType == xml.dom.minidom.Node.ATTRIBUTE_NODE:
01338             clone = newOwnerDocument.createAttributeNS(node.namespaceURI,
01339                                                        node.nodeName)
01340             clone.specified = True
01341             clone.value = node.value
01342         elif node.nodeType == xml.dom.minidom.Node.DOCUMENT_TYPE_NODE:
01343             assert node.ownerDocument is not newOwnerDocument
01344             operation = xml.dom.UserDataHandler.NODE_IMPORTED
01345             clone = newOwnerDocument.implementation.createDocumentType(
01346                 node.name, node.publicId, node.systemId)
01347             clone.ownerDocument = newOwnerDocument
01348             if deep:
01349                 clone.entities._seq = []
01350                 clone.notations._seq = []
01351                 for n in node.notations._seq:
01352                     notation = xml.dom.minidom.Notation(n.nodeName, n.publicId, n.systemId)
01353                     notation.ownerDocument = newOwnerDocument
01354                     clone.notations._seq.append(notation)
01355                     if hasattr(n, '_call_user_data_handler'):
01356                         n._call_user_data_handler(operation, n, notation)
01357                 for e in node.entities._seq:
01358                     entity = xml.dom.minidom.Entity(e.nodeName, e.publicId, e.systemId,
01359                                     e.notationName)
01360                     entity.actualEncoding = e.actualEncoding
01361                     entity.encoding = e.encoding
01362                     entity.version = e.version
01363                     entity.ownerDocument = newOwnerDocument
01364                     clone.entities._seq.append(entity)
01365                     if hasattr(e, '_call_user_data_handler'):
01366                         e._call_user_data_handler(operation, n, entity)
01367         else:
01368             # Note the cloning of Document and DocumentType nodes is
01369             # implemenetation specific.  minidom handles those cases
01370             # directly in the cloneNode() methods.
01371             raise xml.dom.NotSupportedErr("Cannot clone node %s" % repr(node))
01372 
01373         # Check for _call_user_data_handler() since this could conceivably
01374         # used with other DOM implementations (one of the FourThought
01375         # DOMs, perhaps?).
01376         if hasattr(node, '_call_user_data_handler'):
01377             node._call_user_data_handler(operation, node, clone)
01378         return clone
01379 
01380     xml.dom.minidom._clone_node = _clone_node
01381 

Generated on Wed Oct 20 2010 11:12:15 for APBS by  doxygen 1.7.2