[xsl] Side-effect and PROGN, example JDBC in XSLT

Subject: [xsl] Side-effect and PROGN, example JDBC in XSLT
From: Gunther Schadow <gunther@xxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 20 Jun 2003 01:12:02 -0500
Hi, on the issue of side-effects, I rediscovered the PROGN form
that we know from LISP as the thing that's needed in order to
handle inevitable side-effects in non-trivial XSLT applicaitons.
I guess all of that was mentioned in our earlier thread about
this. But I have now a bunch of experience with it and it may
be useful for others to share this again.

Use case: an XSLT application that retrieves or updates data from
a database. With SAXON one can easily script any JDBC work right
in XSLT and it works beautifully. But one needs to make sure the
extension-functions are called in the proper sequence. The way
to do that is to relate variables with dependencies to other
variables AND to specify short sequences that need to be evaluated
in order. The latter is known from LISP as the PROGN form.
PROGN was a primitive and simply a list that was evaluated right
to left and whose result was the last element (n-th element,
hence PROG-N.)

In Saxon 7.5.1 (XSLT/XPath 2.0) this can currently be emulated
with the sequence form:

  <xsl:param name="driversToLoad">
    <class name="org.postgresql.Driver"/>
    <class name="oracle.jdbc.OracleDriver"/>
  </xsl:param>

  <xsl:variable name="driversLoaded"
    xmlns:class="java:java.lang.Class"
    select="for $className in $driversToLoad/class/@name
              return class:forName(@name)"/>

  <xsl:variable name="newConnection"
    xmlns:dm="java:java.sql.DriverManager"
    select="($driversLoaded,
             dm:getConnection($url,$username,$password))[last()]"/>

  <xsl:variable name="connection"
    xmlns:c="java:java.sql.Connection"
    select="(c:setAutoCommit($newConnection, false()),
             $newConnection)[last()]"/>

  <xsl:variable name="SQL">
     SELECT FOO, BAR, BAZ FROM FOOBAR WHERE KNOX=? AND KOUTS=>
  </xsl:variable>

  <xsl:variable name="statement"
    xmlns:c="java:java.sql.Connection"
    select="c:prepareStatement($connection, $SQL)"/>

  <xsl:template match="foobar[@knox and @kouts]">
    <xsl:variable name="resultSet"
      xmlns:st="java:java.sql.PreparedStatement"
      select="(st:setLong($statement, 1, @knox),
               st:setString($statement, 1, @kouts),
               st:executeQuery())[last()]"/>
    <saxon:while test="rs:next($resultSet)">
      <foobar knox="{@knox}" kouts="{@kouts}"
         foo="{rs:getString($resultSet,'FOO')}"
         bar="{rs:getString($resultSet,'BAR')}"
         baz="{rs:getString($resultSet,'BAZ')}"/>
    </saxon:while>
  </xsl:template>

Notice how the dependencies on those variables, NOT
the order of appearence of the xsl:variable elements
forms the execution sequence like a string of pearls.
Also, notice how the same object (here the Connection)
appears under different names (newConnection and connection)
to reflect the different states (new and initialized.)

This works currently because (a) the Saxon optimizer isn't
so smart as to perform lazy-evaluation of sequence
elements or (b) to refuse to evaluate extension functions
that return void.

On that matter I would say that I am prepared for (a) and
(b) should just never happen. If lazy-evaluation of
sequence elements becomes reality (it's a great idea), so
that in a sequence ($x1, $x2, $x3, ..., $xn)[last()] only
the $xn will ever be evaluated, I will introduce my own
extension function, called progn(any*) that will evaluate
every argument left to right and return the last. No big
deal.

I think that (b) the optimizer should never refuse to
evaluate extension functions returning void because there
would be no point in doing this. It would be a piece of
code designed specifically to make people like me unhappy
and would serve no other purpose. I shall be prepared to
take such code out of whatever XSLT processor will do
this.

thanks
-Gunther

PS: Interestingly even Saxon 7.5.1 sometimes
evaluates variables/@select expressions even though the
variable is never actually referenced. But I would never
exploit such odd behavior, actually it is now even
hurting me.

--
Gunther Schadow, M.D., Ph.D.                    gschadow@xxxxxxxxxxxxxxx
Medical Information Scientist      Regenstrief Institute for Health Care
Adjunct Assistant Professor        Indiana University School of Medicine
tel:1(317)630-7960                         http://aurora.regenstrief.org



XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list


Current Thread