Using non-core EXSLT date functions with Xalan Jav

2019-03-05 10:40发布

问题:

I have had EXSLT's core date functions working well in some XSL templates I've been using for years. I'd like to start using a new one: seconds. This function is not one of the "core" functions and therefore implementations can claim compliance with EXSLT without actually implementing it.

I'm using Cocoon 2.1.11 with Xalan 2.7.1 which, it appears, has chosen not to implement date:seconds.

Fortunately, the kind folks at EXSLT provide downloads to help you plug-in individual functions but I can't seem to figure out how to actually achieve the plug-in.

I can use the core functions easily using this template for instance:

<?xml version="1.0" ?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:date="http://exslt.org/dates-and-times" >
  <xsl:template match="/">
    <xsl:value-of select="date:date-time()" />
  </xsl:template>
</xsl:stylesheet>

When attempting to use the date.seconds function, I have tried the following:

  1. Simply adding <xsl:import href="date.seconds.xsl" /> to my template, and using date:seconds(). This gets me the error message "For extension function, could not find method org.apache.xalan.lib.ExsltDatetime.seconds"
  2. Removing the xmlns:date as shown above. This gets me the error "Prefix must resolve to a namespace: date"
  3. Placing the contents of date.seconds.xsl within the template I'm trying to write, then calling date:seconds() with no argument (it's defined to use the current time by default). I get this error message: "Instance method call to method seconds requires an Object instance as first argument". This is looking promising, now.
  4. Adding an argument to date:seconds. I get the error message: "For extension function, could not find method java.lang.String.seconds([ExpressionContext,] )"

Any suggestions for how to use this non-core EXSLT function?

Here is my current template, still telling me that it's trying to call java.lang.String.seconds():

<?xml version="1.0" ?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:func="http://exslt.org/functions"
    xmlns:date="http://exslt.org/dates and times">
  <xsl:import href="date.seconds.xsl" />
  <func:script language="exslt:javascript" implements-prefix="date" src="date.js"/>
  <func:script language="exslt:msxsl" implements-prefix="date" src="date.msxsl.xsl"/>

  <xsl:template match="/">
    <xsl:value-of select="date:seconds('2014-02-27')" />
  </xsl:template>
</xsl:stylesheet>

回答1:

For those who want to roll their own (for seconds() specifically), it can be done rather simply using this code:

package tools;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.text.ParseException;

public class Dates
{
  /**
   * Converts a date in xs:dateTime format into seconds-since-the-epoch
   * 
   * @param date The date to be converted,
   *             in <code>s:dateTime</code> format (yyyy-MM-dd'T'hh:mm:ss).
   *
   * @return Number of seconds since <code>1970-01-01 00:00:00</code>,
   *         or 0 if the date is blank or null.
   * @throws ParseException
   */
  public static long seconds(String date)
      throws ParseException
  {
      if(null == date || 0 == date.trim().length()) return 0;

      SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss");
      Date d = df.parse(date);

      return d.getTime() / 1000;
  }
}

This can be used through Apache Xalan like this:

<?xml ...
  xmlns:java="http://xml.apache.org/xalan/java"
  ...

<xsl:variable name="some-date" select="...some xs:dateTime data ..." />
<xsl:value-of select="java:tools.Dates.seconds($some-date)" />

I'll probably look at the Xalan source in order to make this more flexible, but for now it seems to be doing what I'd like it to do.



回答2:

First, have a look at: http://www.exslt.org/howto.html#other-implementations However, AFAIK Xalan does not support the func:script extension element (at least it says it doesn't, which is not always the same). OTOH, Xalan has its own extension mechanism - see: http://xml.apache.org/xalan-j/extensions.html

If it were me, I would simply use a named template instead.



标签: xslt xalan exslt