1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/libxml2dom/conversions.py Mon Oct 01 23:26:37 2007 +0000
1.3 @@ -0,0 +1,49 @@
1.4 +#!/usr/bin/env python
1.5 +
1.6 +"""
1.7 +Conversion functions and data used by XML-RPC and SOAP.
1.8 +
1.9 +Copyright (C) 2007 Paul Boddie <paul@boddie.org.uk>
1.10 +
1.11 +This program is free software; you can redistribute it and/or modify it under
1.12 +the terms of the GNU Lesser General Public License as published by the Free
1.13 +Software Foundation; either version 3 of the License, or (at your option) any
1.14 +later version.
1.15 +
1.16 +This program is distributed in the hope that it will be useful, but WITHOUT
1.17 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.18 +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
1.19 +details.
1.20 +
1.21 +You should have received a copy of the GNU Lesser General Public License along
1.22 +with this program. If not, see <http://www.gnu.org/licenses/>.
1.23 +"""
1.24 +
1.25 +converters = {
1.26 + "string" : unicode,
1.27 + "int" : int,
1.28 + "i4" : int,
1.29 + "double" : float,
1.30 + "boolean" : boolean, # see the module globals
1.31 + "dateTime.iso8601" : iso8601, # see the module globals
1.32 + "base64" : str
1.33 + }
1.34 +
1.35 +def from_string(typename, value):
1.36 + return converters.get(typename, str)(value)
1.37 +
1.38 +# Utility functions.
1.39 +
1.40 +def boolean(s):
1.41 + if s.lower() == "true":
1.42 + return True
1.43 + elif s.lower() == "false":
1.44 + return False
1.45 + else:
1.46 + raise ValueError, "String value %s not convertable to boolean." % repr(s)
1.47 +
1.48 +def iso8601(s):
1.49 + # NOTE: To be written.
1.50 + return s
1.51 +
1.52 +# vim: tabstop=4 expandtab shiftwidth=4
2.1 --- a/libxml2dom/soap.py Sun Sep 30 23:23:48 2007 +0000
2.2 +++ b/libxml2dom/soap.py Mon Oct 01 23:26:37 2007 +0000
2.3 @@ -91,6 +91,13 @@
2.4 elif Node_localName(_node) == "Text":
2.5 return SOAPTextElement(_node, self, context_node.ownerDocument)
2.6
2.7 + # Detect the method element.
2.8 +
2.9 + if Node_parentNode(_node) and Node_localName(Node_parentNode(_node)) == "Body" and \
2.10 + Node_namespaceURI(Node_parentNode(_node)) == SOAP_ENVELOPE_NAMESPACE:
2.11 +
2.12 + return SOAPMethodElement(_node, self, context_node.ownerDocument)
2.13 +
2.14 # Otherwise, make generic SOAP elements.
2.15
2.16 return SOAPElement(_node, self, context_node.ownerDocument)
2.17 @@ -136,26 +143,14 @@
2.18
2.19 # Convenience methods and properties.
2.20
2.21 - def _methodName(self):
2.22 - return self.envelope.body.methodName
2.23 -
2.24 - def _parameterItems(self):
2.25 - return self.envelope.body.parameterItems
2.26 -
2.27 - def _parameterValues(self):
2.28 - return self.envelope.body.parameterValues
2.29 -
2.30 - def _parameterMap(self):
2.31 - return self.envelope.body.parameterMap
2.32 -
2.33 def _fault(self):
2.34 return self.envelope.body.fault
2.35
2.36 - methodName = property(_methodName)
2.37 - parameterItems = property(_parameterItems)
2.38 - parameterValues = property(_parameterValues)
2.39 - parameterMap = property(_parameterMap)
2.40 + def _method(self):
2.41 + return self.envelope.body.method
2.42 +
2.43 fault = property(_fault)
2.44 + method = property(_method)
2.45
2.46 class SOAPElement(SOAPNode):
2.47
2.48 @@ -197,19 +192,28 @@
2.49 def _method(self):
2.50 return (self.xpath("./*[@env:encodingStyle = '%s']" % SOAP_ENCODING_NAMESPACE) or [None])[0]
2.51
2.52 + # Node construction methods.
2.53 +
2.54 + def createFault(self):
2.55 + return self.ownerDocument.createElementNS(SOAP_ENVELOPE_NAMESPACE, "env:Fault")
2.56 +
2.57 + fault = property(_fault)
2.58 + method = property(_method)
2.59 +
2.60 +class SOAPMethodElement(SOAPNode):
2.61 +
2.62 + "A SOAP method element."
2.63 +
2.64 def _methodName(self):
2.65 - if self.method is not None:
2.66 - return self.method.localName
2.67 - else:
2.68 - return None
2.69 + return self.localName
2.70
2.71 def _resultParameter(self):
2.72 - return (self.method.xpath(".//rpc:result") or [None])[0]
2.73 + return (self.xpath(".//rpc:result") or [None])[0]
2.74
2.75 def _resultParameterValue(self):
2.76 if self.resultParameter:
2.77 name = self.resultParameter.textContent.strip()
2.78 - result = self.method.xpath(".//%s" % name, namespaces={self.method.prefix : self.method.namespaceURI})
2.79 + result = self.xpath(".//%s" % name, namespaces={self.prefix : self.namespaceURI})
2.80 if result:
2.81 return result[0].textContent.strip()
2.82 else:
2.83 @@ -218,70 +222,55 @@
2.84 return None
2.85
2.86 def _parameters(self):
2.87 - if self.method is not None:
2.88 - return self.method.xpath("*")
2.89 - else:
2.90 - return []
2.91 + return self.xpath("*")
2.92
2.93 - def _parameterItems(self):
2.94 + def _parameterValues(self):
2.95 values = []
2.96 for parameter in self.parameters:
2.97 - values.append(self._item_contents(parameter))
2.98 + values.append(self._get_value(parameter))
2.99 return values
2.100
2.101 - def _parameterValues(self):
2.102 - return self._value_contents(self.parameterItems)
2.103 + def _setParameterValues(self, parameters):
2.104 + for node in self.parameters:
2.105 + self.removeChild(node)
2.106
2.107 - def _parameterMap(self):
2.108 - return self._map_contents(self.parameterItems)
2.109 + # Add the parameter values.
2.110 +
2.111 + for parameter in parameters:
2.112 + self._add_value(self, parameter)
2.113
2.114 # Internal methods.
2.115
2.116 - def _item_contents(self, parameter):
2.117 + def _add_value(self, value, parameter):
2.118 + (ns, name), parameter = parameter
2.119 + container = self.ownerDocument.createElementNS(ns, name)
2.120 + value.appendChild(container)
2.121 + if isinstance(parameter, (list, dict)):
2.122 + if isinstance(parameter, dict):
2.123 + items = parameter.items()
2.124 + else:
2.125 + items = parameter
2.126 + for item in items:
2.127 + self._add_value(container, item)
2.128 + else:
2.129 + text = self.ownerDocument.createTextNode(unicode(parameter))
2.130 + container.appendChild(text)
2.131 +
2.132 + def _get_value(self, parameter):
2.133 elements = parameter.xpath("*")
2.134 if elements:
2.135 items = []
2.136 for element in elements:
2.137 - items.append(self._item_contents(element))
2.138 - return (parameter.namespaceURI, parameter.localName), items
2.139 + items.append(self._get_value(element))
2.140 + return (parameter.namespaceURI, parameter.name), items
2.141 else:
2.142 - return (parameter.namespaceURI, parameter.localName), parameter.textContent.strip()
2.143 -
2.144 - def _value_contents(self, items):
2.145 - values = []
2.146 - for (typename, name), value in items:
2.147 - if isinstance(value, list):
2.148 - values.append(self._value_contents(value))
2.149 - elif name is None:
2.150 - values.append(value)
2.151 - else:
2.152 - values.append((name, value))
2.153 - return values
2.154 + return (parameter.namespaceURI, parameter.name), parameter.textContent.strip()
2.155
2.156 - def _map_contents(self, items):
2.157 - d = {}
2.158 - for n, ((typename, name), value) in enumerate(items):
2.159 - key_name = name or str(n)
2.160 - if isinstance(value, list):
2.161 - d[(typename, key_name)] = self._map_contents(value)
2.162 - else:
2.163 - d[(typename, key_name)] = value
2.164 - return d
2.165 -
2.166 - # Node construction methods.
2.167 -
2.168 - def createFault(self):
2.169 - return self.ownerDocument.createElementNS(SOAP_ENVELOPE_NAMESPACE, "env:Fault")
2.170 -
2.171 - fault = property(_fault)
2.172 - method = property(_method)
2.173 methodName = property(_methodName)
2.174 resultParameter = property(_resultParameter)
2.175 resultParameterValue = property(_resultParameterValue)
2.176 parameters = property(_parameters)
2.177 - parameterItems = property(_parameterItems)
2.178 - parameterValues = property(_parameterValues)
2.179 - parameterMap = property(_parameterMap)
2.180 + parameterValues = property(_parameterValues, _setParameterValues)
2.181
2.182 class SOAPFaultElement(SOAPNode):
2.183
3.1 --- a/libxml2dom/xmlrpc.py Sun Sep 30 23:23:48 2007 +0000
3.2 +++ b/libxml2dom/xmlrpc.py Mon Oct 01 23:26:37 2007 +0000
3.3 @@ -80,6 +80,8 @@
3.4 return XMLRPCMemberElement(_node, self, context_node.ownerDocument)
3.5 elif Node_localName(_node) == "value":
3.6 return XMLRPCValueElement(_node, self, context_node.ownerDocument)
3.7 + elif Node_localName(_node) == "name":
3.8 + return XMLRPCNameElement(_node, self, context_node.ownerDocument)
3.9
3.10 # Otherwise, make generic XML-RPC elements.
3.11
3.12 @@ -102,19 +104,6 @@
3.13 def createMethodResponse(self):
3.14 return self.createXMLRPCMessage(None, "methodResponse")
3.15
3.16 -# Internal utility functions.
3.17 -
3.18 -def boolean(s):
3.19 - if s.lower() == "true":
3.20 - return True
3.21 - elif s.lower() == "false":
3.22 - return False
3.23 - else:
3.24 - raise ValueError, "String value %s not convertable to boolean." % repr(s)
3.25 -
3.26 -def iso8601(s):
3.27 - return s
3.28 -
3.29 # Node classes.
3.30
3.31 class XMLRPCNode(libxml2dom.Node):
3.32 @@ -134,35 +123,7 @@
3.33 "An XML-RPC document fragment."
3.34
3.35 def _method(self):
3.36 - return (self.xpath("./methodCall|./methodResponse") or [None])[0]
3.37 -
3.38 - method = property(_method)
3.39 -
3.40 - # Convenience methods and properties.
3.41 -
3.42 - def _methodName(self):
3.43 - if self.method is not None:
3.44 - return self.method.name
3.45 - else:
3.46 - return None
3.47 -
3.48 - def _parameterItems(self):
3.49 - if self.method is not None:
3.50 - return self.method.parameterItems
3.51 - else:
3.52 - return None
3.53 -
3.54 - def _parameterValues(self):
3.55 - if self.method is not None:
3.56 - return self.method.parameterValues
3.57 - else:
3.58 - return None
3.59 -
3.60 - def _parameterMap(self):
3.61 - if self.method is not None:
3.62 - return self.method.parameterMap
3.63 - else:
3.64 - return None
3.65 + return (self.xpath("methodCall|methodResponse") or [None])[0]
3.66
3.67 def _fault(self):
3.68 if self.method is not None:
3.69 @@ -170,6 +131,9 @@
3.70 else:
3.71 return None
3.72
3.73 + method = property(_method)
3.74 + fault = property(_fault)
3.75 +
3.76 # Node construction methods.
3.77
3.78 def createMethodCall(self):
3.79 @@ -178,12 +142,6 @@
3.80 def createMethodResponse(self):
3.81 return self.ownerDocument.createElement("methodResponse")
3.82
3.83 - methodName = property(_methodName)
3.84 - parameterItems = property(_parameterItems)
3.85 - parameterValues = property(_parameterValues)
3.86 - parameterMap = property(_parameterMap)
3.87 - fault = property(_fault)
3.88 -
3.89 class XMLRPCMethodElement(XMLRPCNode):
3.90
3.91 "An XML-RPC method element."
3.92 @@ -191,41 +149,41 @@
3.93 def _fault(self):
3.94 return (self.xpath("./fault") or [None])[0]
3.95
3.96 - def _methodName(self):
3.97 + def _methodNameElement(self):
3.98 return (self.xpath("./methodName") or [None])[0]
3.99
3.100 - def _name(self):
3.101 - name = self.methodName
3.102 + def _methodName(self):
3.103 + name = self.methodNameElement
3.104 if name is not None:
3.105 return name.value
3.106 else:
3.107 return None
3.108
3.109 - def _setName(self, name):
3.110 - if self.methodName is None:
3.111 + def _setMethodName(self, name):
3.112 + if self.methodNameElement is None:
3.113 methodName = self.createMethodName()
3.114 self.appendChild(methodName)
3.115 - self.methodName.value = name
3.116 + self.methodNameElement.value = name
3.117
3.118 def _parameters(self):
3.119 return self.xpath("./params/param")
3.120
3.121 - def _parameterItems(self):
3.122 + def _parameterValues(self):
3.123 values = self.xpath("./params/param/value")
3.124 if values:
3.125 items = []
3.126 for value in values:
3.127 - items.append(self._item_contents(value))
3.128 + items.append(self._get_value(value))
3.129 return items
3.130 else:
3.131 return []
3.132
3.133 - def _parameterValues(self):
3.134 - return self._value_contents(self.parameterItems)
3.135 -
3.136 def _setParameterValues(self, parameters):
3.137 param_list = self.parameters
3.138 params = (self.xpath("./params") or [None])[0]
3.139 +
3.140 + # Remove any previous parameters.
3.141 +
3.142 if params:
3.143 if param_list:
3.144 for param in param_list:
3.145 @@ -234,83 +192,46 @@
3.146 params = self.createParameters()
3.147 self.appendChild(params)
3.148
3.149 + # Add parameter values.
3.150 +
3.151 for parameter in parameters:
3.152 param = self.ownerDocument.createElement("param")
3.153 params.appendChild(param)
3.154 value = self.ownerDocument.createElement("value")
3.155 param.appendChild(value)
3.156 -
3.157 - # NOTE: Only handles simple types.
3.158 -
3.159 - container = self._make_container(parameter)
3.160 - value.appendChild(container)
3.161 - text = self.ownerDocument.createTextNode(unicode(parameter))
3.162 - container.appendChild(text)
3.163 -
3.164 - def _parameterMap(self):
3.165 - return self._map_contents(self.parameterItems)
3.166 -
3.167 - # Internal data.
3.168 -
3.169 - converters = {
3.170 - "string" : unicode,
3.171 - "int" : int,
3.172 - "i4" : int,
3.173 - "double" : float,
3.174 - "boolean" : boolean, # see the module globals
3.175 - "dateTime.iso8601" : iso8601, # see the module globals
3.176 - "base64" : str
3.177 - }
3.178 + self._add_value(value, parameter)
3.179
3.180 # Internal methods.
3.181
3.182 - def _make_container(self, parameter):
3.183 - if isinstance(parameter, (str, unicode)):
3.184 - return self.ownerDocument.createElement("string")
3.185 - elif isinstance(parameter, (int, long)):
3.186 - return self.ownerDocument.createElement("int")
3.187 - elif isinstance(parameter, float):
3.188 - return self.ownerDocument.createElement("double")
3.189 - elif isinstance(parameter, bool):
3.190 - return self.ownerDocument.createElement("boolean")
3.191 - elif isinstance(parameter, datetime.datetime):
3.192 - return self.ownerDocument.createElement("dateTime.iso8601")
3.193 + def _add_value(self, value, parameter):
3.194 + typename, parameter = parameter
3.195 + if typename == "struct":
3.196 + if isinstance(parameter, dict):
3.197 + items = parameter.items()
3.198 + else:
3.199 + items = parameter
3.200 + struct = self.ownerDocument.createElement("struct")
3.201 + for item_name, item_value in items:
3.202 + member = struct.createMember()
3.203 + struct.appendChild(member)
3.204 + member.memberName = item_name
3.205 + memberValue = member.createValue()
3.206 + member.appendChild(memberValue)
3.207 + self._add_value(memberValue, item_value)
3.208 + value.appendChild(struct)
3.209 + else:
3.210 + container = self.ownerDocument.createElement(typename)
3.211 + value.appendChild(container)
3.212 + container.value = unicode(parameter)
3.213
3.214 - def _from_string(self, typename, value):
3.215 - return self.converters.get(typename, str)(value)
3.216 -
3.217 - def _item_contents(self, value):
3.218 + def _get_value(self, value):
3.219 if value.type == "struct":
3.220 items = []
3.221 for member in value.container.members:
3.222 - if member.value.type == "struct":
3.223 - items.append((member.name, self._item_contents(member.value)))
3.224 - else:
3.225 - items.append((member.name, self._from_string(member.value.type, member.value.container.value)))
3.226 - return None, items
3.227 + items.append((member.memberName, self._get_value(member.value)))
3.228 + return (value.type, items)
3.229 else:
3.230 - return None, self._from_string(value.type, value.container.value)
3.231 -
3.232 - def _value_contents(self, items):
3.233 - values = []
3.234 - for name, value in items:
3.235 - if isinstance(value, list):
3.236 - values.append(self._value_contents(value))
3.237 - elif name is None:
3.238 - values.append(value)
3.239 - else:
3.240 - values.append((name, value))
3.241 - return values
3.242 -
3.243 - def _map_contents(self, items):
3.244 - d = {}
3.245 - for n, (name, value) in enumerate(items):
3.246 - key_name = name or str(n)
3.247 - if isinstance(value, list):
3.248 - d[key_name] = self._map_contents(value)
3.249 - else:
3.250 - d[key_name] = value
3.251 - return d
3.252 + return (value.type, value.container.value)
3.253
3.254 # Node construction methods.
3.255
3.256 @@ -324,12 +245,58 @@
3.257 return self.ownerDocument.createElement("fault")
3.258
3.259 fault = property(_fault)
3.260 - name = property(_name, _setName)
3.261 - methodName = property(_methodName)
3.262 + methodNameElement = property(_methodNameElement)
3.263 + methodName = property(_methodName, _setMethodName)
3.264 parameters = property(_parameters)
3.265 - parameterItems = property(_parameterItems)
3.266 parameterValues = property(_parameterValues, _setParameterValues)
3.267 - parameterMap = property(_parameterMap)
3.268 +
3.269 +class XMLRPCStructElement(XMLRPCNode):
3.270 +
3.271 + "An XML-RPC structure element."
3.272 +
3.273 + def _members(self):
3.274 + return self.xpath("./member")
3.275 +
3.276 + # Node construction methods.
3.277 +
3.278 + def createMember(self):
3.279 + return self.ownerDocument.createElement("member")
3.280 +
3.281 + members = property(_members)
3.282 +
3.283 +class XMLRPCMemberElement(XMLRPCNode):
3.284 +
3.285 + "An XML-RPC structure member element."
3.286 +
3.287 + def _nameElement(self):
3.288 + return (self.xpath("./name") or [None])[0]
3.289 +
3.290 + def _memberName(self):
3.291 + if self.nameElement is not None:
3.292 + return self.nameElement.value
3.293 + else:
3.294 + return None
3.295 +
3.296 + def _setMemberName(self, name):
3.297 + if self.nameElement is None:
3.298 + nameElement = self.createName()
3.299 + self.appendChild(nameElement)
3.300 + self.nameElement.value = name
3.301 +
3.302 + def _value(self):
3.303 + return (self.xpath("./value") or [None])[0]
3.304 +
3.305 + # Node construction methods.
3.306 +
3.307 + def createName(self):
3.308 + return self.ownerDocument.createElement("name")
3.309 +
3.310 + def createValue(self):
3.311 + return self.ownerDocument.createElement("value")
3.312 +
3.313 + nameElement = property(_nameElement)
3.314 + memberName = property(_memberName, _setMemberName)
3.315 + value = property(_value)
3.316
3.317 class XMLRPCStringElement(XMLRPCNode):
3.318
3.319 @@ -346,6 +313,12 @@
3.320
3.321 value = property(_value, _setValue)
3.322
3.323 +class XMLRPCNameElement(XMLRPCStringElement):
3.324 +
3.325 + "An XML-RPC name element."
3.326 +
3.327 + pass
3.328 +
3.329 class XMLRPCValueElement(XMLRPCStringElement):
3.330
3.331 "An XML-RPC value element."
3.332 @@ -399,32 +372,6 @@
3.333
3.334 pass
3.335
3.336 -class XMLRPCStructElement(XMLRPCNode):
3.337 -
3.338 - "An XML-RPC structure element."
3.339 -
3.340 - def _members(self):
3.341 - return self.xpath("./member")
3.342 -
3.343 - members = property(_members)
3.344 -
3.345 -class XMLRPCMemberElement(XMLRPCNode):
3.346 -
3.347 - "An XML-RPC structure member element."
3.348 -
3.349 - def _name(self):
3.350 - value = self.xpath("./name")
3.351 - if value:
3.352 - return value[0].textContent.strip()
3.353 - else:
3.354 - return None
3.355 -
3.356 - def _value(self):
3.357 - return (self.xpath("./value") or [None])[0]
3.358 -
3.359 - name = property(_name)
3.360 - value = property(_value)
3.361 -
3.362 class XMLRPCFaultElement(XMLRPCNode):
3.363
3.364 "An XML-RPC fault element."