The Evaluate() Extension


Many of the new facilities included in XSLT 2.0, including multiple output files, grouping facilities, and stylesheet functions, were first pioneered as Saxon extensions. Saxon also copied extensions that were first introduced elsewhere: The ubiquitous node-set () extension function, for example, appeared first in James Clark's xt processor, as did extensions to find the intersection or difference between two node sets. Saxon went further than most XSLT processors in providing a wide range of extensions built in to the product. However, most of these have been superseded by standard features in XSLT 2.0.

The most important extension that remains, which has sadly not made it into XSLT 2.0 even though it has been copied by several other processors, is the ability to evaluate a dynamically constructed XPath expression. This extension has been adopted, in restricted form, as the dyn: evaluate () function within EXSLT (see www.exslt.org). Here I will describe the Saxon implementation of this functionality.

In standard XSLT (even in 2.0), there is no way of constructing an XPath expression at runtime from a string. This makes it difficult to do things that are very familiar to SQL programmers, for example building a query from the values of parameters read from a form, or sorting a table on a column selected by the user . It also makes it impossible to interpret XPath expressions held as part of the text of the source document, perhaps implementing a subset of the XPointer specification for defining links between documents. The Saxon stored expression concept fills this gap: You can use the saxon: expression () extension function to create a stored expression from a string, and saxon: eval () to evaluate the stored expression; or you can combine these two operations into one using the saxon: evaluate () function.

The table below describes these functions in more detail.

Function

Explanation

expression(string)

This function constructs a stored expression from the XPath expression contained in the supplied string. The stored expression can be evaluated later using the saxon:eval() function

If the XPath expression contains namespace prefixes, these are resolved at the time the stored expression is created, not at the time it is subsequently evaluated. (They are always resolved relative to namespaces declared in the stylesheet, which is not ideal when you want to evaluate an XPath expression contained in a source document)

The expression may contain references to the variables $p1 to $p9 . The values of these variables are supplied when the expression is subsequently evaluated

evaHexpression, variables...)

This function evaluates a stored expression supplied in the first argument. The stored expression is constructed using the saxon:expression() function

The second and subsequent arguments (which are optional) provide values that will be bound to the variables $p1..$p9 used within the stored expression

The context node, position, and size for evaluating the expression are those that apply to the stylesheet at the point where eval() is called

evaluate(string, variables...)

This function combines the effect of saxon:expression() and saxon:eval() into a single call: That is, it prepares the expression and immediately evaluates it

Allowing XPath queries to be constructed dynamically gives a number of benefits:

  • You can construct a query such as «//book [author= "Kay" and publisher="Wrox"] » , from the values of stylesheet parameters supplied at runtime.

  • You can easily change the sort order used in an <xsl: sort> element based on parameters supplied at runtime.

  • You can allow XPath expressions to be used within the source document, for example to define hyperlinks between documents, and you can write code in your stylesheet to follow these links. (However, there are limitations because of the way the namespace context is established).

  • You can implement higher order functions in which a function is passed as a parameter to another function.

  • You can use XPath expressions to define business rules in a separate document.

The following example demonstrates the last of these techniques.

Using saxon: evaluate() to Apply Business Rules
start example

In this example, we imagine a call center that is charging customers for the calls they make. We want to prepare the account for a period, listing all the calls and calculating the total charge.

Source

The list of calls is in the file calls.xml , as follows :

  <calls>   <call date="2001-01-15" time="08,15" duration="17"/>   <call date="2001-01-16" time="10.42" duration="8"/>   <call date="2001-01-18" time="17.42" duration="5"/>   <call date="2001-01-18" time="22.10" duration="06"/>   <call date="2001-01-24" time="12.19" duration="41"/>   <call date="2001-01-25" time="06.40" duration="13"/>   <call date="2001-01-27" time="11.15" duration="26"/>   </calls>  

We want to put the business rules for calculating the charges in a separate document. Of course, these rules could go in the stylesheet, but this isn't very good practice; mixing business rules and presentation rules in one place doesn't give the right separation of responsibilities. Instead, we'll put the relevant formula in a separate document tariff .xml , in the form of an XPath expression. This calculates the total charge, with different rates per minute during the working day and outside office hours:

  <tariff>   sum(call[@time &gt;= 08.00 and @time &lt; 18.00]/@duration    )    * 1.50   +   sum(call[@time &lt; 08.00 or @time &gt;= 18.00]/@duration) * 2.50   </tariff>  

Stylesheet

Most of the stylesheet ( account. xsl ) is conventional, and is concerned with displaying the information. When it comes to calculating the total charges, however, the stylesheet reads the XPath expression containing the relevant formula from the tariff.xml document, and evaluates it (using saxon: evaluate () ) in the context of the source document.

  <?xml version="1.0"?>   <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"   xmlns:saxon="http://saxon.sf.net/"   version="1.0">   <xsl:template match="/">   <html>   <head>   <title>Account for period ending   <xsl:value-of select="(//@date)[last()]"/></title>   </head>   <body>   <h1>Account for period ending   <xsl:value-of select="(//@date)[last()]"/></h1>   <xsl:apply-templates/>   </body>   </html>   </xsl:template>   <xsl:template match="calls">   <table>   <tr>   <th width="100">Date</th>   <th width="100">Time</th>   <th width="100">Duration</th>   </tr>   <xsl:apply-templates/>   </table>    <xsl    :    variable name="total"     select="saxon:evaluate(document('tariff.xml'))"/>    <p>Total charges for the period:   <xsl:value-of select="format-number($total, '$###0.00')"/>   </p>   </xsl:template>   <xsl:template match="call">   <tr>   <td><xsl:value-of select="@date"/></td>   <td><xsl:value-of select="@time"/></td>   <td><xsl:value-of select="@duration"/></td>   </tr>   </xsl:template>   </xsl:stylesheet>  

(An observation on this stylesheet: This was first written to work with XSLT 1.0. In principle, it could be rewritten to use the facilities for arithmetic on dates, times, and durations provided in XSLT 2.0. However, little would be gained by doing so. Converting the application to use these facilities would require times to be written as «xs:time ('08:00:00') » rather than as «08.00 » , which would also create a dependency on the declaration of the namespace prefix «xs » . Also, multiplying a duration by a number in XPath 2.0 returns a duration, not a cost. Just because the facilities are provided doesn't mean that you have to use them, and in this case, it seems simpler not to.)

To run this stylesheet, make the directory containing the downloaded files for this chapter the current directory, and enter:

  java -jar c:\saxon\saxon8.jar calls.xml account.xsl >bill.html  

Output

The output of this stylesheet (bill.html) appears in the browser as shown in Figure E-1.

click to expand
Figure E-1
end example
 



XSLT 2.0 Programmer's Reference
NetBeansв„ў IDE Field Guide: Developing Desktop, Web, Enterprise, and Mobile Applications (2nd Edition)
ISBN: 764569090
EAN: 2147483647
Year: 2003
Pages: 324

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net