[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Succinctness, power, XML transformations



I offer the following as an example of succinctness=power, in a system for transforming XML in Scheme.

As background, I have developed an XML toolkit, WebIt!, where XML elements are constructed via constructor functions, and attributes are created via "keyword arguments". One can write the HTML <a href="http://some-url";>something<a/> as (h4:a h4:href: "some-url" "something").

Earlier this summer I posted a note on comp.lang.scheme on a system of exogenous "macros" for transforming XML in Scheme within the context of this toolkit. With my XML macros system, I had introduced a new form, "markup", to deconstruct the contents of element, analogous to how an s-expression may be deconstructed in a Lisp-style macro. One could then write something like the following as a "macro" to transform the poem element:
   (xml-macro poem
              (markup (title: title poet: author . contents)
                      (h4:div 
                       (h4:br) (h4:strong title)
                       (h4:p) (h4:em author)
                       contents)))

As an illustration of the new "macros", I wrote a set of macros to transform a very structural representation of a "book" of poems (each tagged out into stanza and line elements) into HTML. It took 4 xml-macros equalling about 45 lines of code. (The original note, and the associated code, are on my web site: http://celtic.benderweb.net/excess/.)

Quite childishly, I was very pleased with myself at the time- after all I had provided Lisp-style macros as a facility for transforming XML. But just as the pattern matching of syntax-rules added great power to Scheme macros, so it is with processing XML. I envision a new construct, xml-rules, analogous to syntax-rules:
   (xml-rules
      (input-xml-pattern [fender-expression] output-template-expression)
      ...)

The output-template expression can be any Scheme expression, but the form
xml-template must be used to introduce pattern variables into the output
(analogous to the role of the syntax form in syntax-rules/syntax-case).

My poetry book example can now be re-written in a single macro:
   (xml-macro book
     (xml-rules
      ((_ title: bt
          (poem title: t poet: a tag: m
                (stanza (line l1) (line l) ...) ...) ...)
       (xml-template
          (h4:html
           (h4:head (h4:title bt))
           (h4:body
             (h4:h1 bt)
             (h4:p) "Table of Contents:"
             (h4:ul (h4:li (h4:a h4:href: (string-append "#" m) t)) ...)
             (h4:div (h4:p) (h4:a h4:name: m) (h4:strong t) (h4:br) (h4:em a)
                     (list (h4:p) l1 (list (h4:br) l) ...) ...) ...))))))

This macro consumes a book element, consisting of poem elements, and produces an HTML page consisting of a table of contents, linking to each poem, rendered in HTML. Like syntax-rules, xml-rules uses the ellipses to indicate repeated items in both the input and the output. This is both more concise and far more declarative, than my original attempt. In terms of "scaling up", I note as well: the XML constructor functions and keywords encapsulate XML namespace uri's, which supplies xml-rules with support of the XML namespaces both in its input pattern matching and in the output template.

This bit of engineering- pattern matching-based macros for XML- is not an especially novel idea. The above is really just the notation of Scheme's syntax-rules applied to matching XML elements. A pattern of the constructor functions for XML is used to match a tree of struct's. Equally, this is a system similar to the XT3D of Krishnamurthi et al., but given a Scheme notation (rather than XT3D's XML notation).

Jim Bender