From: Sunil Mishra
Subject: Announcing XMLP: Yet Another Lisp XML Toolkit
Date: 
Message-ID: <3AFED87C.2070708@stop.smap.com>
              Announcing XMLP: Yet Another Lisp XML Toolkit

I have finally finished work on an alpha version of XMLP, a toolkit
for processing XML documents. Given that it relies on foreign bindings
to the expat parser, it is limited to Lispworks 4.1 and Allegro CL
5.0.1 running on Unix platforms. [1] XMLP features:

* A true tree structured representation of the XML document, with
    structures to represent everything, including namespaces, names,
    elements, attributes, etc.

* A reader macro that is capable of translating an s-expression form
    of the document representation into the underlying object tree. It
    does for XML what the backquote does for lists.

* A printer for pretty printing XML documents.

* An expander for generating lisp forms that upon evaluation produce
    an equivalent XML document.

* A simple rule engine for manipulating XML data structures, expressed
    through the same #m macro.

* A set of defined tags that operate through the rule engine to
    provide a set of operations for use in a source XML document. [2]

I invite users and developers to download, install and experiment with
the current version of XMLP. The project is hosted at SourceForge:

Home page:      http://lsp.sourceforge.net (nothing here yet)
Project page:   http://www.sourceforge.net/projects/lsp

                           --------------------
                              Some Examples

*** Simple name construction:

  > '#m"foo:bar"
(NS-INTERN "bar" #<XMLNS NS002 (foo)>)

  > #m"foo:bar"
#m"foo:bar"

*** XML document construction. Note that #0m quotes its content, while
      #m evaluates it.

  > '#m(foo:foo1 (foo:a1 10 a2 20 bar:a1 30)
        "Some random string."
        '(this is an s-expression)
        (list 1 2 3 4 5)
        #0m(bar:bar1 (foo:a1 10 a1 30) (subseq "A child." 0 4))
        #m(bar:bar2 () 5))
(MAKE-ELEMENT-NODE
   (NS-INTERN "foo1" #<XMLNS NS002 (foo)>)
   (LIST (MAKE-ATTRIBUTE-NODE (NS-INTERN "a1" #<XMLNS NS002 (foo)>) 10)
         (MAKE-ATTRIBUTE-NODE (NS-INTERN "a2" #<XMLNS NS002 (foo)>) 20)
         (MAKE-ATTRIBUTE-NODE (NS-INTERN "a1" #<XMLNS NS003 (bar)>) 30))
   (LIST (MAKE-TEXT-NODE "Some random string.")
         (MAKE-TEXT-NODE '(THIS IS AN S-EXPRESSION))
         (MAKE-TEXT-NODE (LIST 1 2 3 4 5))
         (MAKE-ELEMENT-NODE
          (NS-INTERN "bar1" #<XMLNS NS003 (bar)>)
          (LIST (MAKE-ATTRIBUTE-NODE
                 (NS-INTERN "a1" #<XMLNS NS002 (foo)>) 10)
                (MAKE-ATTRIBUTE-NODE
                 (NS-INTERN "a1" #<XMLNS NS003 (bar)>) 30))
          (LIST (MAKE-TEXT-NODE '(SUBSEQ "A child." 0 4))))
         (MAKE-ELEMENT-NODE (NS-INTERN "bar2" #<XMLNS NS003 (bar)>)
                            (LIST)
                            (LIST (MAKE-TEXT-NODE 5)))))

  > #m(foo:foo1 (foo:a1 10 a2 20 bar:a1 30)
       "Some random string."
       '(this is an s-expression)
       (list 1 2 3 4 5)
       #0m(bar:bar1 (foo:a1 10 a1 30) (subseq "A child." 0 4))
       #m(bar:bar2 () 5))
#0m(foo:foo1 (a1 10 a2 20 bar:a1 30)
      "Some random string."
      (THIS IS AN S-EXPRESSION)
      (1 2 3 4 5)
      #0m(bar:bar1 (foo:a1 10 a1 30) (SUBSEQ "A child." 0 4))
      #0m(bar:bar2 () 5))

*** Processing through the XMLP package. We would never actually want
      to use the XMLP package like this, but imagine this document has
      been read in from a file. Otherwise, it makes far more sense to
      explicitly write Lisp functions for doing this kind of
      processing. The key is that XMLP uniformly supports both
      approaches.

  > (transform-print
     #0m(html:table ()
         #0m(xmlp:eval ()
             (defvar *colors* #(blue green red))
             (defparameter *current-color* 0)
             (defparameter *row-counter* 0))
         #0m(html:tr (xmlp:function "make-one-row"
                      xmlp:arguments "(data)"
                      xmlp:scope "global")
             #0m(html:td () #0m(xmlp:print () "(incf *row-counter*)"))
             #0m(html:td () #0m(xmlp:print () "data")))
         #0m(xmlp:function
             (xmlp:name "make-row-group"
              xmlp:arguments "(&rest dlist)")
             #0m(xmlp:print ()
                 (loop for data in dlist
                       nconc (make-one-row data))))
         #0m(xmlp:print
             (xmlp:print `((,#m"html:background"
                            ,(aref *colors* *current-color*))))
             (progn
               (setq *current-color*
                     (mod (incf *current-color*) (length *colors*)))
               (make-row-group "data11" "data12"))
             (progn
               (setq *current-color*
                     (mod (incf *current-color*) (length *colors*)))
               (make-row-group "data21" "data22" "data23"))
             (progn
               (setq *current-color*
                     (mod (incf *current-color*) (length *colors*)))
               (make-row-group "data31"))
             (progn
               (setq *current-color*
                     (mod (incf *current-color*) (length *colors*)))
               (make-row-group "data41"))))
<table xmlns="html:">

    <tr background="GREEN"><td>1</td><td>data11</td></tr>
    <tr background="GREEN"><td>2</td><td>data12</td></tr>
    <tr background="RED"><td>3</td><td>data21</td></tr>
    <tr background="RED"><td>4</td><td>data22</td></tr>
    <tr background="RED"><td>5</td><td>data23</td></tr>
    <tr background="BLUE"><td>6</td><td>data31</td></tr>
    <tr background="GREEN"><td>7</td><td>data41</td></tr>
</table>

                           --------------------
                             A Vague Roadmap

In time, XMLP will feature support for a full set of DOM (or DOM-like)
operations. For the immediate future, however, work has begun on XLSP,
a replacement for LSP that is capable of operating on XML documents
and generate XML and HTML documents from XML source.

--------------------
Footnotes:

[1] With a little work, it should also run on Windows and Allegro CL
      6.0, and the expat parser is replaceable with a pure CL event
      based parser that operates as expat does.

[2] For those who remember LSP, the last package I was involved in
      releasing, these tags provide much of the power of LSP for
      processing XML documents. Their implementation through rules makes
      the software design immensely more modular.