def _inherit_context(self, node): '''_inherit_context(self, node) -> list Scan ancestors of attribute and namespace context. Used only for single element node canonicalization, not for subset canonicalization.''' # Collect the initial list of xml:foo attributes. xmlattrs = filter(_IN_XML_NS, _attrs(node)) # Walk up and get all xml:XXX attributes we inherit. inherited, parent = [], node.parentNode while parent and parent.nodeType == Node.ELEMENT_NODE: for a in filter(_IN_XML_NS, _attrs(parent)): n = a.localName if n not in xmlattrs: xmlattrs.append(n) inherited.append(a) parent = parent.parentNode return inherited
def GetElementNSdict(self, elt): '''Get a dictionary of all the namespace attributes for the indicated element. The dictionaries are cached, and we recurse up the tree as necessary. ''' d = self.ns_cache.get(id(elt)) if not d: if elt != self.dom: d = self.GetElementNSdict(elt.parentNode) for a in _attrs(elt): if a.namespaceURI == XMLNS.BASE: if a.localName == "xmlns": d[''] = a.nodeValue else: d[a.localName] = a.nodeValue self.ns_cache[id(elt)] = d return d.copy()
def Receive(self, replytype=None, **kw): '''Parse message, create Python object. if replytype is None, use TC.Any to dynamically parse; otherwise it can be a Python class or the typecode to use in parsing. ''' self.ReceiveSOAP(**kw) if self.ps.IsAFault(): msg = FaultFromFaultMessage(self.ps) raise FaultException(msg) if replytype is None: tc = TC.Any(aslist=1) # if the message is RPC style, skip the fooBarResponse elt_name = '%s' % self.ps.body_root.localName if elt_name.find('Response') > 0: data = _child_elements(self.ps.body_root) else: data = [self.ps.body_root] if len(data) == 0: return None # check for array type, loop and process if found for attr in _attrs(data[0]): if attr.localName.find('arrayType') >= 0: data = _child_elements(data[0]) toReturn = [] for node in data: type = node.localName # handle case where multiple elements are returned if type.find('element') >= 0: node = _child_elements(node)[0] type = node.localName toReturn.append(self.__parse(node, type)) return toReturn # parse a complex or primitive type and return it type = data[0].localName return self.__parse(data[0], type) elif hasattr(replytype, 'typecode'): tc = replytype.typecode else: tc = replytype return self.ps.Parse(tc)
class ParsedSoap: '''A Parsed SOAP object. Convert the text to a DOM tree and parse SOAP elements. Instance data: reader -- the DOM reader dom -- the DOM object ns_cache -- dictionary (by id(node)) of namespace dictionaries id_cache -- dictionary (by XML ID attr) of elements envelope -- the node holding the SOAP Envelope header -- the node holding the SOAP Header (or None) body -- the node holding the SOAP Body body_root -- the serialization root in the SOAP Body data_elements -- list of non-root elements in the SOAP Body trailer_elements -- list of elements following the SOAP body ''' defaultReaderClass = DefaultReader def __init__(self, input, readerclass=None, keepdom=False, trailers=False, resolver=None, envelope=True, **kw): '''Initialize. Keyword arguments: trailers -- allow trailer elments (default is zero) resolver -- function (bound method) to resolve URI's readerclass -- factory class to create a reader keepdom -- do not release the DOM envelope -- look for a SOAP envelope. ''' self.readerclass = readerclass self.keepdom = keepdom if not self.readerclass: self.readerclass = self.defaultReaderClass try: self.reader = self.readerclass() if type(input) in _stringtypes: self.dom = self.reader.fromString(input) else: self.dom = self.reader.fromStream(input) except Exception, e: # Is this in the header? Your guess is as good as mine. #raise ParseException("Can't parse document (" + \ # str(e.__class__) + "): " + str(e), 0) raise self.ns_cache = { id(self.dom): { 'xml': XMLNS.XML, 'xmlns': XMLNS.BASE, '': '' } } self.trailers, self.resolver, self.id_cache = trailers, resolver, {} # Exactly one child element c = [ E for E in _children(self.dom) if E.nodeType == _Node.ELEMENT_NODE ] if len(c) == 0: raise ParseException("Document has no Envelope", 0) if len(c) != 1: raise ParseException("Document has extra child elements", 0) if envelope is False: self.body_root = c[0] return # And that one child must be the Envelope elt = c[0] if elt.localName != "Envelope" \ or elt.namespaceURI != SOAP.ENV: raise ParseException('Document has "' + elt.localName + \ '" element, not Envelope', 0) self._check_for_legal_children("Envelope", elt) for a in _attrs(elt): name = a.nodeName if name.find(":") == -1 and name not in ["xmlns", "id"]: raise ParseException('Unqualified attribute "' + \ name + '" in Envelope', 0) self.envelope = elt if not _valid_encoding(self.envelope): raise ParseException("Envelope has invalid encoding", 0) # Get Envelope's child elements. c = [ E for E in _children(self.envelope) if E.nodeType == _Node.ELEMENT_NODE ] if len(c) == 0: raise ParseException("Envelope is empty (no Body)", 0) # Envelope's first child might be the header; if so, nip it off. elt = c[0] if elt.localName == "Header" \ and elt.namespaceURI == SOAP.ENV: self._check_for_legal_children("Header", elt) self._check_for_pi_nodes(_children(elt), 1) self.header = c.pop(0) self.header_elements = _child_elements(self.header) else: self.header, self.header_elements = None, [] # Now the first child must be the body if len(c) == 0: raise ParseException("Envelope has header but no Body", 0) elt = c.pop(0) if elt.localName != "Body" \ or elt.namespaceURI != SOAP.ENV: if self.header: raise ParseException('Header followed by "' + \ elt.localName + \ '" element, not Body', 0, elt, self.dom) else: raise ParseException('Document has "' + \ elt.localName + \ '" element, not Body', 0, elt, self.dom) self._check_for_legal_children("Body", elt, 0) self._check_for_pi_nodes(_children(elt), 0) self.body = elt if not _valid_encoding(self.body): raise ParseException("Body has invalid encoding", 0) # Trailer elements. if not self.trailers: if len(c): raise ParseException("Element found after Body", 0, elt, self.dom) # Don't set self.trailer_elements = []; if user didn't ask # for trailers we *want* to throw an exception. else: self.trailer_elements = c for elt in self.trailer_elements: if not elt.namespaceURI: raise ParseException('Unqualified trailer element', 0, elt, self.dom) # Find the serialization root. Divide the Body children into # root (root=1), no (root=0), maybe (no root attribute). self.body_root, no, maybe = None, [], [] for elt in _child_elements(self.body): root = _find_root(elt) if root == "1": if self.body_root: raise ParseException("Multiple seralization roots found", 0, elt, self.dom) self.body_root = elt elif root == "0": no.append(elt) elif not root: maybe.append(elt) else: raise ParseException('Illegal value for root attribute', 0, elt, self.dom) # If we didn't find a root, get the first one that didn't # say "not me", unless they all said "not me." if self.body_root is None: if len(maybe): self.body_root = maybe[0] else: raise ParseException('No serialization root found', 0, self.body, self.dom) if not _valid_encoding(self.body_root): raise ParseException("Invalid encoding", 0, elt, self.dom) # Now get all the non-roots (in order!). rootid = id(self.body_root) self.data_elements = [ E for E in _child_elements(self.body) if id(E) != rootid ] self._check_for_pi_nodes(self.data_elements, 0)
def __init__( self, input, readerclass=None, keepdom=False, trailers=False, resolver=None, envelope=True, **kw ): '''Initialize. Keyword arguments: trailers -- allow trailer elments (default is zero) resolver -- function (bound method) to resolve URI's readerclass -- factory class to create a reader keepdom -- do not release the DOM envelope -- look for a SOAP envelope. ''' self.readerclass = readerclass self.keepdom = keepdom if not self.readerclass: self.readerclass = self.defaultReaderClass try: self.reader = self.readerclass() if type(input) in _stringtypes: self.dom = self.reader.fromString(input) else: self.dom = self.reader.fromStream(input) except Exception: # Is this in the header? Your guess is as good as mine. # raise ParseException("Can't parse document (" + \ # str(e.__class__) + "): " + str(e), 0) raise self.ns_cache = {id(self.dom): {'xml': XMLNS.XML, 'xmlns': XMLNS.BASE, '': ''}} (self.trailers, self.resolver, self.id_cache) = (trailers, resolver, {}) # Exactly one child element c = [E for E in _children(self.dom) if E.nodeType == _Node.ELEMENT_NODE] if len(c) == 0: raise ParseException('Document has no Envelope', 0) if len(c) != 1: raise ParseException('Document has extra child elements', 0) if envelope is False: self.body_root = c[0] return # And that one child must be the Envelope elt = c[0] if elt.localName != 'Envelope' or elt.namespaceURI not in (SOAP.ENV, SOAP.ENV12): raise ParseException('Document has %r element, not %s' % ((elt.namespaceURI, elt.localName), (SOAP.ENV12, 'Envelope')), 0) self._check_for_legal_children('Envelope', elt) for a in _attrs(elt): name = a.nodeName if name.find(':') == -1 and name not in ['xmlns', 'id']: raise ParseException('Unqualified attribute "' + name + '" in Envelope', 0) self.envelope = elt if not _valid_encoding(self.envelope): raise ParseException('Envelope has invalid encoding', 0) # Get Envelope's child elements. c = [E for E in _children(self.envelope) if E.nodeType == _Node.ELEMENT_NODE] if len(c) == 0: raise ParseException('Envelope is empty (no Body)', 0) # Envelope's first child might be the header; if so, nip it off. elt = c[0] if elt.localName == 'Header' and elt.namespaceURI in (SOAP.ENV, SOAP.ENV12): self._check_for_legal_children('Header', elt) self._check_for_pi_nodes(_children(elt), 1) self.header = c.pop(0) self.header_elements = _child_elements(self.header) else: (self.header, self.header_elements) = (None, []) # Now the first child must be the body if len(c) == 0: raise ParseException('Envelope has header but no Body', 0) elt = c.pop(0) if elt.localName != 'Body' or elt.namespaceURI not in (SOAP.ENV, SOAP.ENV12): if self.header: raise ParseException('Header followed by "%r" element, not Body' % ((elt.namespaceURI, elt.localName),), 0, elt, self.dom) else: raise ParseException('Document has "%r element, not Body' % ((elt.namespaceURI, elt.localName),), 0, elt, self.dom) self._check_for_legal_children('Body', elt, 0) self._check_for_pi_nodes(_children(elt), 0) self.body = elt if not _valid_encoding(self.body): raise ParseException('Body has invalid encoding', 0) # Trailer elements. if not self.trailers: if len(c): raise ParseException('Element found after Body', 0, elt, self.dom) else: # Don't set self.trailer_elements = []; if user didn't ask # for trailers we *want* to throw an exception. self.trailer_elements = c for elt in self.trailer_elements: if not elt.namespaceURI: raise ParseException('Unqualified trailer element', 0, elt, self.dom) # Find the serialization root. Divide the Body children into # root (root=1), no (root=0), maybe (no root attribute). (self.body_root, no, maybe) = (None, [], []) for elt in _child_elements(self.body): root = _find_root(elt) if root == '1': if self.body_root: raise ParseException('Multiple seralization roots found' , 0, elt, self.dom) self.body_root = elt elif root == '0': no.append(elt) elif not root: maybe.append(elt) else: raise ParseException('Illegal value for root attribute' , 0, elt, self.dom) # If we didn't find a root, get the first one that didn't # say "not me", unless they all said "not me." if self.body_root is None: if len(maybe): self.body_root = maybe[0] else: raise ParseException('No serialization root found', 0, self.body, self.dom) if not _valid_encoding(self.body_root): raise ParseException('Invalid encoding', 0, elt, self.dom) # Now get all the non-roots (in order!). rootid = id(self.body_root) self.data_elements = [E for E in _child_elements(self.body) if id(E) != rootid] self._check_for_pi_nodes(self.data_elements, 0)
def __init__(self, input, readerclass=None, keepdom=False, trailers=False, resolver=None, envelope=True, **kw): """Initialize. Keyword arguments: trailers -- allow trailer elments (default is zero) resolver -- function (bound method) to resolve URI's readerclass -- factory class to create a reader keepdom -- do not release the DOM envelope -- look for a SOAP envelope. """ self.readerclass = readerclass self.keepdom = keepdom if not self.readerclass: if self.defaultReaderClass != None: self.readerclass = self.defaultReaderClass else: from xml.dom.ext.reader import PyExpat self.readerclass = PyExpat.Reader try: self.reader = self.readerclass() if type(input) in _stringtypes: self.dom = self.reader.fromString(input) else: self.dom = self.reader.fromStream(input) except Exception as e: # Is this in the header? Your guess is as good as mine. # raise ParseException("Can't parse document (" + \ # str(e.__class__) + "): " + str(e), 0) raise self.ns_cache = {id(self.dom): {"xml": XMLNS.XML, "xmlns": XMLNS.BASE, "": ""}} self.trailers, self.resolver, self.id_cache = trailers, resolver, {} # Exactly one child element c = [E for E in _children(self.dom) if E.nodeType == _Node.ELEMENT_NODE] if len(c) == 0: raise ParseException("Document has no Envelope", 0) if len(c) != 1: raise ParseException("Document has extra child elements", 0) if envelope is False: self.body_root = c[0] return # And that one child must be the Envelope elt = c[0] if elt.localName != "Envelope" or elt.namespaceURI != SOAP.ENV: raise ParseException('Document has "' + elt.localName + '" element, not Envelope', 0) self._check_for_legal_children("Envelope", elt) for a in _attrs(elt): name = a.nodeName if name.find(":") == -1 and name not in ["xmlns", "id"]: raise ParseException('Unqualified attribute "' + name + '" in Envelope', 0) self.envelope = elt if not _valid_encoding(self.envelope): raise ParseException("Envelope has invalid encoding", 0) # Get Envelope's child elements. c = [E for E in _children(self.envelope) if E.nodeType == _Node.ELEMENT_NODE] if len(c) == 0: raise ParseException("Envelope is empty (no Body)", 0) # Envelope's first child might be the header; if so, nip it off. elt = c[0] if elt.localName == "Header" and elt.namespaceURI == SOAP.ENV: self._check_for_legal_children("Header", elt) self._check_for_pi_nodes(_children(elt), 1) self.header = c.pop(0) self.header_elements = _child_elements(self.header) else: self.header, self.header_elements = None, [] # Now the first child must be the body if len(c) == 0: raise ParseException("Envelope has header but no Body", 0) elt = c.pop(0) if elt.localName != "Body" or elt.namespaceURI != SOAP.ENV: if self.header: raise ParseException('Header followed by "' + elt.localName + '" element, not Body', 0, elt, self.dom) else: raise ParseException('Document has "' + elt.localName + '" element, not Body', 0, elt, self.dom) self._check_for_legal_children("Body", elt, 0) self._check_for_pi_nodes(_children(elt), 0) self.body = elt if not _valid_encoding(self.body): raise ParseException("Body has invalid encoding", 0) # Trailer elements. if not self.trailers: if len(c): raise ParseException("Element found after Body", 0, elt, self.dom) # Don't set self.trailer_elements = []; if user didn't ask # for trailers we *want* to throw an exception. else: self.trailer_elements = c for elt in self.trailer_elements: if not elt.namespaceURI: raise ParseException("Unqualified trailer element", 0, elt, self.dom) # Find the serialization root. Divide the Body children into # root (root=1), no (root=0), maybe (no root attribute). self.body_root, no, maybe = None, [], [] for elt in _child_elements(self.body): root = _find_root(elt) if root == "1": if self.body_root: raise ParseException("Multiple seralization roots found", 0, elt, self.dom) self.body_root = elt elif root == "0": no.append(elt) elif not root: maybe.append(elt) else: raise ParseException("Illegal value for root attribute", 0, elt, self.dom) # If we didn't find a root, get the first one that didn't # say "not me", unless they all said "not me." if self.body_root is None: if len(maybe): self.body_root = maybe[0] else: raise ParseException("No serialization root found", 0, self.body, self.dom) if not _valid_encoding(self.body_root): raise ParseException("Invalid encoding", 0, elt, self.dom) # Now get all the non-roots (in order!). rootid = id(self.body_root) self.data_elements = [E for E in _child_elements(self.body) if id(E) != rootid] self._check_for_pi_nodes(self.data_elements, 0)
def _do_element(self, node, initial_other_attrs = []): '''_do_element(self, node, initial_other_attrs = []) -> None Process an element (and its children).''' # Get state (from the stack) make local copies. # ns_parent -- NS declarations in parent # ns_rendered -- NS nodes rendered by ancestors # xml_attrs -- Attributes in XML namespace from parent # ns_local -- NS declarations relevant to this element ns_parent, ns_rendered, xml_attrs = \ self.state[0], self.state[1][:], self.state[2][:] ns_local = ns_parent.copy() # Divide attributes into NS, XML, and others. other_attrs = initial_other_attrs[:] in_subset = _in_subset(self.subset, node) for a in _attrs(node): if a.namespaceURI == XMLNS.BASE: n = a.nodeName if n == "xmlns:": n = "xmlns" # DOM bug workaround ns_local[n] = a.nodeValue elif a.namespaceURI == XMLNS.XML: if self.unsuppressedPrefixes is None or in_subset: xml_attrs.append(a) else: other_attrs.append(a) # Render the node W, name = self.write, None if in_subset: name = node.nodeName W('<') W(name) # Create list of NS attributes to render. ns_to_render = [] for n,v in ns_local.items(): pval = ns_parent.get(n) # If default namespace is XMLNS.BASE or empty, skip if n == "xmlns" \ and v in [ XMLNS.BASE, '' ] and pval in [ XMLNS.BASE, '' ]: continue # "omit namespace node with local name xml, which defines # the xml prefix, if its string value is # http://www.w3.org/XML/1998/namespace." if n == "xmlns:xml" \ and v in [ 'http://www.w3.org/XML/1998/namespace' ]: continue # If different from parent, or parent didn't render # and if not exclusive, or this prefix is needed or # not suppressed if (v != pval or n not in ns_rendered) \ and (self.unsuppressedPrefixes is None or \ _utilized(n, node, other_attrs, self.unsuppressedPrefixes)): ns_to_render.append((n, v)) # Sort and render the ns, marking what was rendered. ns_to_render.sort(_sorter_ns) for n,v in ns_to_render: self._do_attr(n, v) ns_rendered.append(n) # Add in the XML attributes (don't pass to children, since # we're rendering them), sort, and render. other_attrs.extend(xml_attrs) xml_attrs = [] other_attrs.sort(_sorter) for a in other_attrs: self._do_attr(a.nodeName, a.value) W('>') # Push state, recurse, pop state. state, self.state = self.state, (ns_local, ns_rendered, xml_attrs) for c in _children(node): _implementation.handlers[c.nodeType](self, c) self.state = state if name: W('</%s>' % name)