| @@ -0,0 +1,303 @@ | |||||
| # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved. | |||||
| # | |||||
| # This software is subject to the provisions of the Zope Public License, | |||||
| # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. | |||||
| # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED | |||||
| # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |||||
| # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS | |||||
| # FOR A PARTICULAR PURPOSE. | |||||
| from urlparse import urlparse | |||||
| from ZSI import * | |||||
| from ZSI.client import * | |||||
| import weakref | |||||
| from Utility import DOM | |||||
| import WSDLTools | |||||
| class SOAPCallInfo: | |||||
| """SOAPCallInfo captures the important binding information about a | |||||
| SOAP operation, in a structure that is easier to work with than | |||||
| raw WSDL structures.""" | |||||
| def __init__(self, methodName): | |||||
| self.methodName = methodName | |||||
| self.inheaders = [] | |||||
| self.outheaders = [] | |||||
| self.inparams = [] | |||||
| self.outparams = [] | |||||
| self.retval = None | |||||
| encodingStyle = DOM.NS_SOAP_ENC | |||||
| documentation = '' | |||||
| soapAction = None | |||||
| transport = None | |||||
| namespace = None | |||||
| location = None | |||||
| use = 'encoded' | |||||
| style = 'rpc' | |||||
| def addInParameter(self, name, type, namespace=None, element_type=0): | |||||
| """Add an input parameter description to the call info.""" | |||||
| parameter = ParameterInfo(name, type, namespace, element_type) | |||||
| self.inparams.append(parameter) | |||||
| return parameter | |||||
| def addOutParameter(self, name, type, namespace=None, element_type=0): | |||||
| """Add an output parameter description to the call info.""" | |||||
| parameter = ParameterInfo(name, type, namespace, element_type) | |||||
| self.outparams.append(parameter) | |||||
| return parameter | |||||
| def setReturnParameter(self, name, type, namespace=None, element_type=0): | |||||
| """Set the return parameter description for the call info.""" | |||||
| parameter = ParameterInfo(name, type, namespace, element_type) | |||||
| self.retval = parameter | |||||
| return parameter | |||||
| def addInHeaderInfo(self, name, type, namespace, element_type=0, | |||||
| mustUnderstand=0): | |||||
| """Add an input SOAP header description to the call info.""" | |||||
| headerinfo = HeaderInfo(name, type, namespace, element_type) | |||||
| if mustUnderstand: | |||||
| headerinfo.mustUnderstand = 1 | |||||
| self.inheaders.append(headerinfo) | |||||
| return headerinfo | |||||
| def addOutHeaderInfo(self, name, type, namespace, element_type=0, | |||||
| mustUnderstand=0): | |||||
| """Add an output SOAP header description to the call info.""" | |||||
| headerinfo = HeaderInfo(name, type, namespace, element_type) | |||||
| if mustUnderstand: | |||||
| headerinfo.mustUnderstand = 1 | |||||
| self.outheaders.append(headerinfo) | |||||
| return headerinfo | |||||
| def getInParameters(self): | |||||
| """Return a sequence of the in parameters of the method.""" | |||||
| return self.inparams | |||||
| def getOutParameters(self): | |||||
| """Return a sequence of the out parameters of the method.""" | |||||
| return self.outparams | |||||
| def getReturnParameter(self): | |||||
| """Return param info about the return value of the method.""" | |||||
| return self.retval | |||||
| def getInHeaders(self): | |||||
| """Return a sequence of the in headers of the method.""" | |||||
| return self.inheaders | |||||
| def getOutHeaders(self): | |||||
| """Return a sequence of the out headers of the method.""" | |||||
| return self.outheaders | |||||
| class ParameterInfo: | |||||
| """A ParameterInfo object captures parameter binding information.""" | |||||
| def __init__(self, name, type, namespace=None, element_type=0): | |||||
| if element_type: | |||||
| self.element_type = 1 | |||||
| if namespace is not None: | |||||
| self.namespace = namespace | |||||
| self.name = name | |||||
| self.type = type | |||||
| element_type = 0 | |||||
| namespace = None | |||||
| default = None | |||||
| class HeaderInfo(ParameterInfo): | |||||
| """A HeaderInfo object captures SOAP header binding information.""" | |||||
| def __init__(self, name, type, namespace, element_type=None): | |||||
| ParameterInfo.__init__(self, name, type, namespace, element_type) | |||||
| mustUnderstand = 0 | |||||
| actor = None | |||||
| def callInfoFromWSDL(port, name): | |||||
| """Return a SOAPCallInfo given a WSDL port and operation name.""" | |||||
| wsdl = port.getService().getWSDL() | |||||
| binding = port.getBinding() | |||||
| portType = binding.getPortType() | |||||
| operation = portType.operations[name] | |||||
| opbinding = binding.operations[name] | |||||
| messages = wsdl.messages | |||||
| callinfo = SOAPCallInfo(name) | |||||
| addrbinding = port.getAddressBinding() | |||||
| if not isinstance(addrbinding, WSDLTools.SoapAddressBinding): | |||||
| raise ValueError, 'Unsupported binding type.' | |||||
| callinfo.location = addrbinding.location | |||||
| soapbinding = binding.findBinding(WSDLTools.SoapBinding) | |||||
| if soapbinding is None: | |||||
| raise ValueError, 'Missing soap:binding element.' | |||||
| callinfo.transport = soapbinding.transport | |||||
| callinfo.style = soapbinding.style or 'document' | |||||
| soap_op_binding = opbinding.findBinding(WSDLTools.SoapOperationBinding) | |||||
| if soap_op_binding is not None: | |||||
| callinfo.soapAction = soap_op_binding.soapAction | |||||
| callinfo.style = soap_op_binding.style or callinfo.style | |||||
| parameterOrder = operation.parameterOrder | |||||
| if operation.input is not None: | |||||
| message = messages[operation.input.message] | |||||
| msgrole = opbinding.input | |||||
| mime = msgrole.findBinding(WSDLTools.MimeMultipartRelatedBinding) | |||||
| if mime is not None: | |||||
| raise ValueError, 'Mime bindings are not supported.' | |||||
| else: | |||||
| for item in msgrole.findBindings(WSDLTools.SoapHeaderBinding): | |||||
| part = messages[item.message].parts[item.part] | |||||
| header = callinfo.addInHeaderInfo( | |||||
| part.name, | |||||
| part.element or part.type, | |||||
| item.namespace, | |||||
| element_type = part.element and 1 or 0 | |||||
| ) | |||||
| header.encodingStyle = item.encodingStyle | |||||
| body = msgrole.findBinding(WSDLTools.SoapBodyBinding) | |||||
| if body is None: | |||||
| raise ValueError, 'Missing soap:body binding.' | |||||
| callinfo.encodingStyle = body.encodingStyle | |||||
| callinfo.namespace = body.namespace | |||||
| callinfo.use = body.use | |||||
| if body.parts is not None: | |||||
| parts = [] | |||||
| for name in body.parts: | |||||
| parts.append(message.parts[name]) | |||||
| else: | |||||
| parts = message.parts.values() | |||||
| for part in parts: | |||||
| callinfo.addInParameter( | |||||
| part.name, | |||||
| part.element or part.type, | |||||
| element_type = part.element and 1 or 0 | |||||
| ) | |||||
| if operation.output is not None: | |||||
| message = messages[operation.output.message] | |||||
| msgrole = opbinding.output | |||||
| mime = msgrole.findBinding(WSDLTools.MimeMultipartRelatedBinding) | |||||
| if mime is not None: | |||||
| raise ValueError, 'Mime bindings are not supported.' | |||||
| else: | |||||
| for item in msgrole.findBindings(WSDLTools.SoapHeaderBinding): | |||||
| part = messages[item.message].parts[item.part] | |||||
| header = callinfo.addOutHeaderInfo( | |||||
| part.name, | |||||
| part.element or part.type, | |||||
| item.namespace, | |||||
| element_type = part.element and 1 or 0 | |||||
| ) | |||||
| header.encodingStyle = item.encodingStyle | |||||
| body = msgrole.findBinding(WSDLTools.SoapBodyBinding) | |||||
| if body is None: | |||||
| raise ValueError, 'Missing soap:body binding.' | |||||
| callinfo.encodingStyle = body.encodingStyle | |||||
| callinfo.namespace = body.namespace | |||||
| callinfo.use = body.use | |||||
| if body.parts is not None: | |||||
| parts = [] | |||||
| for name in body.parts: | |||||
| parts.append(message.parts[name]) | |||||
| else: | |||||
| parts = message.parts.values() | |||||
| if parts: | |||||
| callinfo.setReturnParameter( | |||||
| parts[0].name, | |||||
| parts[0].element or parts[0].type, | |||||
| element_type = parts[0].element and 1 or 0 | |||||
| ) | |||||
| for part in parts[1:]: | |||||
| callinfo.addOutParameter( | |||||
| part.name, | |||||
| part.element or part.type, | |||||
| element_type = part.element and 1 or 0 | |||||
| ) | |||||
| return callinfo | |||||
| class ServiceProxy: | |||||
| """A ServiceProxy provides a convenient way to call a remote web | |||||
| service that is described with WSDL. The proxy exposes methods | |||||
| that reflect the methods of the remote web service.""" | |||||
| def __init__(self, wsdl, service=None, port=None, tracefile=None, | |||||
| typesmodule=None, nsdict=None): | |||||
| if not hasattr(wsdl, 'targetNamespace'): | |||||
| wsdl = WSDLTools.WSDLReader().loadFromURL(wsdl) | |||||
| # for item in wsdl.types.items(): | |||||
| # self._serializer.loadSchema(item) | |||||
| self._service = wsdl.services[service or 0] | |||||
| self.__doc__ = self._service.documentation | |||||
| self._port = self._service.ports[port or 0] | |||||
| self._name = self._service.name | |||||
| self._wsdl = wsdl | |||||
| self._tracefile = tracefile | |||||
| self._typesmodule = typesmodule | |||||
| self._nsdict = nsdict | |||||
| binding = self._port.getBinding() | |||||
| portType = binding.getPortType() | |||||
| for item in portType.operations: | |||||
| callinfo = callInfoFromWSDL(self._port, item.name) | |||||
| method = MethodProxy(self, callinfo) | |||||
| setattr(self, item.name, method) | |||||
| def _call(self, name, *args, **kwargs): | |||||
| """Call the named remote web service method.""" | |||||
| if len(args) and len(kwargs): | |||||
| raise TypeError( | |||||
| 'Use positional or keyword argument only.' | |||||
| ) | |||||
| callinfo = getattr(self, name).callinfo | |||||
| url = callinfo.location | |||||
| (protocol, host, uri, query, fragment, identifier) = urlparse(url) | |||||
| port = 80 | |||||
| if host.find(':') >= 0: | |||||
| host, port = host.split(':') | |||||
| params = callinfo.getInParameters() | |||||
| host = str(host) | |||||
| port = str(port) | |||||
| binding = Binding(host=host, tracefile=self._tracefile, | |||||
| ssl=(protocol == 'https'), | |||||
| port=port, url=uri, typesmodule=self._typesmodule, | |||||
| nsdict=self._nsdict) | |||||
| apply(getattr(binding, callinfo.methodName), args) | |||||
| #print binding.ReceiveRaw() | |||||
| return binding.Receive() | |||||
| class MethodProxy: | |||||
| """ """ | |||||
| def __init__(self, parent, callinfo): | |||||
| self.__name__ = callinfo.methodName | |||||
| self.__doc__ = callinfo.documentation | |||||
| self.callinfo = callinfo | |||||
| self.parent = weakref.ref(parent) | |||||
| def __call__(self, *args, **kwargs): | |||||
| return self.parent()._call(self.__name__, *args, **kwargs) | |||||
| @@ -0,0 +1,176 @@ | |||||
| """Based on code from timeout_socket.py, with some tweaks for compatibility. | |||||
| These tweaks should really be rolled back into timeout_socket, but it's | |||||
| not totally clear who is maintaining it at this point. In the meantime, | |||||
| we'll use a different module name for our tweaked version to avoid any | |||||
| confusion. | |||||
| The original timeout_socket is by: | |||||
| Scott Cotton <scott@chronis.pobox.com> | |||||
| Lloyd Zusman <ljz@asfast.com> | |||||
| Phil Mayes <pmayes@olivebr.com> | |||||
| Piers Lauder <piers@cs.su.oz.au> | |||||
| Radovan Garabik <garabik@melkor.dnp.fmph.uniba.sk> | |||||
| """ | |||||
| import string, socket, select, errno | |||||
| WSAEINVAL = getattr(errno, 'WSAEINVAL', 10022) | |||||
| class TimeoutSocket: | |||||
| """A socket imposter that supports timeout limits.""" | |||||
| def __init__(self, timeout=20, sock=None): | |||||
| self.timeout = float(timeout) | |||||
| self.inbuf = '' | |||||
| if sock is None: | |||||
| sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |||||
| self.sock = sock | |||||
| self.sock.setblocking(0) | |||||
| self._rbuf = '' | |||||
| self._wbuf = '' | |||||
| def __getattr__(self, name): | |||||
| # Delegate to real socket attributes. | |||||
| return getattr(self.sock, name) | |||||
| def connect(self, *addr): | |||||
| timeout = self.timeout | |||||
| sock = self.sock | |||||
| try: | |||||
| # Non-blocking mode | |||||
| sock.setblocking(0) | |||||
| apply(sock.connect, addr) | |||||
| sock.setblocking(timeout != 0) | |||||
| return 1 | |||||
| except socket.error,why: | |||||
| if not timeout: | |||||
| raise | |||||
| sock.setblocking(1) | |||||
| if len(why.args) == 1: | |||||
| code = 0 | |||||
| else: | |||||
| code, why = why | |||||
| if code not in ( | |||||
| errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK | |||||
| ): | |||||
| raise | |||||
| r,w,e = select.select([],[sock],[],timeout) | |||||
| if w: | |||||
| try: | |||||
| apply(sock.connect, addr) | |||||
| return 1 | |||||
| except socket.error,why: | |||||
| if len(why.args) == 1: | |||||
| code = 0 | |||||
| else: | |||||
| code, why = why | |||||
| if code in (errno.EISCONN, WSAEINVAL): | |||||
| return 1 | |||||
| raise | |||||
| raise TimeoutError('socket connect() timeout.') | |||||
| def send(self, data, flags=0): | |||||
| total = len(data) | |||||
| next = 0 | |||||
| while 1: | |||||
| r, w, e = select.select([],[self.sock], [], self.timeout) | |||||
| if w: | |||||
| buff = data[next:next + 8192] | |||||
| sent = self.sock.send(buff, flags) | |||||
| next = next + sent | |||||
| if next == total: | |||||
| return total | |||||
| continue | |||||
| raise TimeoutError('socket send() timeout.') | |||||
| def recv(self, amt, flags=0): | |||||
| if select.select([self.sock], [], [], self.timeout)[0]: | |||||
| return self.sock.recv(amt, flags) | |||||
| raise TimeoutError('socket recv() timeout.') | |||||
| buffsize = 4096 | |||||
| handles = 1 | |||||
| def makefile(self, mode="r", buffsize=-1): | |||||
| self.handles = self.handles + 1 | |||||
| self.mode = mode | |||||
| return self | |||||
| def close(self): | |||||
| self.handles = self.handles - 1 | |||||
| if self.handles == 0 and self.sock.fileno() >= 0: | |||||
| self.sock.close() | |||||
| def read(self, n=-1): | |||||
| if not isinstance(n, type(1)): | |||||
| n = -1 | |||||
| if n >= 0: | |||||
| k = len(self._rbuf) | |||||
| if n <= k: | |||||
| data = self._rbuf[:n] | |||||
| self._rbuf = self._rbuf[n:] | |||||
| return data | |||||
| n = n - k | |||||
| L = [self._rbuf] | |||||
| self._rbuf = "" | |||||
| while n > 0: | |||||
| new = self.recv(max(n, self.buffsize)) | |||||
| if not new: break | |||||
| k = len(new) | |||||
| if k > n: | |||||
| L.append(new[:n]) | |||||
| self._rbuf = new[n:] | |||||
| break | |||||
| L.append(new) | |||||
| n = n - k | |||||
| return "".join(L) | |||||
| k = max(4096, self.buffsize) | |||||
| L = [self._rbuf] | |||||
| self._rbuf = "" | |||||
| while 1: | |||||
| new = self.recv(k) | |||||
| if not new: break | |||||
| L.append(new) | |||||
| k = min(k*2, 1024**2) | |||||
| return "".join(L) | |||||
| def readline(self, limit=-1): | |||||
| data = "" | |||||
| i = self._rbuf.find('\n') | |||||
| while i < 0 and not (0 < limit <= len(self._rbuf)): | |||||
| new = self.recv(self.buffsize) | |||||
| if not new: break | |||||
| i = new.find('\n') | |||||
| if i >= 0: i = i + len(self._rbuf) | |||||
| self._rbuf = self._rbuf + new | |||||
| if i < 0: i = len(self._rbuf) | |||||
| else: i = i+1 | |||||
| if 0 <= limit < len(self._rbuf): i = limit | |||||
| data, self._rbuf = self._rbuf[:i], self._rbuf[i:] | |||||
| return data | |||||
| def readlines(self, sizehint = 0): | |||||
| total = 0 | |||||
| list = [] | |||||
| while 1: | |||||
| line = self.readline() | |||||
| if not line: break | |||||
| list.append(line) | |||||
| total += len(line) | |||||
| if sizehint and total >= sizehint: | |||||
| break | |||||
| return list | |||||
| def writelines(self, list): | |||||
| self.send(''.join(list)) | |||||
| def write(self, data): | |||||
| self.send(data) | |||||
| def flush(self): | |||||
| pass | |||||
| class TimeoutError(Exception): | |||||
| pass | |||||
| @@ -0,0 +1,753 @@ | |||||
| # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved. | |||||
| # | |||||
| # This software is subject to the provisions of the Zope Public License, | |||||
| # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. | |||||
| # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED | |||||
| # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |||||
| # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS | |||||
| # FOR A PARTICULAR PURPOSE. | |||||
| from string import join, strip, split | |||||
| from UserDict import UserDict | |||||
| from StringIO import StringIO | |||||
| import xml.dom.minidom, weakref | |||||
| import string, httplib, smtplib, urllib, socket | |||||
| from TimeoutSocket import TimeoutSocket, TimeoutError | |||||
| from StringIO import StringIO | |||||
| from urlparse import urlparse | |||||
| from httplib import HTTPConnection, HTTPSConnection | |||||
| class HTTPResponse: | |||||
| """Captures the information in an HTTP response message.""" | |||||
| def __init__(self, response): | |||||
| self.status = response.status | |||||
| self.reason = response.reason | |||||
| self.headers = response.msg | |||||
| self.body = response.read() or None | |||||
| response.close() | |||||
| class TimeoutHTTP(HTTPConnection): | |||||
| """A custom http connection object that supports socket timeout.""" | |||||
| def __init__(self, host, port=None, timeout=20): | |||||
| HTTPConnection.__init__(self, host, port) | |||||
| self.timeout = timeout | |||||
| def connect(self): | |||||
| self.sock = TimeoutSocket(self.timeout) | |||||
| self.sock.connect((self.host, self.port)) | |||||
| class TimeoutHTTPS(HTTPSConnection): | |||||
| """A custom https object that supports socket timeout. Note that this | |||||
| is not really complete. The builtin SSL support in the Python socket | |||||
| module requires a real socket (type) to be passed in to be hooked to | |||||
| SSL. That means our fake socket won't work and our timeout hacks are | |||||
| bypassed for send and recv calls. Since our hack _is_ in place at | |||||
| connect() time, it should at least provide some timeout protection.""" | |||||
| def __init__(self, host, port=None, timeout=20, **kwargs): | |||||
| if not hasattr(socket, 'ssl'): | |||||
| raise ValueError( | |||||
| 'This Python installation does not have SSL support.' | |||||
| ) | |||||
| HTTPSConnection.__init__(self, str(host), port, **kwargs) | |||||
| self.timeout = timeout | |||||
| def connect(self): | |||||
| sock = TimeoutSocket(self.timeout) | |||||
| sock.connect((self.host, self.port)) | |||||
| realsock = getattr(sock.sock, '_sock', sock.sock) | |||||
| ssl = socket.ssl(realsock, self.key_file, self.cert_file) | |||||
| self.sock = httplib.FakeSocket(sock, ssl) | |||||
| def urlopen(url, timeout=20, redirects=None): | |||||
| """A minimal urlopen replacement hack that supports timeouts for http. | |||||
| Note that this supports GET only.""" | |||||
| scheme, host, path, params, query, frag = urlparse(url) | |||||
| if not scheme in ('http', 'https'): | |||||
| return urllib.urlopen(url) | |||||
| if params: path = '%s;%s' % (path, params) | |||||
| if query: path = '%s?%s' % (path, query) | |||||
| if frag: path = '%s#%s' % (path, frag) | |||||
| if scheme == 'https': | |||||
| if not hasattr(socket, 'ssl'): | |||||
| raise ValueError( | |||||
| 'This Python installation does not have SSL support.' | |||||
| ) | |||||
| conn = TimeoutHTTPS(host, None, timeout) | |||||
| else: | |||||
| conn = TimeoutHTTP(host, None, timeout) | |||||
| conn.putrequest('GET', path) | |||||
| conn.putheader('Connection', 'close') | |||||
| conn.endheaders() | |||||
| response = None | |||||
| while 1: | |||||
| response = conn.getresponse() | |||||
| if response.status != 100: | |||||
| break | |||||
| conn._HTTPConnection__state = httplib._CS_REQ_SENT | |||||
| conn._HTTPConnection__response = None | |||||
| status = response.status | |||||
| # If we get an HTTP redirect, we will follow it automatically. | |||||
| if status >= 300 and status < 400: | |||||
| location = response.msg.getheader('location') | |||||
| if location is not None: | |||||
| response.close() | |||||
| if redirects is not None and redirects.has_key(location): | |||||
| raise RecursionError( | |||||
| 'Circular HTTP redirection detected.' | |||||
| ) | |||||
| if redirects is None: | |||||
| redirects = {} | |||||
| redirects[location] = 1 | |||||
| return urlopen(location, timeout, redirects) | |||||
| raise HTTPResponse(response) | |||||
| if not (status >= 200 and status < 300): | |||||
| raise HTTPResponse(response) | |||||
| body = StringIO(response.read()) | |||||
| response.close() | |||||
| return body | |||||
| class DOM: | |||||
| """The DOM singleton defines a number of XML related constants and | |||||
| provides a number of utility methods for DOM related tasks. It | |||||
| also provides some basic abstractions so that the rest of the | |||||
| package need not care about actual DOM implementation in use.""" | |||||
| # Namespace stuff related to the SOAP specification. | |||||
| NS_SOAP_ENV_1_1 = 'http://schemas.xmlsoap.org/soap/envelope/' | |||||
| NS_SOAP_ENC_1_1 = 'http://schemas.xmlsoap.org/soap/encoding/' | |||||
| NS_SOAP_ENV_1_2 = 'http://www.w3.org/2001/06/soap-envelope' | |||||
| NS_SOAP_ENC_1_2 = 'http://www.w3.org/2001/06/soap-encoding' | |||||
| NS_SOAP_ENV_ALL = (NS_SOAP_ENV_1_1, NS_SOAP_ENV_1_2) | |||||
| NS_SOAP_ENC_ALL = (NS_SOAP_ENC_1_1, NS_SOAP_ENC_1_2) | |||||
| NS_SOAP_ENV = NS_SOAP_ENV_1_1 | |||||
| NS_SOAP_ENC = NS_SOAP_ENC_1_1 | |||||
| _soap_uri_mapping = { | |||||
| NS_SOAP_ENV_1_1 : '1.1', | |||||
| NS_SOAP_ENV_1_2 : '1.2', | |||||
| } | |||||
| SOAP_ACTOR_NEXT_1_1 = 'http://schemas.xmlsoap.org/soap/actor/next' | |||||
| SOAP_ACTOR_NEXT_1_2 = 'http://www.w3.org/2001/06/soap-envelope/actor/next' | |||||
| SOAP_ACTOR_NEXT_ALL = (SOAP_ACTOR_NEXT_1_1, SOAP_ACTOR_NEXT_1_2) | |||||
| def SOAPUriToVersion(self, uri): | |||||
| """Return the SOAP version related to an envelope uri.""" | |||||
| value = self._soap_uri_mapping.get(uri) | |||||
| if value is not None: | |||||
| return value | |||||
| raise ValueError( | |||||
| 'Unsupported SOAP envelope uri: %s' % uri | |||||
| ) | |||||
| def GetSOAPEnvUri(self, version): | |||||
| """Return the appropriate SOAP envelope uri for a given | |||||
| human-friendly SOAP version string (e.g. '1.1').""" | |||||
| attrname = 'NS_SOAP_ENV_%s' % join(split(version, '.'), '_') | |||||
| value = getattr(self, attrname, None) | |||||
| if value is not None: | |||||
| return value | |||||
| raise ValueError( | |||||
| 'Unsupported SOAP version: %s' % version | |||||
| ) | |||||
| def GetSOAPEncUri(self, version): | |||||
| """Return the appropriate SOAP encoding uri for a given | |||||
| human-friendly SOAP version string (e.g. '1.1').""" | |||||
| attrname = 'NS_SOAP_ENC_%s' % join(split(version, '.'), '_') | |||||
| value = getattr(self, attrname, None) | |||||
| if value is not None: | |||||
| return value | |||||
| raise ValueError( | |||||
| 'Unsupported SOAP version: %s' % version | |||||
| ) | |||||
| def GetSOAPActorNextUri(self, version): | |||||
| """Return the right special next-actor uri for a given | |||||
| human-friendly SOAP version string (e.g. '1.1').""" | |||||
| attrname = 'SOAP_ACTOR_NEXT_%s' % join(split(version, '.'), '_') | |||||
| value = getattr(self, attrname, None) | |||||
| if value is not None: | |||||
| return value | |||||
| raise ValueError( | |||||
| 'Unsupported SOAP version: %s' % version | |||||
| ) | |||||
| # Namespace stuff related to XML Schema. | |||||
| NS_XSD_99 = 'http://www.w3.org/1999/XMLSchema' | |||||
| NS_XSI_99 = 'http://www.w3.org/1999/XMLSchema-instance' | |||||
| NS_XSD_00 = 'http://www.w3.org/2000/10/XMLSchema' | |||||
| NS_XSI_00 = 'http://www.w3.org/2000/10/XMLSchema-instance' | |||||
| NS_XSD_01 = 'http://www.w3.org/2001/XMLSchema' | |||||
| NS_XSI_01 = 'http://www.w3.org/2001/XMLSchema-instance' | |||||
| NS_XSD_ALL = (NS_XSD_99, NS_XSD_00, NS_XSD_01) | |||||
| NS_XSI_ALL = (NS_XSI_99, NS_XSI_00, NS_XSI_01) | |||||
| NS_XSD = NS_XSD_01 | |||||
| NS_XSI = NS_XSI_01 | |||||
| _xsd_uri_mapping = { | |||||
| NS_XSD_99 : NS_XSI_99, | |||||
| NS_XSD_00 : NS_XSI_00, | |||||
| NS_XSD_01 : NS_XSI_01, | |||||
| } | |||||
| for key, value in _xsd_uri_mapping.items(): | |||||
| _xsd_uri_mapping[value] = key | |||||
| def InstanceUriForSchemaUri(self, uri): | |||||
| """Return the appropriate matching XML Schema instance uri for | |||||
| the given XML Schema namespace uri.""" | |||||
| return self._xsd_uri_mapping.get(uri) | |||||
| def SchemaUriForInstanceUri(self, uri): | |||||
| """Return the appropriate matching XML Schema namespace uri for | |||||
| the given XML Schema instance namespace uri.""" | |||||
| return self._xsd_uri_mapping.get(uri) | |||||
| # Namespace stuff related to WSDL. | |||||
| NS_WSDL_1_1 = 'http://schemas.xmlsoap.org/wsdl/' | |||||
| NS_WSDL_ALL = (NS_WSDL_1_1,) | |||||
| NS_WSDL = NS_WSDL_1_1 | |||||
| NS_SOAP_BINDING_1_1 = 'http://schemas.xmlsoap.org/wsdl/soap/' | |||||
| NS_HTTP_BINDING_1_1 = 'http://schemas.xmlsoap.org/wsdl/http/' | |||||
| NS_MIME_BINDING_1_1 = 'http://schemas.xmlsoap.org/wsdl/mime/' | |||||
| NS_SOAP_BINDING_ALL = (NS_SOAP_BINDING_1_1,) | |||||
| NS_HTTP_BINDING_ALL = (NS_HTTP_BINDING_1_1,) | |||||
| NS_MIME_BINDING_ALL = (NS_MIME_BINDING_1_1,) | |||||
| NS_SOAP_BINDING = NS_SOAP_BINDING_1_1 | |||||
| NS_HTTP_BINDING = NS_HTTP_BINDING_1_1 | |||||
| NS_MIME_BINDING = NS_MIME_BINDING_1_1 | |||||
| NS_SOAP_HTTP_1_1 = 'http://schemas.xmlsoap.org/soap/http' | |||||
| NS_SOAP_HTTP_ALL = (NS_SOAP_HTTP_1_1,) | |||||
| NS_SOAP_HTTP = NS_SOAP_HTTP_1_1 | |||||
| _wsdl_uri_mapping = { | |||||
| NS_WSDL_1_1 : '1.1', | |||||
| } | |||||
| def WSDLUriToVersion(self, uri): | |||||
| """Return the WSDL version related to a WSDL namespace uri.""" | |||||
| value = self._wsdl_uri_mapping.get(uri) | |||||
| if value is not None: | |||||
| return value | |||||
| raise ValueError( | |||||
| 'Unsupported SOAP envelope uri: %s' % uri | |||||
| ) | |||||
| def GetWSDLUri(self, version): | |||||
| attr = 'NS_WSDL_%s' % join(split(version, '.'), '_') | |||||
| value = getattr(self, attr, None) | |||||
| if value is not None: | |||||
| return value | |||||
| raise ValueError( | |||||
| 'Unsupported WSDL version: %s' % version | |||||
| ) | |||||
| def GetWSDLSoapBindingUri(self, version): | |||||
| attr = 'NS_SOAP_BINDING_%s' % join(split(version, '.'), '_') | |||||
| value = getattr(self, attr, None) | |||||
| if value is not None: | |||||
| return value | |||||
| raise ValueError( | |||||
| 'Unsupported WSDL version: %s' % version | |||||
| ) | |||||
| def GetWSDLHttpBindingUri(self, version): | |||||
| attr = 'NS_HTTP_BINDING_%s' % join(split(version, '.'), '_') | |||||
| value = getattr(self, attr, None) | |||||
| if value is not None: | |||||
| return value | |||||
| raise ValueError( | |||||
| 'Unsupported WSDL version: %s' % version | |||||
| ) | |||||
| def GetWSDLMimeBindingUri(self, version): | |||||
| attr = 'NS_MIME_BINDING_%s' % join(split(version, '.'), '_') | |||||
| value = getattr(self, attr, None) | |||||
| if value is not None: | |||||
| return value | |||||
| raise ValueError( | |||||
| 'Unsupported WSDL version: %s' % version | |||||
| ) | |||||
| def GetWSDLHttpTransportUri(self, version): | |||||
| attr = 'NS_SOAP_HTTP_%s' % join(split(version, '.'), '_') | |||||
| value = getattr(self, attr, None) | |||||
| if value is not None: | |||||
| return value | |||||
| raise ValueError( | |||||
| 'Unsupported WSDL version: %s' % version | |||||
| ) | |||||
| # Other xml namespace constants. | |||||
| NS_XMLNS = 'http://www.w3.org/2000/xmlns/' | |||||
| def isElement(self, node, name, nsuri=None): | |||||
| """Return true if the given node is an element with the given | |||||
| name and optional namespace uri.""" | |||||
| if node.nodeType == node.ELEMENT_NODE: | |||||
| return 0 | |||||
| return node.localName == name and \ | |||||
| (nsuri is None or self.nsUriMatch(node.namespaceURI, nsuri)) | |||||
| def getElement(self, node, name, nsuri=None, default=join): | |||||
| """Return the first child of node with a matching name and | |||||
| namespace uri, or the default if one is provided.""" | |||||
| nsmatch = self.nsUriMatch | |||||
| ELEMENT_NODE = node.ELEMENT_NODE | |||||
| for child in node.childNodes: | |||||
| if child.nodeType == ELEMENT_NODE: | |||||
| if ((child.localName == name or name is None) and | |||||
| (nsuri is None or nsmatch(child.namespaceURI, nsuri)) | |||||
| ): | |||||
| return child | |||||
| if default is not join: | |||||
| return default | |||||
| raise KeyError, name | |||||
| def getElementById(self, node, id, default=join): | |||||
| """Return the first child of node matching an id reference.""" | |||||
| attrget = self.getAttr | |||||
| ELEMENT_NODE = node.ELEMENT_NODE | |||||
| for child in node.childNodes: | |||||
| if child.nodeType == ELEMENT_NODE: | |||||
| if attrget(child, 'id') == id: | |||||
| return child | |||||
| if default is not join: | |||||
| return default | |||||
| raise KeyError, name | |||||
| def getMappingById(self, document, depth=None, element=None, | |||||
| mapping=None, level=1): | |||||
| """Create an id -> element mapping of those elements within a | |||||
| document that define an id attribute. The depth of the search | |||||
| may be controlled by using the (1-based) depth argument.""" | |||||
| if document is not None: | |||||
| element = document.documentElement | |||||
| mapping = {} | |||||
| attr = element._attrs.get('id', None) | |||||
| if attr is not None: | |||||
| mapping[attr.value] = element | |||||
| if depth is None or depth > level: | |||||
| level = level + 1 | |||||
| ELEMENT_NODE = element.ELEMENT_NODE | |||||
| for child in element.childNodes: | |||||
| if child.nodeType == ELEMENT_NODE: | |||||
| self.getMappingById(None, depth, child, mapping, level) | |||||
| return mapping | |||||
| def getElements(self, node, name, nsuri=None): | |||||
| """Return a sequence of the child elements of the given node that | |||||
| match the given name and optional namespace uri.""" | |||||
| nsmatch = self.nsUriMatch | |||||
| result = [] | |||||
| ELEMENT_NODE = node.ELEMENT_NODE | |||||
| for child in node.childNodes: | |||||
| if child.nodeType == ELEMENT_NODE: | |||||
| if ((child.localName == name or name is None) and ( | |||||
| (nsuri is None) or nsmatch(child.namespaceURI, nsuri))): | |||||
| result.append(child) | |||||
| return result | |||||
| def hasAttr(self, node, name, nsuri=None): | |||||
| """Return true if element has attribute with the given name and | |||||
| optional nsuri. If nsuri is not specified, returns true if an | |||||
| attribute exists with the given name with any namespace.""" | |||||
| if nsuri is None: | |||||
| if node._attrs.has_key(name): | |||||
| return 1 | |||||
| for item in node._attrsNS.keys(): | |||||
| if item[1] == name: | |||||
| return 1 | |||||
| return 0 | |||||
| return node.attrsNS.has_key((nsuri, name)) | |||||
| def getAttr(self, node, name, nsuri=None, default=join): | |||||
| """Return the value of the attribute named 'name' with the | |||||
| optional nsuri, or the default if one is specified. If | |||||
| nsuri is not specified, an attribute that matches the | |||||
| given name will be returned regardless of namespace.""" | |||||
| if nsuri is None: | |||||
| result = node._attrs.get(name, None) | |||||
| if result is None: | |||||
| for item in node._attrsNS.keys(): | |||||
| if item[1] == name: | |||||
| result = node._attrsNS[item] | |||||
| break | |||||
| else: | |||||
| result = node._attrsNS.get((nsuri, name), None) | |||||
| if result is not None: | |||||
| return result.value | |||||
| if default is not join: | |||||
| return default | |||||
| return '' | |||||
| def getElementText(self, node, preserve_ws=None): | |||||
| """Return the text value of an xml element node. Leading and trailing | |||||
| whitespace is stripped from the value unless the preserve_ws flag | |||||
| is passed with a true value.""" | |||||
| result = [] | |||||
| for child in node.childNodes: | |||||
| nodetype = child.nodeType | |||||
| if nodetype == child.TEXT_NODE or \ | |||||
| nodetype == child.CDATA_SECTION_NODE: | |||||
| result.append(child.nodeValue) | |||||
| value = join(result, '') | |||||
| if preserve_ws is None: | |||||
| value = strip(value) | |||||
| return value | |||||
| def findNamespaceURI(self, prefix, node): | |||||
| """Find a namespace uri given a prefix and a context node.""" | |||||
| attrkey = (self.NS_XMLNS, prefix) | |||||
| DOCUMENT_NODE = node.DOCUMENT_NODE | |||||
| ELEMENT_NODE = node.ELEMENT_NODE | |||||
| while 1: | |||||
| if node.nodeType != ELEMENT_NODE: | |||||
| node = node.parentNode | |||||
| continue | |||||
| result = node._attrsNS.get(attrkey, None) | |||||
| if result is not None: | |||||
| return result.value | |||||
| if hasattr(node, '__imported__'): | |||||
| raise DOMException('Value for prefix %s not found.' % prefix) | |||||
| node = node.parentNode | |||||
| if node.nodeType == DOCUMENT_NODE: | |||||
| raise DOMException('Value for prefix %s not found.' % prefix) | |||||
| def findDefaultNS(self, node): | |||||
| """Return the current default namespace uri for the given node.""" | |||||
| attrkey = (self.NS_XMLNS, 'xmlns') | |||||
| DOCUMENT_NODE = node.DOCUMENT_NODE | |||||
| ELEMENT_NODE = node.ELEMENT_NODE | |||||
| while 1: | |||||
| if node.nodeType != ELEMENT_NODE: | |||||
| node = node.parentNode | |||||
| continue | |||||
| result = node._attrsNS.get(attrkey, None) | |||||
| if result is not None: | |||||
| return result.value | |||||
| if hasattr(node, '__imported__'): | |||||
| raise DOMException('Cannot determine default namespace.') | |||||
| node = node.parentNode | |||||
| if node.nodeType == DOCUMENT_NODE: | |||||
| raise DOMException('Cannot determine default namespace.') | |||||
| def findTargetNS(self, node): | |||||
| """Return the defined target namespace uri for the given node.""" | |||||
| attrget = self.getAttr | |||||
| attrkey = (self.NS_XMLNS, 'xmlns') | |||||
| DOCUMENT_NODE = node.DOCUMENT_NODE | |||||
| ELEMENT_NODE = node.ELEMENT_NODE | |||||
| while 1: | |||||
| if node.nodeType != ELEMENT_NODE: | |||||
| node = node.parentNode | |||||
| continue | |||||
| result = attrget(node, 'targetNamespace', default=None) | |||||
| if result is not None: | |||||
| return result | |||||
| node = node.parentNode | |||||
| if node.nodeType == DOCUMENT_NODE: | |||||
| raise DOMException('Cannot determine target namespace.') | |||||
| def getTypeRef(self, element): | |||||
| """Return (namespaceURI, name) for a type attribue of the given | |||||
| element, or None if the element does not have a type attribute.""" | |||||
| typeattr = self.getAttr(element, 'type', default=None) | |||||
| if typeattr is None: | |||||
| return None | |||||
| parts = typeattr.split(':', 1) | |||||
| if len(parts) == 2: | |||||
| nsuri = self.findNamespaceURI(parts[0], element) | |||||
| else: | |||||
| nsuri = self.findDefaultNS(element) | |||||
| return (nsuri, parts[1]) | |||||
| def importNode(self, document, node, deep=0): | |||||
| """Implements (well enough for our purposes) DOM node import.""" | |||||
| nodetype = node.nodeType | |||||
| if nodetype in (node.DOCUMENT_NODE, node.DOCUMENT_TYPE_NODE): | |||||
| raise DOMException('Illegal node type for importNode') | |||||
| if nodetype == node.ENTITY_REFERENCE_NODE: | |||||
| deep = 0 | |||||
| clone = node.cloneNode(deep) | |||||
| self._setOwnerDoc(document, clone) | |||||
| clone.__imported__ = 1 | |||||
| return clone | |||||
| def _setOwnerDoc(self, document, node): | |||||
| node.ownerDocument = document | |||||
| for child in node.childNodes: | |||||
| self._setOwnerDoc(document, child) | |||||
| def nsUriMatch(self, value, wanted, strict=0, tt=type(())): | |||||
| """Return a true value if two namespace uri values match.""" | |||||
| if value == wanted or (type(wanted) is tt) and value in wanted: | |||||
| return 1 | |||||
| if not strict: | |||||
| wanted = type(wanted) is tt and wanted or (wanted,) | |||||
| value = value[-1:] != '/' and value or value[:-1] | |||||
| for item in wanted: | |||||
| if item == value or item[:-1] == value: | |||||
| return 1 | |||||
| return 0 | |||||
| def createDocument(self, nsuri, qname, doctype=None): | |||||
| """Create a new writable DOM document object.""" | |||||
| impl = xml.dom.minidom.getDOMImplementation() | |||||
| return impl.createDocument(nsuri, qname, doctype) | |||||
| def loadDocument(self, data): | |||||
| """Load an xml file from a file-like object and return a DOM | |||||
| document instance.""" | |||||
| return xml.dom.minidom.parse(data) | |||||
| def loadFromURL(self, url): | |||||
| """Load an xml file from a URL and return a DOM document.""" | |||||
| file = urlopen(url) | |||||
| try: result = self.loadDocument(file) | |||||
| finally: file.close() | |||||
| return result | |||||
| class DOMException(Exception): | |||||
| pass | |||||
| DOM = DOM() | |||||
| class Collection(UserDict): | |||||
| """Helper class for maintaining ordered named collections.""" | |||||
| def __init__(self, parent): | |||||
| UserDict.__init__(self) | |||||
| self.parent = weakref.ref(parent) | |||||
| self.list = [] | |||||
| def __getitem__(self, key): | |||||
| if type(key) is type(1): | |||||
| return self.list[key] | |||||
| return self.data[key] | |||||
| def __setitem__(self, key, item): | |||||
| item.parent = weakref.ref(self) | |||||
| self.list.append(item) | |||||
| self.data[key] = item | |||||
| def keys(self): | |||||
| return map(lambda i: i.name, self.list) | |||||
| def items(self): | |||||
| return map(lambda i: (i.name, i), self.list) | |||||
| def values(self): | |||||
| return self.list | |||||
| # This is a runtime guerilla patch for pulldom (used by minidom) so | |||||
| # that xml namespace declaration attributes are not lost in parsing. | |||||
| # We need them to do correct QName linking for XML Schema and WSDL. | |||||
| # The patch has been submitted to SF for the next Python version. | |||||
| from xml.dom.pulldom import PullDOM, START_ELEMENT | |||||
| if 1: | |||||
| def startPrefixMapping(self, prefix, uri): | |||||
| if not hasattr(self, '_xmlns_attrs'): | |||||
| self._xmlns_attrs = [] | |||||
| self._xmlns_attrs.append((prefix or 'xmlns', uri)) | |||||
| self._ns_contexts.append(self._current_context.copy()) | |||||
| self._current_context[uri] = prefix or '' | |||||
| PullDOM.startPrefixMapping = startPrefixMapping | |||||
| def startElementNS(self, name, tagName , attrs): | |||||
| # Retrieve xml namespace declaration attributes. | |||||
| xmlns_uri = 'http://www.w3.org/2000/xmlns/' | |||||
| xmlns_attrs = getattr(self, '_xmlns_attrs', None) | |||||
| if xmlns_attrs is not None: | |||||
| for aname, value in xmlns_attrs: | |||||
| attrs._attrs[(xmlns_uri, aname)] = value | |||||
| self._xmlns_attrs = [] | |||||
| uri, localname = name | |||||
| if uri: | |||||
| # When using namespaces, the reader may or may not | |||||
| # provide us with the original name. If not, create | |||||
| # *a* valid tagName from the current context. | |||||
| if tagName is None: | |||||
| prefix = self._current_context[uri] | |||||
| if prefix: | |||||
| tagName = prefix + ":" + localname | |||||
| else: | |||||
| tagName = localname | |||||
| if self.document: | |||||
| node = self.document.createElementNS(uri, tagName) | |||||
| else: | |||||
| node = self.buildDocument(uri, tagName) | |||||
| else: | |||||
| # When the tagname is not prefixed, it just appears as | |||||
| # localname | |||||
| if self.document: | |||||
| node = self.document.createElement(localname) | |||||
| else: | |||||
| node = self.buildDocument(None, localname) | |||||
| for aname,value in attrs.items(): | |||||
| a_uri, a_localname = aname | |||||
| if a_uri == xmlns_uri: | |||||
| if a_localname == 'xmlns': | |||||
| qname = a_localname | |||||
| else: | |||||
| qname = 'xmlns:' + a_localname | |||||
| attr = self.document.createAttributeNS(a_uri, qname) | |||||
| node.setAttributeNodeNS(attr) | |||||
| elif a_uri: | |||||
| prefix = self._current_context[a_uri] | |||||
| if prefix: | |||||
| qname = prefix + ":" + a_localname | |||||
| else: | |||||
| qname = a_localname | |||||
| attr = self.document.createAttributeNS(a_uri, qname) | |||||
| node.setAttributeNodeNS(attr) | |||||
| else: | |||||
| attr = self.document.createAttribute(a_localname) | |||||
| node.setAttributeNode(attr) | |||||
| attr.value = value | |||||
| self.lastEvent[1] = [(START_ELEMENT, node), None] | |||||
| self.lastEvent = self.lastEvent[1] | |||||
| self.push(node) | |||||
| PullDOM.startElementNS = startElementNS | |||||
| # | |||||
| # This is a runtime guerilla patch for minidom so | |||||
| # that xmlns prefixed attributes dont raise AttributeErrors | |||||
| # during cloning. | |||||
| # | |||||
| # Namespace declarations can appear in any start-tag, must look for xmlns | |||||
| # prefixed attribute names during cloning. | |||||
| # | |||||
| # key (attr.namespaceURI, tag) | |||||
| # ('http://www.w3.org/2000/xmlns/', u'xsd') <xml.dom.minidom.Attr instance at 0x82227c4> | |||||
| # ('http://www.w3.org/2000/xmlns/', 'xmlns') <xml.dom.minidom.Attr instance at 0x8414b3c> | |||||
| # | |||||
| # xml.dom.minidom.Attr.nodeName = xmlns:xsd | |||||
| # xml.dom.minidom.Attr.value = = http://www.w3.org/2001/XMLSchema | |||||
| if 1: | |||||
| def _clone_node(node, deep, newOwnerDocument): | |||||
| """ | |||||
| Clone a node and give it the new owner document. | |||||
| Called by Node.cloneNode and Document.importNode | |||||
| """ | |||||
| if node.ownerDocument.isSameNode(newOwnerDocument): | |||||
| operation = xml.dom.UserDataHandler.NODE_CLONED | |||||
| else: | |||||
| operation = xml.dom.UserDataHandler.NODE_IMPORTED | |||||
| if node.nodeType == xml.dom.minidom.Node.ELEMENT_NODE: | |||||
| clone = newOwnerDocument.createElementNS(node.namespaceURI, | |||||
| node.nodeName) | |||||
| for attr in node.attributes.values(): | |||||
| clone.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value) | |||||
| prefix, tag = xml.dom.minidom._nssplit(attr.nodeName) | |||||
| if prefix == 'xmlns': | |||||
| a = clone.getAttributeNodeNS(attr.namespaceURI, tag) | |||||
| else: | |||||
| a = clone.getAttributeNodeNS(attr.namespaceURI, attr.nodeName) | |||||
| a.specified = attr.specified | |||||
| if deep: | |||||
| for child in node.childNodes: | |||||
| c = xml.dom.minidom._clone_node(child, deep, newOwnerDocument) | |||||
| clone.appendChild(c) | |||||
| elif node.nodeType == xml.dom.minidom.Node.DOCUMENT_FRAGMENT_NODE: | |||||
| clone = newOwnerDocument.createDocumentFragment() | |||||
| if deep: | |||||
| for child in node.childNodes: | |||||
| c = xml.dom.minidom._clone_node(child, deep, newOwnerDocument) | |||||
| clone.appendChild(c) | |||||
| elif node.nodeType == xml.dom.minidom.Node.TEXT_NODE: | |||||
| clone = newOwnerDocument.createTextNode(node.data) | |||||
| elif node.nodeType == xml.dom.minidom.Node.CDATA_SECTION_NODE: | |||||
| clone = newOwnerDocument.createCDATASection(node.data) | |||||
| elif node.nodeType == xml.dom.minidom.Node.PROCESSING_INSTRUCTION_NODE: | |||||
| clone = newOwnerDocument.createProcessingInstruction(node.target, | |||||
| node.data) | |||||
| elif node.nodeType == xml.dom.minidom.Node.COMMENT_NODE: | |||||
| clone = newOwnerDocument.createComment(node.data) | |||||
| elif node.nodeType == xml.dom.minidom.Node.ATTRIBUTE_NODE: | |||||
| clone = newOwnerDocument.createAttributeNS(node.namespaceURI, | |||||
| node.nodeName) | |||||
| clone.specified = True | |||||
| clone.value = node.value | |||||
| elif node.nodeType == xml.dom.minidom.Node.DOCUMENT_TYPE_NODE: | |||||
| assert node.ownerDocument is not newOwnerDocument | |||||
| operation = xml.dom.UserDataHandler.NODE_IMPORTED | |||||
| clone = newOwnerDocument.implementation.createDocumentType( | |||||
| node.name, node.publicId, node.systemId) | |||||
| clone.ownerDocument = newOwnerDocument | |||||
| if deep: | |||||
| clone.entities._seq = [] | |||||
| clone.notations._seq = [] | |||||
| for n in node.notations._seq: | |||||
| notation = Notation(n.nodeName, n.publicId, n.systemId) | |||||
| notation.ownerDocument = newOwnerDocument | |||||
| clone.notations._seq.append(notation) | |||||
| if hasattr(n, '_call_user_data_handler'): | |||||
| n._call_user_data_handler(operation, n, notation) | |||||
| for e in node.entities._seq: | |||||
| entity = Entity(e.nodeName, e.publicId, e.systemId, | |||||
| e.notationName) | |||||
| entity.actualEncoding = e.actualEncoding | |||||
| entity.encoding = e.encoding | |||||
| entity.version = e.version | |||||
| entity.ownerDocument = newOwnerDocument | |||||
| clone.entities._seq.append(entity) | |||||
| if hasattr(e, '_call_user_data_handler'): | |||||
| e._call_user_data_handler(operation, n, entity) | |||||
| else: | |||||
| # Note the cloning of Document and DocumentType nodes is | |||||
| # implemenetation specific. minidom handles those cases | |||||
| # directly in the cloneNode() methods. | |||||
| raise xml.dom.NotSupportedErr("Cannot clone node %s" % repr(node)) | |||||
| # Check for _call_user_data_handler() since this could conceivably | |||||
| # used with other DOM implementations (one of the FourThought | |||||
| # DOMs, perhaps?). | |||||
| if hasattr(node, '_call_user_data_handler'): | |||||
| node._call_user_data_handler(operation, node, clone) | |||||
| return clone | |||||
| xml.dom.minidom._clone_node = _clone_node | |||||
| @@ -0,0 +1,951 @@ | |||||
| # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved. | |||||
| # | |||||
| # This software is subject to the provisions of the Zope Public License, | |||||
| # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. | |||||
| # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED | |||||
| # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |||||
| # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS | |||||
| # FOR A PARTICULAR PURPOSE. | |||||
| from Utility import DOM, Collection | |||||
| from XMLSchema import XMLSchema | |||||
| from StringIO import StringIO | |||||
| import urllib | |||||
| class WSDLReader: | |||||
| """A WSDLReader creates WSDL instances from urls and xml data.""" | |||||
| # Custom subclasses of WSDLReader may wish to implement a caching | |||||
| # strategy or other optimizations. Because application needs vary | |||||
| # so widely, we don't try to provide any caching by default. | |||||
| def loadFromStream(self, file): | |||||
| """Return a WSDL instance loaded from a file object.""" | |||||
| document = DOM.loadDocument(file) | |||||
| wsdl = WSDL() | |||||
| wsdl.load(document) | |||||
| return wsdl | |||||
| def loadFromURL(self, url): | |||||
| """Return a WSDL instance loaded from the given url.""" | |||||
| document = DOM.loadFromURL(url) | |||||
| wsdl = WSDL() | |||||
| wsdl.location = url | |||||
| wsdl.load(document) | |||||
| return wsdl | |||||
| def loadFromString(self, data): | |||||
| """Return a WSDL instance loaded from an xml string.""" | |||||
| return self.loadFromStream(StringIO(data)) | |||||
| def loadFromFile(self, filename): | |||||
| """Return a WSDL instance loaded from the given file.""" | |||||
| file = open(filename, 'rb') | |||||
| try: | |||||
| wsdl = self.loadFromStream(file) | |||||
| finally: | |||||
| file.close() | |||||
| return wsdl | |||||
| class WSDL: | |||||
| """A WSDL object models a WSDL service description. WSDL objects | |||||
| may be created manually or loaded from an xml representation | |||||
| using a WSDLReader instance.""" | |||||
| def __init__(self, targetNamespace=None): | |||||
| self.targetNamespace = targetNamespace or 'urn:this-document.wsdl' | |||||
| self.documentation = '' | |||||
| self.location = None | |||||
| self.document = None | |||||
| self.name = None | |||||
| self.services = Collection(self) | |||||
| self.messages = Collection(self) | |||||
| self.portTypes = Collection(self) | |||||
| self.bindings = Collection(self) | |||||
| self.imports = Collection(self) | |||||
| self.types = Types(self) | |||||
| self.extensions = [] | |||||
| def __del__(self): | |||||
| if self.document is not None: | |||||
| self.document.unlink() | |||||
| self.document = None | |||||
| version = '1.1' | |||||
| def addService(self, name, documentation=''): | |||||
| if self.services.has_key(name): | |||||
| raise WSDLError( | |||||
| 'Duplicate service element: %s' % name | |||||
| ) | |||||
| item = Service(name, documentation) | |||||
| self.services[name] = item | |||||
| return item | |||||
| def addMessage(self, name, documentation=''): | |||||
| if self.messages.has_key(name): | |||||
| raise WSDLError( | |||||
| 'Duplicate message element: %s.' % name | |||||
| ) | |||||
| item = Message(name, documentation) | |||||
| self.messages[name] = item | |||||
| return item | |||||
| def addPortType(self, name, documentation=''): | |||||
| if self.portTypes.has_key(name): | |||||
| raise WSDLError( | |||||
| 'Duplicate portType element: name' | |||||
| ) | |||||
| item = PortType(name, documentation) | |||||
| self.portTypes[name] = item | |||||
| return item | |||||
| def addBinding(self, name, type, documentation=''): | |||||
| if self.bindings.has_key(name): | |||||
| raise WSDLError( | |||||
| 'Duplicate binding element: %s' % name | |||||
| ) | |||||
| item = Binding(name, type, documentation) | |||||
| self.bindings[name] = item | |||||
| return item | |||||
| def addImport(self, namespace, location): | |||||
| item = ImportElement(namespace, location) | |||||
| self.imports[namespace] = item | |||||
| return item | |||||
| def load(self, document): | |||||
| # We save a reference to the DOM document to ensure that elements | |||||
| # saved as "extensions" will continue to have a meaningful context | |||||
| # for things like namespace references. The lifetime of the DOM | |||||
| # document is bound to the lifetime of the WSDL instance. | |||||
| self.document = document | |||||
| definitions = DOM.getElement(document, 'definitions', None, None) | |||||
| if definitions is None: | |||||
| raise WSDLError( | |||||
| 'Missing <definitions> element.' | |||||
| ) | |||||
| self.version = DOM.WSDLUriToVersion(definitions.namespaceURI) | |||||
| NS_WSDL = DOM.GetWSDLUri(self.version) | |||||
| self.targetNamespace = DOM.getAttr(definitions, 'targetNamespace', | |||||
| None, None) | |||||
| self.name = DOM.getAttr(definitions, 'name', None, None) | |||||
| self.documentation = GetDocumentation(definitions) | |||||
| # Resolve (recursively) any import elements in the document. | |||||
| imported = {} | |||||
| while 1: | |||||
| imports = [] | |||||
| for element in DOM.getElements(definitions, 'import', NS_WSDL): | |||||
| location = DOM.getAttr(element, 'location') | |||||
| if not imported.has_key(location): | |||||
| imports.append(element) | |||||
| if not imports: | |||||
| break | |||||
| for element in imports: | |||||
| self._import(document, element) | |||||
| location = DOM.getAttr(element, 'location') | |||||
| imported[location] = 1 | |||||
| for element in DOM.getElements(definitions, None, None): | |||||
| localName = element.localName | |||||
| if not DOM.nsUriMatch(element.namespaceURI, NS_WSDL): | |||||
| if localName == 'schema': | |||||
| self.types.addSchema(XMLSchema(element)) | |||||
| else: | |||||
| self.extensions.append(element) | |||||
| continue | |||||
| elif localName == 'message': | |||||
| name = DOM.getAttr(element, 'name') | |||||
| docs = GetDocumentation(element) | |||||
| message = self.addMessage(name, docs) | |||||
| parts = DOM.getElements(element, 'part', NS_WSDL) | |||||
| message.load(parts) | |||||
| continue | |||||
| elif localName == 'portType': | |||||
| name = DOM.getAttr(element, 'name') | |||||
| docs = GetDocumentation(element) | |||||
| ptype = self.addPortType(name, docs) | |||||
| operations = DOM.getElements(element, 'operation', NS_WSDL) | |||||
| ptype.load(operations) | |||||
| continue | |||||
| elif localName == 'binding': | |||||
| name = DOM.getAttr(element, 'name') | |||||
| type = DOM.getAttr(element, 'type', default=None) | |||||
| if type is None: | |||||
| raise WSDLError( | |||||
| 'Missing type attribute for binding %s.' % name | |||||
| ) | |||||
| type = type.split(':', 1)[-1] | |||||
| docs = GetDocumentation(element) | |||||
| binding = self.addBinding(name, type, docs) | |||||
| operations = DOM.getElements(element, 'operation', NS_WSDL) | |||||
| binding.load(operations) | |||||
| binding.load_ex(GetExtensions(element)) | |||||
| continue | |||||
| elif localName == 'service': | |||||
| name = DOM.getAttr(element, 'name') | |||||
| docs = GetDocumentation(element) | |||||
| service = self.addService(name, docs) | |||||
| ports = DOM.getElements(element, 'port', NS_WSDL) | |||||
| service.load(ports) | |||||
| service.load_ex(GetExtensions(element)) | |||||
| continue | |||||
| elif localName == 'types': | |||||
| self.types.documentation = GetDocumentation(element) | |||||
| for item in DOM.getElements(element, None, None): | |||||
| if item.localName == 'schema': | |||||
| self.types.addSchema(XMLSchema(item)) | |||||
| else: | |||||
| self.types.addExtension(item) | |||||
| continue | |||||
| def _import(self, document, element): | |||||
| namespace = DOM.getAttr(element, 'namespace', default=None) | |||||
| location = DOM.getAttr(element, 'location', default=None) | |||||
| if namespace is None or location is None: | |||||
| raise WSDLError( | |||||
| 'Invalid import element (missing namespace or location).' | |||||
| ) | |||||
| # Sort-of support relative locations to simplify unit testing. The | |||||
| # WSDL specification actually doesn't allow relative URLs, so its | |||||
| # ok that this only works with urls relative to the initial document. | |||||
| location = urllib.basejoin(self.location, location) | |||||
| obimport = self.addImport(namespace, location) | |||||
| obimport._loaded = 1 | |||||
| importdoc = DOM.loadFromURL(location) | |||||
| try: | |||||
| if location.find('#') > -1: | |||||
| idref = location.split('#')[-1] | |||||
| imported = DOM.getElementById(importdoc, idref) | |||||
| else: | |||||
| imported = importdoc.documentElement | |||||
| if imported is None: | |||||
| raise WSDLError( | |||||
| 'Import target element not found for: %s' % location | |||||
| ) | |||||
| imported_tns = DOM.findTargetNS(imported) | |||||
| if imported_tns != namespace: | |||||
| return | |||||
| if imported.localName == 'definitions': | |||||
| imported_nodes = imported.childNodes | |||||
| else: | |||||
| imported_nodes = [imported] | |||||
| parent = element.parentNode | |||||
| for node in imported_nodes: | |||||
| if node.nodeType != node.ELEMENT_NODE: | |||||
| continue | |||||
| child = DOM.importNode(document, node, 1) | |||||
| parent.appendChild(child) | |||||
| child.setAttribute('targetNamespace', namespace) | |||||
| attrsNS = imported._attrsNS | |||||
| for attrkey in attrsNS.keys(): | |||||
| if attrkey[0] == DOM.NS_XMLNS: | |||||
| attr = attrsNS[attrkey].cloneNode(1) | |||||
| child.setAttributeNode(attr) | |||||
| finally: | |||||
| importdoc.unlink() | |||||
| class Element: | |||||
| """A class that provides common functions for WSDL element classes.""" | |||||
| def __init__(self, name=None, documentation=''): | |||||
| self.name = name | |||||
| self.documentation = documentation | |||||
| self.extensions = [] | |||||
| def addExtension(self, item): | |||||
| self.extensions.append(item) | |||||
| class ImportElement(Element): | |||||
| def __init__(self, namespace, location): | |||||
| self.namespace = namespace | |||||
| self.location = location | |||||
| _loaded = None | |||||
| class Types(Collection): | |||||
| def __init__(self, parent): | |||||
| Collection.__init__(self, parent) | |||||
| self.documentation = '' | |||||
| self.extensions = [] | |||||
| def addSchema(self, schema): | |||||
| name = schema.targetNamespace | |||||
| self[name] = schema | |||||
| return schema | |||||
| def keys(self): | |||||
| return map(lambda i: i.targetNamespace, self.list) | |||||
| def items(self): | |||||
| return map(lambda i: i.targetNamespace, self.list) | |||||
| def addExtension(self, item): | |||||
| self.extensions.append(item) | |||||
| class Message(Element): | |||||
| def __init__(self, name, documentation=''): | |||||
| Element.__init__(self, name, documentation) | |||||
| self.parts = Collection(self) | |||||
| def addPart(self, name, type=None, element=None): | |||||
| if self.parts.has_key(name): | |||||
| raise WSDLError( | |||||
| 'Duplicate message part element: %s' % name | |||||
| ) | |||||
| if type is None and element is None: | |||||
| raise WSDLError( | |||||
| 'Missing type or element attribute for part: %s' % name | |||||
| ) | |||||
| item = MessagePart(name) | |||||
| item.element = element | |||||
| item.type = type | |||||
| self.parts[name] = item | |||||
| return item | |||||
| def load(self, elements): | |||||
| for element in elements: | |||||
| name = DOM.getAttr(element, 'name') | |||||
| part = MessagePart(name) | |||||
| self.parts[name] = part | |||||
| elemref = DOM.getAttr(element, 'element', default=None) | |||||
| typeref = DOM.getAttr(element, 'type', default=None) | |||||
| if typeref is None and elemref is None: | |||||
| raise WSDLError( | |||||
| 'No type or element attribute for part: %s' % name | |||||
| ) | |||||
| if typeref is not None: | |||||
| part.type = ParseTypeRef(typeref, element) | |||||
| if elemref is not None: | |||||
| part.element = ParseTypeRef(elemref, element) | |||||
| class MessagePart(Element): | |||||
| def __init__(self, name): | |||||
| Element.__init__(self, name, '') | |||||
| self.element = None | |||||
| self.type = None | |||||
| class PortType(Element): | |||||
| def __init__(self, name, documentation=''): | |||||
| Element.__init__(self, name, documentation) | |||||
| self.operations = Collection(self) | |||||
| def getWSDL(self): | |||||
| return self.parent().parent() | |||||
| def addOperation(self, name, documentation='', parameterOrder=None): | |||||
| item = Operation(name, documentation, parameterOrder) | |||||
| self.operations[name] = item | |||||
| return item | |||||
| def load(self, elements): | |||||
| for element in elements: | |||||
| name = DOM.getAttr(element, 'name') | |||||
| docs = GetDocumentation(element) | |||||
| param_order = DOM.getAttr(element, 'parameterOrder', default=None) | |||||
| if param_order is not None: | |||||
| param_order = param_order.split(' ') | |||||
| operation = self.addOperation(name, docs, param_order) | |||||
| item = DOM.getElement(element, 'input', None, None) | |||||
| if item is not None: | |||||
| name = DOM.getAttr(item, 'name') | |||||
| docs = GetDocumentation(item) | |||||
| msgref = DOM.getAttr(item, 'message') | |||||
| message = msgref.split(':', 1)[-1] | |||||
| operation.setInput(message, name, docs) | |||||
| item = DOM.getElement(element, 'output', None, None) | |||||
| if item is not None: | |||||
| name = DOM.getAttr(item, 'name') | |||||
| docs = GetDocumentation(item) | |||||
| msgref = DOM.getAttr(item, 'message') | |||||
| message = msgref.split(':', 1)[-1] | |||||
| operation.setOutput(message, name, docs) | |||||
| for item in DOM.getElements(element, 'fault', None): | |||||
| name = DOM.getAttr(item, 'name') | |||||
| docs = GetDocumentation(item) | |||||
| msgref = DOM.getAttr(item, 'message') | |||||
| message = msgref.split(':', 1)[-1] | |||||
| operation.addFault(message, name, docs) | |||||
| class Operation(Element): | |||||
| def __init__(self, name, documentation='', parameterOrder=None): | |||||
| Element.__init__(self, name, documentation) | |||||
| self.parameterOrder = parameterOrder | |||||
| self.faults = Collection(self) | |||||
| self.input = None | |||||
| self.output = None | |||||
| def getPortType(self): | |||||
| return self.parent().parent() | |||||
| def getInputMessage(self): | |||||
| if self.input is None: | |||||
| return None | |||||
| wsdl = self.getPortType().getWSDL() | |||||
| return wsdl.messages[self.input.message] | |||||
| def getOutputMessage(self): | |||||
| if self.output is None: | |||||
| return None | |||||
| wsdl = self.getPortType().getWSDL() | |||||
| return wsdl.messages[self.output.message] | |||||
| def getFaultMessage(self, name): | |||||
| wsdl = self.getPortType().getWSDL() | |||||
| return wsdl.messages[self.faults[name].message] | |||||
| def addFault(self, name, message, documentation=''): | |||||
| if self.faults.has_key(name): | |||||
| raise WSDLError( | |||||
| 'Duplicate fault element: %s' % name | |||||
| ) | |||||
| item = MessageRole('fault', message, name, documentation) | |||||
| self.faults[name] = item | |||||
| return item | |||||
| def setInput(self, message, name='', documentation=''): | |||||
| self.input = MessageRole('input', message, name, documentation) | |||||
| return self.input | |||||
| def setOutput(self, message, name='', documentation=''): | |||||
| self.output = MessageRole('output', message, name, documentation) | |||||
| return self.output | |||||
| class MessageRole(Element): | |||||
| def __init__(self, type, message, name='', documentation=''): | |||||
| Element.__init__(self, name, documentation) | |||||
| self.message = message | |||||
| self.type = type | |||||
| class Binding(Element): | |||||
| def __init__(self, name, type, documentation=''): | |||||
| Element.__init__(self, name, documentation) | |||||
| self.operations = Collection(self) | |||||
| self.type = type | |||||
| def getWSDL(self): | |||||
| """Return the WSDL object that contains this binding.""" | |||||
| return self.parent().parent() | |||||
| def getPortType(self): | |||||
| """Return the PortType object associated with this binding.""" | |||||
| return self.getWSDL().portTypes[self.type] | |||||
| def findBinding(self, kind): | |||||
| for item in self.extensions: | |||||
| if isinstance(item, kind): | |||||
| return item | |||||
| return None | |||||
| def findBindings(self, kind): | |||||
| return [ item for item in self.extensions if isinstance(item, kind) ] | |||||
| def addOperationBinding(self, name, documentation=''): | |||||
| item = OperationBinding(name, documentation) | |||||
| self.operations[name] = item | |||||
| return item | |||||
| def load(self, elements): | |||||
| for element in elements: | |||||
| name = DOM.getAttr(element, 'name') | |||||
| docs = GetDocumentation(element) | |||||
| opbinding = self.addOperationBinding(name, docs) | |||||
| opbinding.load_ex(GetExtensions(element)) | |||||
| item = DOM.getElement(element, 'input', None, None) | |||||
| if item is not None: | |||||
| mbinding = MessageRoleBinding('input') | |||||
| mbinding.documentation = GetDocumentation(item) | |||||
| opbinding.input = mbinding | |||||
| mbinding.load_ex(GetExtensions(item)) | |||||
| item = DOM.getElement(element, 'output', None, None) | |||||
| if item is not None: | |||||
| mbinding = MessageRoleBinding('output') | |||||
| mbinding.documentation = GetDocumentation(item) | |||||
| opbinding.output = mbinding | |||||
| mbinding.load_ex(GetExtensions(item)) | |||||
| for item in DOM.getElements(element, 'fault', None): | |||||
| name = DOM.getAttr(item, 'name') | |||||
| mbinding = MessageRoleBinding('fault', name) | |||||
| mbinding.documentation = GetDocumentation(item) | |||||
| opbinding.faults[name] = mbinding | |||||
| mbinding.load_ex(GetExtensions(item)) | |||||
| def load_ex(self, elements): | |||||
| for e in elements: | |||||
| ns, name = e.namespaceURI, e.localName | |||||
| if ns in DOM.NS_SOAP_BINDING_ALL and name == 'binding': | |||||
| transport = DOM.getAttr(e, 'transport', default=None) | |||||
| style = DOM.getAttr(e, 'style', default='document') | |||||
| ob = SoapBinding(transport, style) | |||||
| self.addExtension(ob) | |||||
| continue | |||||
| elif ns in DOM.NS_HTTP_BINDING_ALL and name == 'binding': | |||||
| verb = DOM.getAttr(e, 'verb') | |||||
| ob = HttpBinding(verb) | |||||
| self.addExtension(ob) | |||||
| continue | |||||
| else: | |||||
| self.addExtension(e) | |||||
| class OperationBinding(Element): | |||||
| def __init__(self, name, documentation=''): | |||||
| Element.__init__(self, name, documentation) | |||||
| self.input = None | |||||
| self.output = None | |||||
| self.faults = Collection(self) | |||||
| def getBinding(self): | |||||
| """Return the parent Binding object of the operation binding.""" | |||||
| return self.parent().parent() | |||||
| def getOperation(self): | |||||
| """Return the abstract Operation associated with this binding.""" | |||||
| return self.getBinding().getPortType().operations[self.name] | |||||
| def findBinding(self, kind): | |||||
| for item in self.extensions: | |||||
| if isinstance(item, kind): | |||||
| return item | |||||
| return None | |||||
| def findBindings(self, kind): | |||||
| return [ item for item in self.extensions if isinstance(item, kind) ] | |||||
| def addInputBinding(self, binding): | |||||
| if self.input is None: | |||||
| self.input = MessageRoleBinding('input') | |||||
| self.input.addExtension(binding) | |||||
| return binding | |||||
| def addOutputBinding(self, binding): | |||||
| if self.output is None: | |||||
| self.output = MessageRoleBinding('output') | |||||
| self.output.addExtension(binding) | |||||
| return binding | |||||
| def addFaultBinding(self, name, binding): | |||||
| fault = self.get(name, None) | |||||
| if fault is None: | |||||
| fault = MessageRoleBinding('fault', name) | |||||
| fault.addExtension(binding) | |||||
| return binding | |||||
| def load_ex(self, elements): | |||||
| for e in elements: | |||||
| ns, name = e.namespaceURI, e.localName | |||||
| if ns in DOM.NS_SOAP_BINDING_ALL and name == 'operation': | |||||
| soapaction = DOM.getAttr(e, 'soapAction', default=None) | |||||
| style = DOM.getAttr(e, 'style', default=None) | |||||
| ob = SoapOperationBinding(soapaction, style) | |||||
| self.addExtension(ob) | |||||
| continue | |||||
| elif ns in DOM.NS_HTTP_BINDING_ALL and name == 'operation': | |||||
| location = DOM.getAttr(e, 'location') | |||||
| ob = HttpOperationBinding(location) | |||||
| self.addExtension(ob) | |||||
| continue | |||||
| else: | |||||
| self.addExtension(e) | |||||
| class MessageRoleBinding(Element): | |||||
| def __init__(self, type, name='', documentation=''): | |||||
| Element.__init__(self, name, documentation) | |||||
| self.type = type | |||||
| def findBinding(self, kind): | |||||
| for item in self.extensions: | |||||
| if isinstance(item, kind): | |||||
| return item | |||||
| return None | |||||
| def findBindings(self, kind): | |||||
| return [ item for item in self.extensions if isinstance(item, kind) ] | |||||
| def load_ex(self, elements): | |||||
| for e in elements: | |||||
| ns, name = e.namespaceURI, e.localName | |||||
| if ns in DOM.NS_SOAP_BINDING_ALL and name == 'body': | |||||
| encstyle = DOM.getAttr(e, 'encodingStyle', default=None) | |||||
| namespace = DOM.getAttr(e, 'namespace', default=None) | |||||
| parts = DOM.getAttr(e, 'parts', default=None) | |||||
| use = DOM.getAttr(e, 'use', default=None) | |||||
| if use is None: | |||||
| raise WSDLError( | |||||
| 'Invalid soap:body binding element.' | |||||
| ) | |||||
| ob = SoapBodyBinding(use, namespace, encstyle, parts) | |||||
| self.addExtension(ob) | |||||
| continue | |||||
| elif ns in DOM.NS_SOAP_BINDING_ALL and name == 'fault': | |||||
| encstyle = DOM.getAttr(e, 'encodingStyle', default=None) | |||||
| namespace = DOM.getAttr(e, 'namespace', default=None) | |||||
| name = DOM.getAttr(e, 'name', default=None) | |||||
| use = DOM.getAttr(e, 'use', default=None) | |||||
| if use is None or name is None: | |||||
| raise WSDLError( | |||||
| 'Invalid soap:fault binding element.' | |||||
| ) | |||||
| ob = SoapFaultBinding(name, use, namespace, encstyle) | |||||
| self.addExtension(ob) | |||||
| continue | |||||
| elif ns in DOM.NS_SOAP_BINDING_ALL and name in ( | |||||
| 'header', 'headerfault' | |||||
| ): | |||||
| encstyle = DOM.getAttr(e, 'encodingStyle', default=None) | |||||
| namespace = DOM.getAttr(e, 'namespace', default=None) | |||||
| message = DOM.getAttr(e, 'message') | |||||
| part = DOM.getAttr(e, 'part') | |||||
| use = DOM.getAttr(e, 'use') | |||||
| if name == 'header': | |||||
| _class = SoapHeaderBinding | |||||
| else: | |||||
| _class = SoapHeaderFaultBinding | |||||
| ob = _class(message, part, use, namespace, encstyle) | |||||
| self.addExtension(ob) | |||||
| continue | |||||
| elif ns in DOM.NS_HTTP_BINDING_ALL and name == 'urlReplacement': | |||||
| ob = HttpUrlReplacementBinding() | |||||
| self.addExtension(ob) | |||||
| continue | |||||
| elif ns in DOM.NS_HTTP_BINDING_ALL and name == 'urlEncoded': | |||||
| ob = HttpUrlEncodedBinding() | |||||
| self.addExtension(ob) | |||||
| continue | |||||
| elif ns in DOM.NS_MIME_BINDING_ALL and name == 'multipartRelated': | |||||
| ob = MimeMultipartRelatedBinding() | |||||
| self.addExtension(ob) | |||||
| ob.load_ex(GetExtensions(e)) | |||||
| continue | |||||
| elif ns in DOM.NS_MIME_BINDING_ALL and name == 'content': | |||||
| part = DOM.getAttr(e, 'part', default=None) | |||||
| type = DOM.getAttr(e, 'type', default=None) | |||||
| ob = MimeContentBinding(part, type) | |||||
| self.addExtension(ob) | |||||
| continue | |||||
| elif ns in DOM.NS_MIME_BINDING_ALL and name == 'mimeXml': | |||||
| part = DOM.getAttr(e, 'part', default=None) | |||||
| ob = MimeXmlBinding(part) | |||||
| self.addExtension(ob) | |||||
| continue | |||||
| else: | |||||
| self.addExtension(e) | |||||
| class Service(Element): | |||||
| def __init__(self, name, documentation=''): | |||||
| Element.__init__(self, name, documentation) | |||||
| self.ports = Collection(self) | |||||
| def getWSDL(self): | |||||
| return self.parent().parent() | |||||
| def addPort(self, name, binding, documentation=''): | |||||
| item = Port(name, binding, documentation) | |||||
| self.ports[name] = item | |||||
| return item | |||||
| def load(self, elements): | |||||
| for element in elements: | |||||
| name = DOM.getAttr(element, 'name', default=None) | |||||
| docs = GetDocumentation(element) | |||||
| binding = DOM.getAttr(element, 'binding', default=None) | |||||
| if name is None or binding is None: | |||||
| raise WSDLError( | |||||
| 'Invalid port element.' | |||||
| ) | |||||
| binding = binding.split(':', 1)[-1] | |||||
| port = self.addPort(name, binding, docs) | |||||
| port.load_ex(GetExtensions(element)) | |||||
| def load_ex(self, elements): | |||||
| for e in elements: | |||||
| self.addExtension(e) | |||||
| class Port(Element): | |||||
| def __init__(self, name, binding, documentation=''): | |||||
| Element.__init__(self, name, documentation) | |||||
| self.binding = binding | |||||
| def getService(self): | |||||
| """Return the Service object associated with this port.""" | |||||
| return self.parent().parent() | |||||
| def getBinding(self): | |||||
| """Return the Binding object that is referenced by this port.""" | |||||
| wsdl = self.getService().getWSDL() | |||||
| return wsdl.bindings[self.binding] | |||||
| def getPortType(self): | |||||
| """Return the PortType object that is referenced by this port.""" | |||||
| wsdl = self.getService().getWSDL() | |||||
| binding = wsdl.bindings[self.binding] | |||||
| return wsdl.portTypes[binding.type] | |||||
| def getAddressBinding(self): | |||||
| """A convenience method to obtain the extension element used | |||||
| as the address binding for the port, or None if undefined.""" | |||||
| for item in self.extensions: | |||||
| if isinstance(item, SoapAddressBinding) or \ | |||||
| isinstance(item, HttpAddressBinding): | |||||
| return item | |||||
| raise WSDLError( | |||||
| 'No address binding found in port.' | |||||
| ) | |||||
| def load_ex(self, elements): | |||||
| for e in elements: | |||||
| ns, name = e.namespaceURI, e.localName | |||||
| if ns in DOM.NS_SOAP_BINDING_ALL and name == 'address': | |||||
| location = DOM.getAttr(e, 'location', default=None) | |||||
| ob = SoapAddressBinding(location) | |||||
| self.addExtension(ob) | |||||
| continue | |||||
| elif ns in DOM.NS_HTTP_BINDING_ALL and name == 'address': | |||||
| location = DOM.getAttr(e, 'location', default=None) | |||||
| ob = HttpAddressBinding(location) | |||||
| self.addExtension(ob) | |||||
| continue | |||||
| else: | |||||
| self.addExtension(e) | |||||
| class SoapBinding: | |||||
| def __init__(self, transport, style='rpc'): | |||||
| self.transport = transport | |||||
| self.style = style | |||||
| class SoapAddressBinding: | |||||
| def __init__(self, location): | |||||
| self.location = location | |||||
| class SoapOperationBinding: | |||||
| def __init__(self, soapAction=None, style=None): | |||||
| self.soapAction = soapAction | |||||
| self.style = style | |||||
| class SoapBodyBinding: | |||||
| def __init__(self, use, namespace=None, encodingStyle=None, parts=None): | |||||
| if not use in ('literal', 'encoded'): | |||||
| raise WSDLError( | |||||
| 'Invalid use attribute value: %s' % use | |||||
| ) | |||||
| self.encodingStyle = encodingStyle | |||||
| self.namespace = namespace | |||||
| if type(parts) in (type(''), type(u'')): | |||||
| raise WSDLError( | |||||
| 'The parts argument must be a sequence.' | |||||
| ) | |||||
| self.parts = parts | |||||
| self.use = use | |||||
| class SoapFaultBinding: | |||||
| def __init__(self, name, use, namespace=None, encodingStyle=None): | |||||
| if not use in ('literal', 'encoded'): | |||||
| raise WSDLError( | |||||
| 'Invalid use attribute value: %s' % use | |||||
| ) | |||||
| self.encodingStyle = encodingStyle | |||||
| self.namespace = namespace | |||||
| self.name = name | |||||
| self.use = use | |||||
| class SoapHeaderBinding: | |||||
| def __init__(self, message, part, use, namespace=None, encodingStyle=None): | |||||
| if not use in ('literal', 'encoded'): | |||||
| raise WSDLError( | |||||
| 'Invalid use attribute value: %s' % use | |||||
| ) | |||||
| self.encodingStyle = encodingStyle | |||||
| self.namespace = namespace | |||||
| self.message = message | |||||
| self.part = part | |||||
| self.use = use | |||||
| tagname = 'header' | |||||
| class SoapHeaderFaultBinding(SoapHeaderBinding): | |||||
| tagname = 'headerfault' | |||||
| class HttpBinding: | |||||
| def __init__(self, verb): | |||||
| self.verb = verb | |||||
| class HttpAddressBinding: | |||||
| def __init__(self, location): | |||||
| self.location = location | |||||
| class HttpOperationBinding: | |||||
| def __init__(self, location): | |||||
| self.location = location | |||||
| class HttpUrlReplacementBinding: | |||||
| pass | |||||
| class HttpUrlEncodedBinding: | |||||
| pass | |||||
| class MimeContentBinding: | |||||
| def __init__(self, part=None, type=None): | |||||
| self.part = part | |||||
| self.type = type | |||||
| class MimeXmlBinding: | |||||
| def __init__(self, part=None): | |||||
| self.part = part | |||||
| class MimeMultipartRelatedBinding: | |||||
| def __init__(self): | |||||
| self.parts = [] | |||||
| def load_ex(self, elements): | |||||
| for e in elements: | |||||
| ns, name = e.namespaceURI, e.localName | |||||
| if ns in DOM.NS_MIME_BINDING_ALL and name == 'part': | |||||
| self.parts.append(MimePartBinding()) | |||||
| continue | |||||
| class MimePartBinding: | |||||
| def __init__(self): | |||||
| self.items = [] | |||||
| def load_ex(self, elements): | |||||
| for e in elements: | |||||
| ns, name = e.namespaceURI, e.localName | |||||
| if ns in DOM.NS_MIME_BINDING_ALL and name == 'content': | |||||
| part = DOM.getAttr(e, 'part', default=None) | |||||
| type = DOM.getAttr(e, 'type', default=None) | |||||
| ob = MimeContentBinding(part, type) | |||||
| self.items.append(ob) | |||||
| continue | |||||
| elif ns in DOM.NS_MIME_BINDING_ALL and name == 'mimeXml': | |||||
| part = DOM.getAttr(e, 'part', default=None) | |||||
| ob = MimeXmlBinding(part) | |||||
| self.items.append(ob) | |||||
| continue | |||||
| elif ns in DOM.NS_SOAP_BINDING_ALL and name == 'body': | |||||
| encstyle = DOM.getAttr(e, 'encodingStyle', default=None) | |||||
| namespace = DOM.getAttr(e, 'namespace', default=None) | |||||
| parts = DOM.getAttr(e, 'parts', default=None) | |||||
| use = DOM.getAttr(e, 'use', default=None) | |||||
| if use is None: | |||||
| raise WSDLError( | |||||
| 'Invalid soap:body binding element.' | |||||
| ) | |||||
| ob = SoapBodyBinding(use, namespace, encstyle, parts) | |||||
| self.items.append(ob) | |||||
| continue | |||||
| class WSDLError(Exception): | |||||
| pass | |||||
| def DeclareNSPrefix(writer, prefix, nsuri): | |||||
| if writer.hasNSPrefix(nsuri): | |||||
| return | |||||
| writer.declareNSPrefix(prefix, nsuri) | |||||
| def ParseTypeRef(value, element): | |||||
| parts = value.split(':', 1) | |||||
| if len(parts) == 1: | |||||
| return (DOM.findTargetNS(element), value) | |||||
| nsuri = DOM.findNamespaceURI(parts[0], element) | |||||
| return (nsuri, parts[1]) | |||||
| def ParseQName(value, element): | |||||
| nameref = value.split(':', 1) | |||||
| if len(nameref) == 2: | |||||
| nsuri = DOM.findNamespaceURI(nameref[0], element) | |||||
| name = nameref[-1] | |||||
| else: | |||||
| nsuri = DOM.findTargetNS(element) | |||||
| name = nameref[-1] | |||||
| return nsuri, name | |||||
| def GetDocumentation(element): | |||||
| docnode = DOM.getElement(element, 'documentation', None, None) | |||||
| if docnode is not None: | |||||
| return DOM.getElementText(docnode) | |||||
| return '' | |||||
| def GetExtensions(element): | |||||
| return [ item for item in DOM.getElements(element, None, None) | |||||
| if item.namespaceURI != DOM.NS_WSDL ] | |||||
| def FindExtensions(object, kind, t_type=type(())): | |||||
| if isinstance(kind, t_type): | |||||
| result = [] | |||||
| namespaceURI, name = kind | |||||
| return [ item for item in object.extensions | |||||
| if hasattr(item, 'nodeType') \ | |||||
| and DOM.nsUriMatch(namespaceURI, item.namespaceURI) \ | |||||
| and item.name == name ] | |||||
| return [ item for item in object.extensions if isinstance(item, kind) ] | |||||
| def FindExtension(object, kind, t_type=type(())): | |||||
| if isinstance(kind, t_type): | |||||
| namespaceURI, name = kind | |||||
| for item in object.extensions: | |||||
| if hasattr(item, 'nodeType') \ | |||||
| and DOM.nsUriMatch(namespaceURI, item.namespaceURI) \ | |||||
| and item.name == name: | |||||
| return item | |||||
| else: | |||||
| for item in object.extensions: | |||||
| if isinstance(item, kind): | |||||
| return item | |||||
| return None | |||||
| @@ -0,0 +1,331 @@ | |||||
| # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved. | |||||
| # | |||||
| # This software is subject to the provisions of the Zope Public License, | |||||
| # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. | |||||
| # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED | |||||
| # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |||||
| # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS | |||||
| # FOR A PARTICULAR PURPOSE. | |||||
| import string, types, base64, re | |||||
| from Utility import DOM, Collection | |||||
| from StringIO import StringIO | |||||
| class SchemaReader: | |||||
| """A SchemaReader creates XMLSchema objects from urls and xml data.""" | |||||
| def loadFromStream(self, file): | |||||
| """Return an XMLSchema instance loaded from a file object.""" | |||||
| document = DOM.loadDocument(file) | |||||
| schema = XMLSchema() | |||||
| schema.load(document) | |||||
| return schema | |||||
| def loadFromString(self, data): | |||||
| """Return an XMLSchema instance loaded from an xml string.""" | |||||
| return self.loadFromStream(StringIO(data)) | |||||
| def loadFromURL(self, url): | |||||
| """Return an XMLSchema instance loaded from the given url.""" | |||||
| document = DOM.loadFromURL(url) | |||||
| schema = XMLSchema() | |||||
| schema.location = url | |||||
| schema.load(document) | |||||
| return schema | |||||
| def loadFromFile(self, filename): | |||||
| """Return an XMLSchema instance loaded from the given file.""" | |||||
| file = open(filename, 'rb') | |||||
| try: schema = self.loadFromStream(file) | |||||
| finally: file.close() | |||||
| return schema | |||||
| class XMLSchema: | |||||
| # This is temporary, for the benefit of WSDL until the real thing works. | |||||
| def __init__(self, element): | |||||
| self.targetNamespace = DOM.getAttr(element, 'targetNamespace') | |||||
| self.element = element | |||||
| class realXMLSchema: | |||||
| """A schema is a collection of schema components derived from one | |||||
| or more schema documents, that is, one or more <schema> element | |||||
| information items. It represents the abstract notion of a schema | |||||
| rather than a single schema document (or other representation).""" | |||||
| def __init__(self): | |||||
| self.simpleTypes = Collection(self) | |||||
| self.complexTypes = Collection(self) | |||||
| self.attributes = Collection(self) | |||||
| self.elements = Collection(self) | |||||
| self.attrGroups = Collection(self) | |||||
| self.idConstraints=None | |||||
| self.modelGroups = None | |||||
| self.notations = None | |||||
| self.extensions = [] | |||||
| targetNamespace = None | |||||
| attributeFormDefault = 'unqualified' | |||||
| elementFormDefault = 'unqualified' | |||||
| blockDefault = None | |||||
| finalDefault = None | |||||
| location = None | |||||
| version = None | |||||
| id = None | |||||
| def load(self, document): | |||||
| if document.nodeType == document.DOCUMENT_NODE: | |||||
| schema = DOM.getElement(document, 'schema', None, None) | |||||
| else: | |||||
| schema = document | |||||
| if schema is None: | |||||
| raise SchemaError('Missing <schema> element.') | |||||
| self.namespace = namespace = schema.namespaceURI | |||||
| if not namespace in DOM.NS_XSD_ALL: | |||||
| raise SchemaError( | |||||
| 'Unknown XML schema namespace: %s.' % self.namespace | |||||
| ) | |||||
| for attrname in ( | |||||
| 'targetNamespace', 'attributeFormDefault', 'elementFormDefault', | |||||
| 'blockDefault', 'finalDefault', 'version', 'id' | |||||
| ): | |||||
| value = DOM.getAttr(schema, attrname, None, None) | |||||
| if attr is not None: | |||||
| setattr(self, attrname, value) | |||||
| # Resolve imports and includes here? | |||||
| ## imported = {} | |||||
| ## while 1: | |||||
| ## imports = [] | |||||
| ## for element in DOM.getElements(definitions, 'import', NS_WSDL): | |||||
| ## location = DOM.getAttr(element, 'location') | |||||
| ## if not imported.has_key(location): | |||||
| ## imports.append(element) | |||||
| ## if not imports: | |||||
| ## break | |||||
| ## for element in imports: | |||||
| ## self._import(document, element) | |||||
| ## imported[location] = 1 | |||||
| for element in DOM.getElements(schema, None, None): | |||||
| localName = element.localName | |||||
| if not DOM.nsUriMatch(element.namespaceURI, namespace): | |||||
| self.extensions.append(element) | |||||
| continue | |||||
| elif localName == 'message': | |||||
| name = DOM.getAttr(element, 'name') | |||||
| docs = GetDocumentation(element) | |||||
| message = self.addMessage(name, docs) | |||||
| parts = DOM.getElements(element, 'part', NS_WSDL) | |||||
| message.load(parts) | |||||
| continue | |||||
| def _import(self, document, element): | |||||
| namespace = DOM.getAttr(element, 'namespace', default=None) | |||||
| location = DOM.getAttr(element, 'location', default=None) | |||||
| if namespace is None or location is None: | |||||
| raise WSDLError( | |||||
| 'Invalid import element (missing namespace or location).' | |||||
| ) | |||||
| # Sort-of support relative locations to simplify unit testing. The | |||||
| # WSDL specification actually doesn't allow relative URLs, so its | |||||
| # ok that this only works with urls relative to the initial document. | |||||
| location = urllib.basejoin(self.location, location) | |||||
| obimport = self.addImport(namespace, location) | |||||
| obimport._loaded = 1 | |||||
| importdoc = DOM.loadFromURL(location) | |||||
| try: | |||||
| if location.find('#') > -1: | |||||
| idref = location.split('#')[-1] | |||||
| imported = DOM.getElementById(importdoc, idref) | |||||
| else: | |||||
| imported = importdoc.documentElement | |||||
| if imported is None: | |||||
| raise WSDLError( | |||||
| 'Import target element not found for: %s' % location | |||||
| ) | |||||
| imported_tns = DOM.getAttr(imported, 'targetNamespace') | |||||
| importer_tns = namespace | |||||
| if imported_tns != importer_tns: | |||||
| return | |||||
| if imported.localName == 'definitions': | |||||
| imported_nodes = imported.childNodes | |||||
| else: | |||||
| imported_nodes = [imported] | |||||
| parent = element.parentNode | |||||
| for node in imported_nodes: | |||||
| if node.nodeType != node.ELEMENT_NODE: | |||||
| continue | |||||
| child = DOM.importNode(document, node, 1) | |||||
| parent.appendChild(child) | |||||
| child.setAttribute('targetNamespace', importer_tns) | |||||
| attrsNS = imported._attrsNS | |||||
| for attrkey in attrsNS.keys(): | |||||
| if attrkey[0] == DOM.NS_XMLNS: | |||||
| attr = attrsNS[attrkey].cloneNode(1) | |||||
| child.setAttributeNode(attr) | |||||
| finally: | |||||
| importdoc.unlink() | |||||
| class Element: | |||||
| """Common base class for element representation classes.""" | |||||
| def __init__(self, name=None, documentation=''): | |||||
| self.name = name | |||||
| self.documentation = documentation | |||||
| self.extensions = [] | |||||
| def addExtension(self, item): | |||||
| self.extensions.append(item) | |||||
| class SimpleTypeDefinition: | |||||
| """Represents an xml schema simple type definition.""" | |||||
| class ComplexTypeDefinition: | |||||
| """Represents an xml schema complex type definition.""" | |||||
| class AttributeDeclaration: | |||||
| """Represents an xml schema attribute declaration.""" | |||||
| class ElementDeclaration: | |||||
| """Represents an xml schema element declaration.""" | |||||
| def __init__(self, name, type=None, targetNamespace=None): | |||||
| self.name = name | |||||
| targetNamespace = None | |||||
| annotation = None | |||||
| nillable = 0 | |||||
| abstract = 0 | |||||
| default = None | |||||
| fixed = None | |||||
| scope = 'global' | |||||
| type = None | |||||
| form = 0 | |||||
| # Things we will not worry about for now. | |||||
| id_constraint_defs = None | |||||
| sub_group_exclude = None | |||||
| sub_group_affils = None | |||||
| disallowed_subs = None | |||||
| class AttributeGroupDefinition: | |||||
| """Represents an xml schema attribute group definition.""" | |||||
| class IdentityConstraintDefinition: | |||||
| """Represents an xml schema identity constraint definition.""" | |||||
| class ModelGroupDefinition: | |||||
| """Represents an xml schema model group definition.""" | |||||
| class NotationDeclaration: | |||||
| """Represents an xml schema notation declaration.""" | |||||
| class Annotation: | |||||
| """Represents an xml schema annotation.""" | |||||
| class ModelGroup: | |||||
| """Represents an xml schema model group.""" | |||||
| class Particle: | |||||
| """Represents an xml schema particle.""" | |||||
| class WildCard: | |||||
| """Represents an xml schema wildcard.""" | |||||
| class AttributeUse: | |||||
| """Represents an xml schema attribute use.""" | |||||
| class ElementComponent: | |||||
| namespace = '' | |||||
| name = '' | |||||
| type = None | |||||
| form = 'qualified | unqualified' | |||||
| scope = 'global or complex def' | |||||
| constraint = ('value', 'default | fixed') | |||||
| nillable = 0 | |||||
| id_constraint_defs = None | |||||
| sub_group_affil = None | |||||
| sub_group_exclusions = None | |||||
| disallowed_subs = 'substitution, extension, restriction' | |||||
| abstract = 0 | |||||
| minOccurs = 1 | |||||
| maxOccurs = 1 | |||||
| ref = '' | |||||
| class AttributeThing: | |||||
| name = '' | |||||
| namespace = '' | |||||
| typeName = '' | |||||
| typeUri = '' | |||||
| scope = 'global | local to complex def' | |||||
| constraint = ('value:default', 'value:fixed') | |||||
| use = 'optional | prohibited | required' | |||||
| class ElementDataType: | |||||
| namespace = '' | |||||
| name = '' | |||||
| element_form = 'qualified | unqualified' | |||||
| attr_form = None | |||||
| type_name = '' | |||||
| type_uri = '' | |||||
| def __init__(self, name, namespace, type_name, type_uri): | |||||
| self.namespace = namespace | |||||
| self.name = name | |||||
| # type may be anonymous... | |||||
| self.type_name = type_name | |||||
| self.type_uri = type_uri | |||||
| def checkValue(self, value, context): | |||||
| # Delegate value checking to the type of the element. | |||||
| typeref = (self.type_uri, self.type_name) | |||||
| handler = context.serializer.getType(typeref) | |||||
| return handler.checkValue(value, context) | |||||
| def serialize(self, name, namespace, value, context, **kwargs): | |||||
| if context.check_values: | |||||
| self.checkValue(value, context) | |||||
| # Delegate serialization to the type of the element. | |||||
| typeref = (self.type_uri, self.type_name) | |||||
| handler = context.serializer.getType(typeref) | |||||
| return handler.serialize(self.name, self.namespace, value, context) | |||||
| def deserialize(self, element, context): | |||||
| if element_is_null(element, context): | |||||
| return None | |||||
| # Delegate deserialization to the type of the element. | |||||
| typeref = (self.type_uri, self.type_name) | |||||
| handler = context.serializer.getType(typeref) | |||||
| return handler.deserialize(element, context) | |||||
| def parse_schema(data): | |||||
| targetNS = '' | |||||
| attributeFormDefault = 0 | |||||
| elementFormDefault = 0 | |||||
| blockDefault = '' | |||||
| finalDefault = '' | |||||
| language = None | |||||
| version = None | |||||
| id = '' | |||||
| @@ -0,0 +1,61 @@ | |||||
| Zope Public License (ZPL) Version 2.0 | |||||
| ----------------------------------------------- | |||||
| This software is Copyright (c) Zope Corporation (tm) and | |||||
| Contributors. All rights reserved. | |||||
| This license has been certified as open source. It has also | |||||
| been designated as GPL compatible by the Free Software | |||||
| Foundation (FSF). | |||||
| Redistribution and use in source and binary forms, with or | |||||
| without modification, are permitted provided that the | |||||
| following conditions are met: | |||||
| 1. Redistributions in source code must retain the above | |||||
| copyright notice, this list of conditions, and the following | |||||
| disclaimer. | |||||
| 2. Redistributions in binary form must reproduce the above | |||||
| copyright notice, this list of conditions, and the following | |||||
| disclaimer in the documentation and/or other materials | |||||
| provided with the distribution. | |||||
| 3. The name Zope Corporation (tm) must not be used to | |||||
| endorse or promote products derived from this software | |||||
| without prior written permission from Zope Corporation. | |||||
| 4. The right to distribute this software or to use it for | |||||
| any purpose does not give you the right to use Servicemarks | |||||
| (sm) or Trademarks (tm) of Zope Corporation. Use of them is | |||||
| covered in a separate agreement (see | |||||
| http://www.zope.com/Marks). | |||||
| 5. If any files are modified, you must cause the modified | |||||
| files to carry prominent notices stating that you changed | |||||
| the files and the date of any change. | |||||
| Disclaimer | |||||
| THIS SOFTWARE IS PROVIDED BY ZOPE CORPORATION ``AS IS'' | |||||
| AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT | |||||
| NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY | |||||
| AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | |||||
| NO EVENT SHALL ZOPE CORPORATION OR ITS CONTRIBUTORS BE | |||||
| LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |||||
| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||||
| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||||
| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||||
| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |||||
| CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE | |||||
| OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |||||
| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH | |||||
| DAMAGE. | |||||
| This software consists of contributions made by Zope | |||||
| Corporation and many individuals on behalf of Zope | |||||
| Corporation. Specific attributions are listed in the | |||||
| accompanying credits file. | |||||
| @@ -0,0 +1,12 @@ | |||||
| # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved. | |||||
| # | |||||
| # This software is subject to the provisions of the Zope Public License, | |||||
| # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. | |||||
| # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED | |||||
| # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |||||
| # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS | |||||
| # FOR A PARTICULAR PURPOSE. | |||||
| """WSDL parsing services package for Web Services for Python.""" | |||||
| from ServiceProxy import ServiceProxy | |||||