2007-07-28

Macros for XSLT

Gary King is confused because [XSLT] seems so ridiculously verbose. Others have already suggested mad higher-order function tricks using XSLT 2.0.

My solution: Macros. If XSLT lacks an element to do what you want (creating a text node with a newline, in Gary's case), just invent the feature you need and send your XSLT stylesheet through another XSLT stylesheet to implement it.

BR

Say you have demo.xsl which wants to use
  <x:br/>

to emit a newline. (In this example, `x' is simply the namespace for our extensions.) Write an additional stylesheet macros.xsl and send the original demo.xsl through the macro stylesheet to generate the actual XSLT source code. A macro template for <x:br> would be as simple as:
  <xsl:template match="x:br">
    <_xsl:text><xsl:text>&#10;</xsl:text></_xsl:text>
  </xsl:template>
In the macro stylesheet, xsl is the namespace of the "macro definition" and _xsl is the namespace of the "macro expansion". (If you care about details, the trick is to use xsl:namespace-alias to make the XSLT processor believe they are different namespaces.)

DOTIMES

For a more interesting example of macro use, suppose we want to repeat our code count times. Doing this kind of iteration involves a recursive template call, which we want to hide. We will define a macro <x:dotimes> that can be used like this:
  <x:dotimes var="i" count="3">
    <xsl:value-of select="$i"/>
  </x:dotimes>
Our macro stylesheet replaces each use of <x:dotimes> with a template call, and adds a recursive template as a top-level element:
  <xsl:template match="xsl:stylesheet">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
      <xsl:for-each select="//x:dotimes">
        <_xsl:template name="x:dotimes_{generate-id()}">
          ... recursive template definition here ...
        </_xsl:template>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="x:dotimes">
    <_xsl:call-template name="x:dotimes_{generate-id()}">
      ... parameters elided for brevity ...
    </_xsl:call-template>
  </xsl:template>
Download the full macros.xsl and demo.xsl to try the example. To run it with xsltproc, use the Makefile in the same directory.

2007-07-01

There's exactly one way to do it

XOM is a DOM alternative written in Java and for Java -- in contrast to DOM, which feels wrong in almost every language.

Key phrases:
  • "Comatose lists"
  • This is a cathedral, not a bazaar
  • There's exactly one way to do it
  • The Wrong Side of 80/20

Lots of good ideas waiting to be stolen. Stay tuned for a Common Lisp adaptation.