From: ········@gmail.com
Subject: Re: Save a class into xml file?
Date: 
Message-ID: <1167468350.911586.272530@h40g2000cwb.googlegroups.com>
·······@gmail.com wrote:
> Hello,
>
> I have a program with several structures of data with variables (ready,
> arrays,...) and I would like to write in a file xml. I would like to
> know if I cand do this job easy, without having to write much code. I
> am new in common lisp, recently I saw a video where xml directly loaded
> the classes froma a file, maybe in a video of allego cache. Somebody
> can give some link where I can obtains more information?

BKNR http://common-lisp.net/project/bknr/html/home.html has an XML
import/export package, which offers XML bindings for CLOS objects...

The video your thinking of might have been
http://franz.com/products/allegrocache/acachedemo.htm ? They generate
CLOS class definitions from an XML file... Do they actually serialize
the db? I don't remember, it's kind of long...

;Here's a quick hack

(defmacro wrap-in-tag ((stream tag-name &rest attribute-plist) &body
body)
  (let ((s (gensym))
	(n (gensym)))
    `(let ((,s ,stream)
	  (,n ,tag-name))
      (format ,s "<~A~{ ~A=\"~A\"~}>" ,n (list ,@attribute-plist))
      (progn ,@body)
      (format ,s "</~A>" ,n)
      nil)))

;(wrap-in-tag (stream "tag" "attr" "val")
;  (format t "text"))
;
; expands to:
;
;(LET ((#:G11006 STREAM) (#:G11007 "tag"))
;  (FORMAT #:G11006 "<~A~{ ~A=\"~A\"~}>" #:G11007 (LIST "attr" "val"))
;  (PROGN (FORMAT STREAM "text"))
;  (FORMAT #:G11006 "</~A>" #:G11007) NIL)
;
; prints to STREAM:
;
;"<tag attr=\"val\">text</tag>"
;
; returns:
;
;NIL

(defgeneric render-slots (instance &optional stream)
  (:method-combination progn))

(defmacro make-render-method (class-name slot-names)
  `(defmethod render-slots progn ((x ,class-name) &optional (stream t))
      (dolist (s ',slot-names)
	(format stream "~%  ")
	(wrap-in-tag (stream "slot" "name" (string s))
	   (prin1 (slot-value x s) stream)))))

(defun render (instance &optional (stream t))
  (wrap-in-tag (stream "instance" "class" (string (type-of instance)))
     (render-slots instance stream)
     (terpri stream)))




;now in use:

(defclass foo ()
  ((foo-slot :initarg :foo-slot)))

(defclass bar (foo)
  ((bar-slot :initarg :bar-slot)))

(defclass baz (bar)
  ((baz-slot :initarg :baz-slot)))

(make-render-method foo (foo-slot))
(make-render-method bar (bar-slot))
(make-render-method baz (baz-slot))

(setf x (make-instance 'baz
		       :foo-slot 1
		       :bar-slot 2
		       :baz-slot 3))

(render x)


#|

prints:

<instance class="BAZ">
  <slot name="BAZ-SLOT">3</slot>
  <slot name="BAR-SLOT">2</slot>
  <slot name="FOO-SLOT">1</slot>
</instance>

of course none of the resultant text is gauranteed to be XML safe... or
printed in such a way... also remember about symbol packages and how
they read...

still, though, as you can see, this wouldn't be that big of a deal to
do it right...

if you are using an implementation with MOP you could use the CLASS-
functions
http://www.franz.com/support/documentation/8.0/doc/mop/dictionary.html#class-
to make a RENDER fn that fishes out all the class info of an instance
by itself so you don't have to do a MAKE-RENDER-METHOD by hand for
every class...

hth, take care

Nick

|#




> 
> 
> Bye
> 
> Elizabeth.