# HG changeset patch # User paulb # Date 1191767475 0 # Node ID b1fda3d0156ac420e1c4a62881055e8dac7e861e # Parent 33abadb956abd6252bc359ea92e1be036b2cf7b3 [project @ 2007-10-07 14:31:15 by paulb] Introduced a SOAPContents class to permit the labelling of sequences of elements. Added support for archaic SOAP namespaces. diff -r 33abadb956ab -r b1fda3d0156a libxml2dom/soap.py --- a/libxml2dom/soap.py Sun Oct 07 13:48:50 2007 +0000 +++ b/libxml2dom/soap.py Sun Oct 07 14:31:15 2007 +0000 @@ -1,7 +1,8 @@ #!/usr/bin/env python """ -SOAP support using libxml2dom. +SOAP support using libxml2dom. Support for the archaic SOAP namespaces is also +provided. See: http://www.w3.org/TR/2007/REC-soap12-part0-20070427/ @@ -41,6 +42,11 @@ XS_NAMESPACE = "http://www.w3.org/2001/XMLSchema" XSI_NAMESPACE = "http://www.w3.org/2001/XMLSchema-instance" +# Archaic namespaces. + +OLD_SOAP_ENVELOPE_NAMESPACE = "http://schemas.xmlsoap.org/soap/envelope/" +OLD_SOAP_ENCODING_NAMESPACE = "http://schemas.xmlsoap.org/soap/encoding/" + # Default namespace bindings for XPath. default_ns = { @@ -48,7 +54,9 @@ "enc" : SOAP_ENCODING_NAMESPACE, "rpc" : SOAP_RPC_NAMESPACE, "xs" : XS_NAMESPACE, - "xsi" : XSI_NAMESPACE + "xsi" : XSI_NAMESPACE, + "SOAP-ENV" : OLD_SOAP_ENVELOPE_NAMESPACE, + "SOAP-ENC" : OLD_SOAP_ENCODING_NAMESPACE } class SOAPImplementation(libxml2dom.Implementation): @@ -73,7 +81,7 @@ # Make special envelope elements. - if Node_namespaceURI(_node) == SOAP_ENVELOPE_NAMESPACE: + if Node_namespaceURI(_node) in (SOAP_ENVELOPE_NAMESPACE, OLD_SOAP_ENVELOPE_NAMESPACE): if Node_localName(_node) == "Envelope": return SOAPEnvelopeElement(_node, self, context_node.ownerDocument) elif Node_localName(_node) == "Header": @@ -94,7 +102,7 @@ # Detect the method element. if Node_parentNode(_node) and Node_localName(Node_parentNode(_node)) == "Body" and \ - Node_namespaceURI(Node_parentNode(_node)) == SOAP_ENVELOPE_NAMESPACE: + Node_namespaceURI(Node_parentNode(_node)) in (SOAP_ENVELOPE_NAMESPACE, OLD_SOAP_ENVELOPE_NAMESPACE): return SOAPMethodElement(_node, self, context_node.ownerDocument) @@ -138,45 +146,65 @@ return node.textContent.strip() def _contents(self): + # NOTE: Should check whether this should be a leaf element. if not self.xpath("*"): return (self.localName, getattr(self.ownerDocument, "convert", self.convert)(self)) else: - return self + return (self.localName, SOAPContents(self)) def __len__(self): - children = self.xpath("*") - if not children: - return 2 - else: - return len(children) + return 2 def __getitem__(self, i): - children = self.xpath("*") - if not children: - return self.contents[i] - else: - return self.xpath("*")[i] + return self.contents[i] def __eq__(self, other): - children = self.xpath("*") - if children: - for i, j in map(None, self, other): - if i != j: - return False - return True - elif hasattr(other, "contents"): + if hasattr(other, "contents"): return self.contents == other.contents else: return self.contents == other + # Node construction methods. + + def createSOAPElement(self, localName): + + "Create an element with the appropriate namespace and prefix." + + ref_element = self.ownerDocument.documentElement + prefix = ref_element.prefix + if prefix: + name = prefix + ":" + localName + else: + name = localName + return self.createElementNS(ref_element.namespaceURI, name) + contents = property(_contents) +class SOAPContents(object): + + "A wrapper around another node in order to provide sequence-like access." + + def __init__(self, node): + self.node = node + + def __len__(self): + return len(self.node.xpath("*")) + + def __getitem__(self, i): + return self.node.xpath("*")[i] + + def __eq__(self, other): + for i, j in map(None, self, other): + if i != j: + return False + return True + class SOAPDocument(libxml2dom._Document, SOAPNode): "A SOAP document fragment." def _envelope(self): - return self.xpath("./env:Envelope")[0] + return self.xpath("env:Envelope|SOAP-ENV:Envelope")[0] envelope = property(_envelope) @@ -202,7 +230,7 @@ "A SOAP envelope element." def _body(self): - return self.xpath("./env:Body")[0] + return self.xpath("env:Body|SOAP-ENV:Body")[0] def _setBody(self, body): self.appendChild(body) @@ -211,7 +239,7 @@ self.removeChild(self.body) def createBody(self): - return self.ownerDocument.createElementNS(SOAP_ENVELOPE_NAMESPACE, "env:Body") + return self.createSOAPElement("Body") body = property(_body, _setBody, _delBody) @@ -226,15 +254,18 @@ "A SOAP body element." def _fault(self): - return (self.xpath("./env:Fault") or [None])[0] + return (self.xpath("env:Fault|SOAP-ENV:Fault") or [None])[0] def _method(self): - return (self.xpath("./*[@env:encodingStyle = '%s']" % SOAP_ENCODING_NAMESPACE) or [None])[0] + if self.namespaceURI == SOAP_ENVELOPE_NAMESPACE: + return (self.xpath("*[@env:encodingStyle = '%s']" % SOAP_ENCODING_NAMESPACE) or [None])[0] + else: + return (self.xpath("*") or [None])[0] # Node construction methods. def createFault(self): - return self.ownerDocument.createElementNS(SOAP_ENVELOPE_NAMESPACE, "env:Fault") + return self.createSOAPElement("Fault") fault = property(_fault) method = property(_method) @@ -273,27 +304,27 @@ "A SOAP fault element." def _code(self): - code = self.xpath("./env:Code") + code = self.xpath("env:Code|SOAP-ENV:Code") if code: return code[0].value else: return None def _subcode(self): - subcode = self.xpath("./env:Code/env:Subcode") + subcode = self.xpath("./env:Code/env:Subcode|./SOAP-ENV:Code/SOAP-ENV:Subcode") if subcode: return subcode[0].value else: return None def _reason(self): - return (self.xpath("./env:Reason") or [None])[0] + return (self.xpath("env:Reason|SOAP-ENV:Reason") or [None])[0] def _detail(self): - return (self.xpath("./env:Detail") or [None])[0] + return (self.xpath("env:Detail|SOAP-ENV:Detail") or [None])[0] def createCode(self): - return self.ownerDocument.createElementNS(SOAP_ENVELOPE_NAMESPACE, "env:Code") + return self.createSOAPElement("Code") code = property(_code) subcode = property(_subcode) @@ -305,14 +336,14 @@ "A SOAP subcode element." def _value(self): - value = self.xpath("./env:Value") + value = self.xpath("env:Value|SOAP-ENV:Value") if value: return value[0].textContent.strip() else: return None def _setValue(self, value): - nodes = self.xpath("./env:Value") + nodes = self.xpath("env:Value|SOAP-ENV:Value") v = self.createValue() if nodes: self.replaceChild(v, nodes[0]) @@ -321,7 +352,7 @@ v.value = value def createValue(self, value=None): - code_value = self.ownerDocument.createElementNS(SOAP_ENVELOPE_NAMESPACE, "env:Value") + code_value = self.createSOAPElement("Value") if value is not None: code_value.value = code return code_value @@ -333,10 +364,10 @@ "A SOAP code element." def _subcode(self): - return (self.xpath("./env:Subcode") or [None])[0] + return (self.xpath("env:Subcode|SOAP-ENV:Subcode") or [None])[0] def createSubcode(self): - return self.ownerDocument.createElementNS(SOAP_ENVELOPE_NAMESPACE, "env:Subcode") + return self.createSOAPElement("Subcode") subcode = property(_subcode)