Function: soap-decode-xs-complex-type
soap-decode-xs-complex-type is a byte-compiled function defined in
soap-client.el.gz.
Signature
(soap-decode-xs-complex-type TYPE NODE)
Documentation
Use TYPE, a soap-xs-complex-type, to decode the contents of NODE.
A LISP value is returned based on the contents of NODE and the type-info stored in TYPE.
This is a specialization of soap-decode-type for
soap-xs-basic-type objects.
Source Code
;; Defined in /usr/src/emacs/lisp/net/soap-client.el.gz
(defun soap-decode-xs-complex-type (type node)
"Use TYPE, a `soap-xs-complex-type', to decode the contents of NODE.
A LISP value is returned based on the contents of NODE and the
type-info stored in TYPE.
This is a specialization of `soap-decode-type' for
`soap-xs-basic-type' objects."
(cl-case (soap-xs-complex-type-indicator type)
(array
(let ((result nil)
(element-type (soap-xs-complex-type-base type)))
(dolist (node (xml-node-children node))
(when (consp node)
(push (soap-decode-type element-type node) result)))
(nreverse result)))
((sequence choice all nil)
(let ((result nil)
(base (soap-xs-complex-type-base type)))
(when base
(setq result (nreverse (soap-decode-type base node))))
(catch 'done
(dolist (element (soap-xs-complex-type-elements type))
(let* ((instance-count 0)
(e-name (soap-xs-element-name element))
;; Heuristic: guess if we need to decode using local
;; namespaces.
(use-fq-names (string-match ":" (symbol-name (car node))))
(children (if e-name
(if use-fq-names
;; Find relevant children
;; using local namespaces by
;; searching for the element's
;; fully-qualified name.
(soap-xml-get-children-fq
node
(soap-xs-element-get-fq-name
element soap-current-wsdl))
;; No local namespace resolution
;; needed so use the element's
;; name unqualified.
(xml-get-children node (intern e-name)))
;; e-name is nil so a) we don't know which
;; children to operate on, and b) we want to
;; reuse soap-decode-xs-complex-type, which
;; expects a node argument with a complex
;; type; therefore we need to operate on the
;; entire node. We wrap node in a list so
;; that it will carry through as "node" in the
;; loop below.
;;
;; For example:
;;
;; Element Type:
;; <xs:complexType name="A">
;; <xs:sequence>
;; <xs:element name="B" type="t:BType"/>
;; <xs:choice>
;; <xs:element name="C" type="xs:string"/>
;; <xs:element name="D" type="t:DType"/>
;; </xs:choice>
;; </xs:sequence>
;; </xs:complexType>
;;
;; Node:
;; <t:A>
;; <t:B tag="b"/>
;; <t:C>1</C>
;; </t:A>
;;
;; soap-decode-type will be called below with:
;;
;; element =
;; <xs:choice>
;; <xs:element name="C" type="xs:string"/>
;; <xs:element name="D" type="t:DType"/>
;; </xs:choice>
;; node =
;; <t:A>
;; <t:B tag="b"/>
;; <t:C>1</C>
;; </t:A>
(list node)))
(element-type (soap-xs-element-type element)))
(dolist (node children)
(incf instance-count)
(let* ((attributes
(soap-decode-xs-attributes element-type node))
;; Attributes may specify xsi:type override.
(element-type
(if (soap-xml-get-attribute-or-nil1 node 'xsi:type)
(soap-wsdl-get
(soap-l2fq
(soap-xml-get-attribute-or-nil1 node
'xsi:type))
soap-current-wsdl 'soap-xs-type-p t)
element-type))
(decoded-child (soap-decode-type element-type node)))
(if e-name
(push (cons (intern e-name)
(append attributes decoded-child)) result)
;; When e-name is nil we don't want to introduce an extra
;; level of nesting, so we splice the decoding into
;; result.
(setq result (append decoded-child result)))))
(cond ((and (eq (soap-xs-complex-type-indicator type) 'choice)
;; Choices can allow multiple values.
(not (soap-xs-complex-type-multiple-p type))
(> instance-count 0))
;; This was a choice node, and we decoded one value.
(throw 'done t))
;; Do some sanity checking
((and (not (eq (soap-xs-complex-type-indicator type)
'choice))
(= instance-count 0)
(not (soap-xs-element-optional? element))
(and (soap-xs-complex-type-p element-type)
(not (soap-xs-complex-type-optional-p
element-type))))
(soap-warning "missing non-nillable slot %s" e-name))
((and (> instance-count 1)
(not (soap-xs-complex-type-multiple-p type))
(not (soap-xs-element-multiple? element))
(and (soap-xs-complex-type-p element-type)
(not (soap-xs-complex-type-multiple-p
element-type))))
(soap-warning "expected single %s slot, found multiple"
e-name))))))
(nreverse result)))
(t
(error "Don't know how to decode complex type: %s"
(soap-xs-complex-type-indicator type)))))