Update of /project/cl-soap/cvsroot/cl-soap/src In directory common-lisp.net:/tmp/cvs-serv3468/src
Modified Files: lxml.lisp wsdl.lisp xsd.lisp Log Message: basic integration of xsd primitive type handling in wsdl-soap-call
Date: Fri Sep 16 09:51:15 2005 Author: scaekenberghe
Index: cl-soap/src/lxml.lisp diff -u cl-soap/src/lxml.lisp:1.4 cl-soap/src/lxml.lisp:1.5 --- cl-soap/src/lxml.lisp:1.4 Thu Sep 15 15:32:32 2005 +++ cl-soap/src/lxml.lisp Fri Sep 16 09:51:15 2005 @@ -1,6 +1,6 @@ ;;;; -*- mode: lisp -*- ;;;; -;;;; $Id: lxml.lisp,v 1.4 2005/09/15 13:32:32 scaekenberghe Exp $ +;;;; $Id: lxml.lisp,v 1.5 2005/09/16 07:51:15 scaekenberghe Exp $ ;;;; ;;;; Some tools to manipulate lxml ;;;; @@ -13,6 +13,8 @@
(in-package :cl-soap)
+;;; external + (defun lxml-get-tag (lxml) "Return the XML tag symbol of the lxml XML DOM" (cond ((symbolp lxml) lxml) @@ -28,5 +30,14 @@ (defun lxml-find-tag (tag lxml) "Find a specific tag in a lxml XML DOM list" (find tag lxml :key #'lxml-get-tag)) + +;;; internal + +(defun actual-name (qname) + "For now we ignore prefixes ;-)" + (multiple-value-bind (prefix identifier) + (s-xml:split-identifier qname) + (declare (ignore prefix)) + identifier))
;;;; eof
Index: cl-soap/src/wsdl.lisp diff -u cl-soap/src/wsdl.lisp:1.6 cl-soap/src/wsdl.lisp:1.7 --- cl-soap/src/wsdl.lisp:1.6 Thu Sep 15 15:37:34 2005 +++ cl-soap/src/wsdl.lisp Fri Sep 16 09:51:15 2005 @@ -1,6 +1,6 @@ ;;;; -*- mode: lisp -*- ;;;; -;;;; $Id: wsdl.lisp,v 1.6 2005/09/15 13:37:34 scaekenberghe Exp $ +;;;; $Id: wsdl.lisp,v 1.7 2005/09/16 07:51:15 scaekenberghe Exp $ ;;;; ;;;; The basic WSDL protocol: we parse the generic and soap specific parts ;;;; @@ -303,13 +303,6 @@
;; Interpreting the WSDL model
-(defun actual-name (qname) - "For now we ignore prefixes ;-)" - (multiple-value-bind (prefix identifier) - (s-xml:split-identifier qname) - (declare (ignore prefix)) - identifier)) - (defun find-item-named (item-name sequence) (find (actual-name item-name) sequence :test #'string-equal :key #'get-name))
@@ -436,12 +429,16 @@ (s-xml:register-namespace input-namespace-uri "ns1" :ns1) (error "The case where input and output namespaces differ is not yet supported")) (loop :for part :in (get-parts input-message) :do - (let* ((value (second (member (get-name part) input :test #'equal)))) + (let* ((value (second (member (get-name part) input :test #'equal))) + (part-type (get-type part))) (if value (push `((,(intern (get-name part) :keyword) xsi::|type| ,(get-type part)) - ,(princ-to-string value)) - actual-input-parameters) + ;; basic type conversions ;-) + ,(if (xsd-primitive-type-name-p part-type) + (lisp->xsd-primitive value (intern-xsd-type-name part-type)) + (princ-to-string value))) + actual-input-parameters) (error "No input binding found for ~a:~a" (get-name input-message) (get-name part))))) (let* ((input-wrapper (intern (get-name binding-operation) :ns1)) (result (soap-call soap-end-point @@ -456,10 +453,17 @@ (if (eql (lxml-get-tag result) output-wrapper) (progn (loop :for part :in (get-parts output-message) :do - (let ((part-element (lxml-find-tag (intern (get-name part) :keyword) (rest result)))) - ;; add type conversions ;-) - (push (rest part-element) result-values))) - (nreverse result-values)) + (let* ((part-element (lxml-find-tag (intern (get-name part) :keyword) (rest result))) + (part-value (second part-element)) + (part-type (get-type part))) ;; part-element might have a type attribute as well + ;; basic type conversions ;-) + (if (xsd-primitive-type-name-p part-type) + (push (xsd-primitive->lisp part-value (intern-xsd-type-name part-type)) + result-values) + (push part-value result-values)))) + (if (= (length result-values) 1) + (first result-values) + (nreverse result-values))) (error "Expected <~a> element" output-wrapper)))) (error "Only standard SOAP RPC style currently supported as binding")) (error "Only standard SOAP HTTP transport currently supported as binding"))))
Index: cl-soap/src/xsd.lisp diff -u cl-soap/src/xsd.lisp:1.1 cl-soap/src/xsd.lisp:1.2 --- cl-soap/src/xsd.lisp:1.1 Thu Sep 15 15:37:34 2005 +++ cl-soap/src/xsd.lisp Fri Sep 16 09:51:15 2005 @@ -1,6 +1,6 @@ ;;;; -*- mode: lisp -*- ;;;; -;;;; $Id: xsd.lisp,v 1.1 2005/09/15 13:37:34 scaekenberghe Exp $ +;;;; $Id: xsd.lisp,v 1.2 2005/09/16 07:51:15 scaekenberghe Exp $ ;;;; ;;;; A partial implementation of the XML Schema Definition standard ;;;; @@ -97,14 +97,79 @@
;;; Interpreting the XSD model
-;;; Primitive Types/Values +;;; Primitive Types/Values (types are keywords) + +(defconstant +known-primitive-type-names+ + '("string" + "normalizedString" "token" + "Name" "QName" "NCName" "anyURI" + "integer" + "positiveInteger" "negativeInteger" "nonPositiveInteger" "nonNegativeInteger" + "long" "unsignedLong" "int" "unsignedInt" "short" "unsignedShort" + "byte" "decimal" + "float" "double" + "boolean" + "duration" "date" "time" "dateTime" + "base64Binary" "hexBinary")) + +(defun xsd-primitive-type-name-p (name) + (member (actual-name name) +known-primitive-type-names+ :test #'string-equal)) + +(defun intern-xsd-type-name (name) + (intern (string-upcase (actual-name name)) :keyword))
(defun xsd-primitive->lisp (value type) - (declare (ignore type)) - value) + "Convert the XSD string value to a Common Lisp value, interpreting it as type" + ;; more work needed here ;-) + (ecase type + ((:string :normalizedString :token) + value) + ((:Name :QName :NCName :anyURI) + value) + ((:integer + :positiveInteger :negativeInteger :nonPositiveInteger :nonNegativeInteger + :long :unsignedLong :int :unsignedInt :short :unsignedShort + :byte :decimal) + (parse-integer value) 'integer) + (:float + (coerce (read-from-string value) 'float)) + (:double + (coerce (read-from-string value) 'double)) + (:boolean + (cond ((string-equal value "true") t) + ((string-equal value "false") nil) + (t (= (parse-integer value) 1)))) + (:duration value) + (:date value) + (:time value) + (:dateTime value) + ((:base64Binary :hexBinary) + (error "~a not yet supported as primitive type" type))))
(defun lisp->xsd-primitive (value type) - (declare (ignore type)) - value) + "Convert the Common Lisp value to a XSD string value, interpreting it as type" + ;; more work needed here ;-) + (ecase type + ((:string :normalizedString :token) + value) + ((:Name :QName :NCName :anyURI) + value) + ((:integer + :positiveInteger :negativeInteger :nonPositiveInteger :nonNegativeInteger + :long :unsignedLong :int :unsignedInt :short :unsignedShort + :byte :decimal) + (princ-to-string value)) + (:float + (princ-to-string value)) + (:double + (princ-to-string value)) + (:boolean + (if value "true" "false")) + (:duration value) + (:date value) + (:time value) + (:dateTime value) + ((:base64Binary :hexBinary) + (error "~a not yet supported as primitive type" type))))
;;;; eof