[cxml-cvs] CVS cxml/xml

dlichteblau dlichteblau at common-lisp.net
Tue May 1 20:07:01 UTC 2007


Update of /project/cxml/cvsroot/cxml/xml
In directory clnet:/tmp/cvs-serv10936/xml

Modified Files:
	package.lisp unparse.lisp 
Log Message:
Added new functions attribute*, unparse-attribute, and macro with-element*,
with-namespace* to the SAX generation wrapper API.


--- /project/cxml/cvsroot/cxml/xml/package.lisp	2007/04/22 13:23:55	1.15
+++ /project/cxml/cvsroot/cxml/xml/package.lisp	2007/05/01 20:07:00	1.16
@@ -50,8 +50,12 @@
    #:make-character-stream-sink/utf8
 
    #:with-xml-output
+   #:with-namespace
    #:with-element
+   #:with-element*
    #:attribute
+   #:attribute*
+   #:unparse-attribute
    #:cdata
    #:text
 
--- /project/cxml/cvsroot/cxml/xml/unparse.lisp	2006/12/02 13:21:37	1.12
+++ /project/cxml/cvsroot/cxml/xml/unparse.lisp	2007/05/01 20:07:00	1.13
@@ -509,13 +509,17 @@
 
 (defvar *current-element*)
 (defvar *sink*)
+(defvar *unparse-namespace-bindings*)
+(defvar *current-namespace-bindings*)
 
 (defmacro with-xml-output (sink &body body)
   `(invoke-with-xml-output (lambda () , at body) ,sink))
 
 (defun invoke-with-xml-output (fn sink)
   (let ((*sink* sink)
-        (*current-element* nil))
+        (*current-element* nil)
+	(*unparse-namespace-bindings* *initial-namespace-bindings*)
+	(*current-namespace-bindings* nil))
     (sax:start-document *sink*)
     (funcall fn)
     (sax:end-document *sink*)))
@@ -523,37 +527,86 @@
 (defmacro with-element (qname &body body)
   `(invoke-with-element (lambda () , at body) ,qname))
 
+(defmacro with-element* ((prefix lname) &body body)
+  `(invoke-with-element* (lambda () , at body) ,prefix ,lname))
+
+(defmacro with-namespace ((prefix uri) &body body)
+  `(invoke-with-namespace (lambda () , at body) ,prefix ,uri))
+
 (defun maybe-emit-start-tag ()
   (when *current-element*
     ;; starting child node, need to emit opening tag of parent first:
-    (destructuring-bind (qname &rest attributes) *current-element*
-      (sax:start-element *sink* nil nil qname (reverse attributes)))
+    (destructuring-bind ((uri lname qname) &rest attributes) *current-element*
+      (sax:start-element *sink* uri lname qname (reverse attributes)))
     (setf *current-element* nil)))
 
+(defun invoke-with-namespace (fn prefix uri)
+  (let ((*unparse-namespace-bindings*
+	 (acons prefix uri *unparse-namespace-bindings*))
+	(*current-namespace-bindings*
+	 (acons prefix uri *current-namespace-bindings*)))
+    (sax:start-prefix-mapping *sink* prefix uri)
+    (multiple-value-prog1
+	(funcall fn)
+      (sax:end-prefix-mapping *sink* prefix))))
+
 (defun invoke-with-element (fn qname)
   (setf qname (rod qname))
+  (multiple-value-bind (prefix lname)
+      (split-qname qname)
+    (invoke-with-element* fn prefix lname qname)))
+
+(defun find-unparse-namespace (prefix)
+  (cdr (assoc prefix *unparse-namespace-bindings* :test 'equal)))
+
+(defun invoke-with-element* (fn prefix lname &optional qname)
+  (setf prefix (when prefix (rod prefix)))
+  (setf lname (rod lname))
   (maybe-emit-start-tag)
-  (let ((*current-element* (list qname)))
+  (let* ((qname (or qname
+		    (if prefix (concatenate 'rod prefix #":" lname) lname)))
+	 (uri (find-unparse-namespace (or prefix #"")))
+	 (*current-element*
+	  (cons (list uri lname qname)
+		(mapcar (lambda (x)
+			  (destructuring-bind (prefix &rest uri) x
+			    (sax:make-attribute
+			     :namespace-uri #"http://www.w3.org/2000/xmlns/"
+			     :local-name prefix
+			     :qname (if (zerop (length prefix))
+					#"xmlns"
+					(concatenate 'rod #"xmlns:" prefix))
+			     :value uri)))
+			*current-namespace-bindings*))))
     (multiple-value-prog1
-        (funcall fn)
+        (let ((*current-namespace-bindings* nil))
+	  (funcall fn))
       (maybe-emit-start-tag)
-      (sax:end-element *sink* nil nil qname))))
+      (sax:end-element *sink* uri lname qname))))
 
-(defun attribute-1 (name value)
-  (push (sax:make-attribute :qname (rod name) :value (rod value))
-        (cdr *current-element*))
-  value)
+(defgeneric unparse-attribute (value))
+(defmethod unparse-attribute ((value string)) value)
+(defmethod unparse-attribute ((value null)) nil)
+(defmethod unparse-attribute ((value integer)) (write-to-string value))
 
-(defgeneric attribute (name value))
-
-(defmethod attribute (name (value string))
-  (attribute-1 name value))
-
-(defmethod attribute (name (value null))
-  (declare (ignore name)))
-
-(defmethod attribute (name (value integer))
-  (attribute-1 name (write-to-string value)))
+(defun attribute (qname value)
+  (setf qname (rod qname))
+  (multiple-value-bind (prefix lname)
+      (split-qname qname)
+    (attribute* prefix lname value qname)))
+
+(defun attribute* (prefix lname value &optional qname)
+  (setf value (unparse-attribute value))
+  (when value
+    (setf prefix (when prefix (rod prefix)))
+    (setf lname (rod lname))
+    (push (sax:make-attribute
+	   :namespace-uri (find-unparse-namespace prefix)
+	   :local-name lname
+	   :qname (or qname
+		      (if prefix (concatenate 'rod prefix #":" lname) lname))
+	   :value (rod value))
+	  (cdr *current-element*))))
 
 (defun cdata (data)
   (maybe-emit-start-tag)




More information about the Cxml-cvs mailing list