There are a couple of ways I think are easier to extend ESQL.  In particular, I think it is useful to have all of your extensions in a separate place, outside the jar file.  Otherwise, it is easy to lose track of the changes you have made.  So one option is to bring the esql.xsl outside the jar, and change cocoon.xconf to point to the new location (I assume that it still works this way in 2.1, I am still using 2.0.x).  To take it one step better, create your own stylesheet that contains your single template, and use <xsl:import> to import the esql.xsl.  Again, change cocoon.xconf to use your stylesheet.

If you start getting a lot of these, you might consider creating a "wrapper" logicsheet.  In essence you create a stylesheet with your own namespace, like "jeff.sql".  The logicsheet defines or redefines templates as needed, and simply creates ESQL tags to re-use the esql functionality.  You can have one template that merely passes forward to ESQL any tags that your logicsheet doesn't explicitly redefine.   This has advantages and disadvantages; one disadvantage is that you have to copy over any named templates from ESQL that you need to make your custom templates work, e.g., "get-nested-string".  In your case, you are using a couple of named templates, but I wonder if you could do a wrapper template like:
<xsl:template match="jeff.sql:row-results//jeff.sql:get-epoch|jeff.sql:call-results//jeff.sql:get-epoch">
 <xsp:expr>(<esql:get-timestamp column="[EMAIL PROTECTED]"/>).getTime()</xsp:expr>
</xsl:template>


I don't have the esql.xsl right in front of me, so I don't know if this works or not.  If not, maybe ((java.sql.Timestamp)(<esql:get-object column="[EMAIL PROTECTED]" />)).getTime().  You have to get a bit creative....

We have a logicsheet like this, that gives us various extended features.  For instance, it handles all of the connection pool stuff, so that I don't have that explicitly in each of my XSP pages.  I also used it to get a "short form" for update queries, e.g.,
<fsql:action-query>
        update blah set blah = blah;
</fsql:action-query>

and it does other stuff, too.  If you are interested in this, here's a skeleton:

<?xml version="1.0"?>
<xsl:stylesheet
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xsp="http://apache.org/xsp"
        xmlns:esql="http://apache.org/cocoon/SQL/v2"
        xmlns:jeff.sql="http://jeff.org/jeff/sql"
        version="1.0"
>

<!-- Basic identity copy -->
<xsl:template match="@*|node()" priority="-1">
        <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
</xsl:template>

<!-- forwarding template; anything using jeff.sql that we don't explictly handle, -->
<!-- should be treated as an esql logicsheet element.                                            -->
<xsl:template match="jeff.sql:*" priority="-0.9">
        <xsl:element name="esql:{local-name()}">
                <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
</xsl:template>


<!-- copy over ESQL templates needed by your templates, e.g., get-nested-string -->

<!-- jeff.sql-specific templates defined here -->


</xsl:stylesheet>





"Jeff Jones" <[EMAIL PROTECTED]>

05/13/2004 03:25 PM
Please respond to users

       
        To:        <[EMAIL PROTECTED]>
        cc:        
        Subject:        Extending ESQL - how (if at all)



Hello all.

I'd like to use XSP/ESQL to retrieve a date from a database (might be Oracle or
MySQL) in "Unix epoch" format, i.e. milliseconds since 1/1/1970. Unfortunately,
that's not a format available in java.text.SimpleDateFormat, so it doesn't seem
possible to retrieve it using the <esql:get-timestamp/> tag.

I know that this could be done with a separate XSL transform, but for
performance reasons, I'd prefer not to have to convert back to a Date object and
then back to a String representation; I'd like to work with the Date object
(actually java.sql.Timestamp) retrieved from the database.

So I've tried adding this to esql.xsl:

<xspdoc:desc>returns the value of the given column as milliseconds since the
epoch.</xspdoc:desc>
<xsl:template match
="esql:row-results//esql:get-epoch|esql:call-results//esql:get-epoch">
 <xsp:expr><xsl:call-template name="get-resultset"/>.getTimestamp
(<xsl:call-template name="get-column"/>).getTime()</xsp:expr>
</xsl:template>

And here's the part of my XSP that uses the new tag:

<process_tm><esql:get-epoch column="process_tm"/></process_tm>

A few questions:

1. Apparently I'm missing a step somewhere, because I'm just getting the
<esql:get-epoch/> tag passed straight through when the pipeline runs. (Yes,
everything else works.) I've restarted Tomcat, rebuilt the databases block, and
copied the new databases-block.jar into WEB-INF/lib, to no avail. What do I need
to do to get this change reflected in running code?

2. Am I doing this the hard way? Is there an easier solution that I'm missing?
(Remember that I really don't want to do it in a separate transform, for
performance reasons.)

3. If this actually is a worthwhile idea, how would I go about submitting it?

(Details: Cocoon 2.1.4, Tomcat 4.1.29, Sun Java 1.4.2-b28 on SuSE Linux 9.0,
kernel 2.4.21.)

Thanks in advance for any help.

</Jeff>

Reply via email to