1.1 --- a/libxml2dom/xmlrpc.py Sun Sep 07 18:46:50 2008 +0200
1.2 +++ b/libxml2dom/xmlrpc.py Wed Sep 10 00:35:11 2008 +0200
1.3 @@ -5,7 +5,7 @@
1.4
1.5 See: http://www.xmlrpc.com/spec
1.6
1.7 -Copyright (C) 2007 Paul Boddie <paul@boddie.org.uk>
1.8 +Copyright (C) 2007, 2008 Paul Boddie <paul@boddie.org.uk>
1.9
1.10 This program is free software; you can redistribute it and/or modify it under
1.11 the terms of the GNU Lesser General Public License as published by the Free
1.12 @@ -34,87 +34,18 @@
1.13 createDocument as Node_createDocument
1.14 import datetime
1.15
1.16 -class XMLRPCImplementation(libxml2dom.Implementation):
1.17 -
1.18 - "Contains an XML-RPC-specific implementation."
1.19 -
1.20 - # Wrapping of documents.
1.21 -
1.22 - def adoptDocument(self, node):
1.23 - return XMLRPCDocument(node, self)
1.24 -
1.25 - # Factory functions.
1.26 -
1.27 - def get_node(self, _node, context_node):
1.28 -
1.29 - """
1.30 - Get a libxml2dom node for the given low-level '_node' and libxml2dom
1.31 - 'context_node'.
1.32 - """
1.33 -
1.34 - if Node_nodeType(_node) == context_node.ELEMENT_NODE:
1.35 -
1.36 - # Make special elements.
1.37 -
1.38 - if Node_localName(_node) in ("methodCall", "methodResponse"):
1.39 - return XMLRPCMethodElement(_node, self, context_node.ownerDocument)
1.40 - elif Node_localName(_node) == "methodName":
1.41 - return XMLRPCMethodNameElement(_node, self, context_node.ownerDocument)
1.42 - elif Node_localName(_node) == "fault":
1.43 - return XMLRPCFaultElement(_node, self, context_node.ownerDocument)
1.44 - elif Node_localName(_node) == "string":
1.45 - return XMLRPCStringElement(_node, self, context_node.ownerDocument)
1.46 - elif Node_localName(_node) in ("int", "i4"):
1.47 - return XMLRPCIntegerElement(_node, self, context_node.ownerDocument)
1.48 - elif Node_localName(_node) == "boolean":
1.49 - return XMLRPCBooleanElement(_node, self, context_node.ownerDocument)
1.50 - elif Node_localName(_node) == "double":
1.51 - return XMLRPCDoubleElement(_node, self, context_node.ownerDocument)
1.52 - elif Node_localName(_node) == "dateTime.iso8601":
1.53 - return XMLRPCDateTimeElement(_node, self, context_node.ownerDocument)
1.54 - elif Node_localName(_node) == "base64":
1.55 - return XMLRPCBase64Element(_node, self, context_node.ownerDocument)
1.56 - elif Node_localName(_node) == "struct":
1.57 - return XMLRPCStructElement(_node, self, context_node.ownerDocument)
1.58 - elif Node_localName(_node) == "member":
1.59 - return XMLRPCMemberElement(_node, self, context_node.ownerDocument)
1.60 - elif Node_localName(_node) == "value":
1.61 - return XMLRPCValueElement(_node, self, context_node.ownerDocument)
1.62 - elif Node_localName(_node) == "name":
1.63 - return XMLRPCNameElement(_node, self, context_node.ownerDocument)
1.64 - elif Node_localName(_node) == "array":
1.65 - return XMLRPCArrayElement(_node, self, context_node.ownerDocument)
1.66 - elif Node_localName(_node) == "data":
1.67 - return XMLRPCDataElement(_node, self, context_node.ownerDocument)
1.68 -
1.69 - # Otherwise, make generic XML-RPC elements.
1.70 -
1.71 - return XMLRPCElement(_node, self, context_node.ownerDocument)
1.72 -
1.73 - else:
1.74 - return libxml2dom.Implementation.get_node(self, _node, context_node)
1.75 -
1.76 - # Convenience functions.
1.77 -
1.78 - def createXMLRPCMessage(self, namespaceURI, localName):
1.79 -
1.80 - "Create a new XML-RPC message document (fragment)."
1.81 -
1.82 - return XMLRPCDocument(Node_createDocument(namespaceURI, localName, None), self).documentElement
1.83 -
1.84 - def createMethodCall(self):
1.85 - return self.createXMLRPCMessage(None, "methodCall")
1.86 -
1.87 - def createMethodResponse(self):
1.88 - return self.createXMLRPCMessage(None, "methodResponse")
1.89 -
1.90 # Node classes.
1.91
1.92 class XMLRPCNode(libxml2dom.Node):
1.93
1.94 "Convenience modifications to nodes specific to libxml2dom.xmlrpc."
1.95
1.96 - pass
1.97 + def add_or_replace_element(self, new_element):
1.98 + elements = self.xpath("*")
1.99 + if elements:
1.100 + self.replaceChild(new_element, elements[0])
1.101 + else:
1.102 + self.appendChild(new_element)
1.103
1.104 class XMLRPCElement(XMLRPCNode):
1.105
1.106 @@ -140,11 +71,17 @@
1.107
1.108 # Node construction methods.
1.109
1.110 - def createMethodCall(self):
1.111 - return self.ownerDocument.createElement("methodCall")
1.112 + def createMethodCall(self, insert=0):
1.113 + e = self.ownerDocument.createElement("methodCall")
1.114 + if insert:
1.115 + self.add_or_replace_element(e)
1.116 + return e
1.117
1.118 - def createMethodResponse(self):
1.119 - return self.ownerDocument.createElement("methodResponse")
1.120 + def createMethodResponse(self, insert=0):
1.121 + e = self.ownerDocument.createElement("methodResponse")
1.122 + if insert:
1.123 + self.add_or_replace_element(e)
1.124 + return e
1.125
1.126 class XMLRPCMethodElement(XMLRPCNode):
1.127
1.128 @@ -174,20 +111,56 @@
1.129
1.130 # Node construction methods.
1.131
1.132 - def createMethodName(self):
1.133 - return self.ownerDocument.createElement("methodName")
1.134 + def createMethodName(self, insert=0):
1.135 + e = self.ownerDocument.createElement("methodName")
1.136 + if insert:
1.137 + self.add_or_replace_element(e)
1.138 + return e
1.139
1.140 - def createParameters(self):
1.141 - return self.ownerDocument.createElement("params")
1.142 + def createParameters(self, insert=0):
1.143 + e = self.ownerDocument.createElement("params")
1.144 + if insert:
1.145 + self.add_or_replace_element(e)
1.146 + return e
1.147
1.148 - def createFault(self):
1.149 - return self.ownerDocument.createElement("fault")
1.150 + def createFault(self, insert=0):
1.151 + e = self.ownerDocument.createElement("fault")
1.152 + if insert:
1.153 + self.add_or_replace_element(e)
1.154 + return e
1.155
1.156 fault = property(_fault)
1.157 methodNameElement = property(_methodNameElement)
1.158 methodName = property(_methodName, _setMethodName)
1.159 parameterValues = property(_parameterValues)
1.160
1.161 +class XMLRPCParametersElement(XMLRPCNode):
1.162 +
1.163 + "An XML-RPC parameters/params element."
1.164 +
1.165 + # Node construction methods.
1.166 +
1.167 + def createParameter(self, insert=0):
1.168 + e = self.ownerDocument.createElement("param")
1.169 + if insert:
1.170 + self.appendChild(e)
1.171 + return e
1.172 +
1.173 +class XMLRPCParameterElement(XMLRPCNode):
1.174 +
1.175 + "An XML-RPC parameter/param element."
1.176 +
1.177 + # Node construction methods.
1.178 +
1.179 + def createValue(self, typename=None, insert=0):
1.180 + value = self.ownerDocument.createElement("value")
1.181 + if typename is not None:
1.182 + contents = self.ownerDocument.createElement(typename)
1.183 + value.appendChild(contents)
1.184 + if insert:
1.185 + self.add_or_replace_element(value)
1.186 + return value
1.187 +
1.188 class XMLRPCArrayElement(XMLRPCNode):
1.189
1.190 "An XML-RPC array element."
1.191 @@ -220,8 +193,11 @@
1.192
1.193 # Node construction methods.
1.194
1.195 - def createData(self):
1.196 - return self.ownerDocument.createElement("data")
1.197 + def createData(self, insert=0):
1.198 + e = self.ownerDocument.createElement("data")
1.199 + if insert:
1.200 + self.add_or_replace_element(e)
1.201 + return e
1.202
1.203 data = property(_data)
1.204 contents = property(_contents)
1.205 @@ -252,8 +228,11 @@
1.206
1.207 # Node construction methods.
1.208
1.209 - def createMember(self):
1.210 - return self.ownerDocument.createElement("member")
1.211 + def createMember(self, insert=0):
1.212 + e = self.ownerDocument.createElement("member")
1.213 + if insert:
1.214 + self.add_or_replace_element(e)
1.215 + return e
1.216
1.217 members = property(_members)
1.218 contents = property(_contents)
1.219 @@ -275,8 +254,11 @@
1.220
1.221 # Node construction methods.
1.222
1.223 - def createValue(self):
1.224 - return self.ownerDocument.createElement("value")
1.225 + def createValue(self, insert=0):
1.226 + e = self.ownerDocument.createElement("value")
1.227 + if insert:
1.228 + self.add_or_replace_element(e)
1.229 + return e
1.230
1.231 values = property(_values)
1.232
1.233 @@ -318,11 +300,17 @@
1.234
1.235 # Node construction methods.
1.236
1.237 - def createName(self):
1.238 - return self.ownerDocument.createElement("name")
1.239 + def createName(self, insert=0):
1.240 + e = self.ownerDocument.createElement("name")
1.241 + if insert:
1.242 + self.add_or_replace_element(e)
1.243 + return e
1.244
1.245 - def createValue(self):
1.246 - return self.ownerDocument.createElement("value")
1.247 + def createValue(self, insert=0):
1.248 + e = self.ownerDocument.createElement("value")
1.249 + if insert:
1.250 + self.add_or_replace_element(e)
1.251 + return e
1.252
1.253 value = property(_value)
1.254 nameElement = property(_nameElement)
1.255 @@ -373,10 +361,14 @@
1.256 else:
1.257 return "string"
1.258
1.259 + def _setType(self, typename):
1.260 + new_contents = self.ownerDocument.createElement(typename)
1.261 + self.add_or_replace_element(new_contents)
1.262 +
1.263 def _container(self):
1.264 return (self.xpath("*") or [self])[0]
1.265
1.266 - type = property(_type)
1.267 + type = property(_type, _setType)
1.268 container = property(_container)
1.269
1.270 class XMLRPCMethodNameElement(XMLRPCStringElement):
1.271 @@ -463,6 +455,87 @@
1.272 "base64" : str
1.273 }
1.274
1.275 +# Implementation-related functionality.
1.276 +
1.277 +class XMLRPCImplementation(libxml2dom.Implementation):
1.278 +
1.279 + "Contains an XML-RPC-specific implementation."
1.280 +
1.281 + # Mapping of element names to wrappers.
1.282 +
1.283 + _class_for_name = {
1.284 + "methodCall" : XMLRPCMethodElement,
1.285 + "methodResponse" : XMLRPCMethodElement,
1.286 + "methodName" : XMLRPCMethodNameElement,
1.287 + "params" : XMLRPCParametersElement,
1.288 + "param" : XMLRPCParameterElement,
1.289 + "fault" : XMLRPCFaultElement,
1.290 + "string" : XMLRPCStringElement,
1.291 + "int" : XMLRPCIntegerElement,
1.292 + "i4" : XMLRPCIntegerElement,
1.293 + "boolean" : XMLRPCBooleanElement,
1.294 + "double" : XMLRPCDoubleElement,
1.295 + "dateTime.iso8601" : XMLRPCDateTimeElement,
1.296 + "base64" : XMLRPCBase64Element,
1.297 + "struct" : XMLRPCStructElement,
1.298 + "member" : XMLRPCMemberElement,
1.299 + "value" : XMLRPCValueElement,
1.300 + "name" : XMLRPCNameElement,
1.301 + "array" : XMLRPCArrayElement,
1.302 + "data" : XMLRPCDataElement
1.303 + }
1.304 +
1.305 + # Wrapping of documents.
1.306 +
1.307 + def adoptDocument(self, node):
1.308 + return XMLRPCDocument(node, self)
1.309 +
1.310 + # Factory functions.
1.311 +
1.312 + def get_node(self, _node, context_node):
1.313 +
1.314 + """
1.315 + Get a libxml2dom node for the given low-level '_node' and libxml2dom
1.316 + 'context_node'.
1.317 + """
1.318 +
1.319 + if Node_nodeType(_node) == context_node.ELEMENT_NODE:
1.320 +
1.321 + # Make special objects for certain elements.
1.322 + # Otherwise, make generic XML-RPC elements.
1.323 +
1.324 + cls = self._class_for_name.get(Node_localName(_node)) or XMLRPCElement
1.325 + return cls(_node, self, context_node.ownerDocument)
1.326 +
1.327 + else:
1.328 + return libxml2dom.Implementation.get_node(self, _node, context_node)
1.329 +
1.330 + # Convenience functions.
1.331 +
1.332 + def createXMLRPCMessage(self, namespaceURI, localName):
1.333 +
1.334 + "Create a new XML-RPC message document (fragment)."
1.335 +
1.336 + return XMLRPCDocument(Node_createDocument(namespaceURI, localName, None), self).documentElement
1.337 +
1.338 + def createMethodCall(self, name=None):
1.339 +
1.340 + """
1.341 + Create and return a message fragment for a method call having the given
1.342 + 'name'.
1.343 + """
1.344 +
1.345 + message = self.createXMLRPCMessage(None, "methodCall")
1.346 + if name is not None:
1.347 + message.methodName = name
1.348 + return message
1.349 +
1.350 + def createMethodResponse(self):
1.351 +
1.352 + "Create and return a message fragment for a method response."
1.353 +
1.354 + return self.createXMLRPCMessage(None, "methodResponse")
1.355 +
1.356 # Utility functions.
1.357
1.358 createDocument = libxml2dom.createDocument
1.359 @@ -471,8 +544,8 @@
1.360 def createXMLRPCMessage(namespaceURI, localName):
1.361 return default_impl.createXMLRPCMessage(None, localName)
1.362
1.363 -def createMethodCall():
1.364 - return default_impl.createMethodCall()
1.365 +def createMethodCall(name=None):
1.366 + return default_impl.createMethodCall(name)
1.367
1.368 def createMethodResponse():
1.369 return default_impl.createMethodResponse()