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.