Walking objects
In the previous chapter, we built an STP object tree in memory. Let's make another STP document and keep it in a variable:CL-USER> (setf *doc* (let* ((elt (stp:make-element "elt")) (doc (stp:make-document elt)) (txt (stp:make-text "foo"))) (stp:append-child elt txt) doc))
#.(CXML-STP:ELEMENT #| :PARENT of type DOCUMENT |# :CHILDREN '(#.(CXML-STP:TEXT #| :PARENT of type ELEMENT |# :DATA "foo")) :LOCAL-NAME "elt")
stp:serialize gives us the SAX events corresponding to a walk over that in-memory document:
CL-USER> (stp:serialize *doc* nil)
0: (SAX:START-DOCUMENT NIL) 0: (SAX:START-ELEMENT NIL "" "elt" "elt" NIL) 0: (SAX:CHARACTERS NIL "foo") 0: (SAX:END-ELEMENT NIL "" "elt" "elt") 0: (SAX:END-DOCUMENT NIL) 0: returned NIL NIL
Imagine the possibilities!
For instance, let's send that to our tostring2 handler:
CL-USER> (stp:serialize *doc* (make-instance 'tostring2))
"foo"
Works!
Let's build an STP document from an STP document:
CL-USER> (stp:serialize *doc* (stp:make-builder))
#.(CXML-STP-IMPL::DOCUMENT :CHILDREN '(#.(CXML-STP:ELEMENT :CHILDREN '(#.(CXML-STP:TEXT :DATA "bar")) :LOCAL-NAME "foo")))
It's a round-trip! Okay, that's boring in this case, but the technique is clearly powerful in principle.