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
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] postion gives me 2 instea, Michael Kay | Thread | RE: [xsl] Side-effect and PROGN, ex, Michael Kay |
Re: [xsl] XalanNode.cloneNode() iss, david_n_bertoni | Date | [xsl] Ho to acheiverReverse XML tra, Kalyan Ghosh |
Month |