Can an XSLT insert the current date? - xslt

A program we use in my office exports reports by translating a XML file it exports with an XSLT file into XHTML. I'm rewriting the XSLT to change the formatting and to add more information from the source XML File.
I'd like to include the date the file was created in the final report. But the current date/time is not included in the original XML file, nor do I have any control on how the XML file is created. There doesn't seem to be any date functions building into XSLT that will return the current date.
Does anyone have any idea how I might be able to include the current date during my XSLT transformation?

XSLT 2
Date functions are available natively, such as:
<xsl:value-of select="current-dateTime()"/>
There is also current-date() and current-time().
XSLT 1
Use the EXSLT date and times extension package.
Download the date and times package from GitHub.
Extract date.xsl to the location of your XSL files.
Set the stylesheet header.
Import date.xsl.
For example:
<xsl:stylesheet version="1.0"
xmlns:date="http://exslt.org/dates-and-times"
extension-element-prefixes="date"
...>
<xsl:import href="date.xsl" />
<xsl:template match="//root">
<xsl:value-of select="date:date-time()"/>
</xsl:template>
</xsl:stylesheet>

Do you have control over running the transformation? If so, you could pass in the current date to the XSL and use $current-date from inside your XSL. Below is how you declare the incoming parameter, but with knowing how you are running the transformation, I can't tell you how to pass in the value.
<xsl:param name="current-date" />
For example, from the bash script, use:
xsltproc --stringparam current-date `date +%Y-%m-%d` -o output.html path-to.xsl path-to.xml
Then, in the xsl you can use:
<xsl:value-of select="$current-date"/>

For MSXML parser, try this:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:my="urn:sample" extension-element-prefixes="msxsl">
<msxsl:script language="JScript" implements-prefix="my">
function today()
{
return new Date();
}
</msxsl:script>
<xsl:template match="/">
Today = <xsl:value-of select="my:today()"/>
</xsl:template>
</xsl:stylesheet>
Also read XSLT Stylesheet Scripting using msxsl:script and Extending XSLT with JScript, C#, and Visual Basic .NET

...
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:local="urn:local" extension-element-prefixes="msxsl">
<msxsl:script language="CSharp" implements-prefix="local">
public string dateTimeNow()
{
return DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ssZ");
}
</msxsl:script>
...
<xsl:value-of select="local:dateTimeNow()"/>

Late answer, but my solution works in Eclipse XSLT. Eclipse uses XSLT 1 at time of this writing. You can install an XSLT 2 engine like Saxon. Or you can use the XSLT 1 solution below to insert current date and time.
<xsl:value-of select="java:util.Date.new()"/>
This will call Java's Data class to output the date. It will not work unless you also put the following "java:" definition in your <xsl:stylesheet> tag.
<xsl:stylesheet [...snip...]
xmlns:java="java"
[...snip...]>
I hope that helps someone. This simple answer was difficult to find for me.

format-date(current-date(), '[M01]/[D01]/[Y0001]') = 09/19/2013
format-time(current-time(), '[H01]:[m01] [z]') = 09:26 GMT+10
format-dateTime(current-dateTime(), '[h1]:[m01] [P] on [MNn] [D].') = 9:26 a.m. on September 19.
reference: Formatting Dates and Times using XSLT 2.0 and XPath

Related

Value-of select in <a href=> (XSLT)

I try to concstruct link with
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="concat('file:///', substring-before('%RolesPath%', 'roles'),'Flores.chm')"/>
</xsl:attribute>
Help
</xsl:element>
but I get error:
File file:///Flores.chm not found
I'm pretty sure, that variable %RolesPath% works fine. I'm using it in code normally. And if I use in code only
<xsl:value-of select="concat('file:///', substring-before('%RolesPath%', 'roles'),'Flores.chm')"/>
I get
file:///C:\Flores\Flores.chm
which is right path. Where I'm doing mistake please?
edit. %RolesPath% stores path to specify folder of program, which works with this code. In my case %RolesPath% stores "C:\Flores\roles\".
To specify my problem. I need open file(Flores.chm) in root folder of program. Program can be install everywhere in PC and prapably only way, how I can get the path is via %RolesPath%.
What you are passing to substring-before() is just a string ('%RolesPath%'). It appears that you are trying to use a Windows environment variable. This isn't going to work the way you're using it.
I think you have 2 options:
Option 1
Pass the value of the environment variable as an xsl:param when you call the stylesheet. This would work in either XSLT 1.0 or 2.0.
You would need the xsl:param:
<xsl:param name="RolesPath"/>
and this is how you would reference it:
<a href="{concat('file:///', substring-before($RolesPath, 'roles'),'Flores.chm')}"/>
Option 2
Use the environment-variable() function. This would only work with an XSLT 3.0 processor, such as Saxon-PE or EE.
Example:
<a href="{concat('file:///', substring-before(environment-variable('RolesPath'), 'roles'),'Flores.chm')}"/>
Here's another example of environment-variable() to show the function actually working:
XSLT 3.0
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<environment-variable name="TEMP" value="{environment-variable('TEMP')}"/>
</xsl:template>
</xsl:stylesheet>
Output (when applied to any well-formed XML)
<environment-variable name="TEMP" value="C:\Users\dhaley\AppData\Local\Temp"/>
Use this shorter expression:
<a href="file:///{substring-before($RolesPath, 'roles')}Flores.chm"/>
where $RolesPath is passed as an external, global parameter to the transformation.
How exactly to pass an external parameter to the transformation varies from one XSLT processor to another -- read your XSLT processor documentation. Some XSLT processors also allow string-typed parameters to be passed to the transformation from a command-line execution utility.

BaseX: where to declare the XML document on which to perform a query

With the program BaseX I was able to use XPath and XQuery in order to query an XML document located at my home directory, but I have a problem with doing the same in XSLT.
The document I'm querying is BookstoreQ.xml.
XPath version, running totally fine:
doc("/home/ioannis/Desktop/BookstoreQ.xml")/Bookstore/Book/Title
XSLT code which I want to execute:
<xsl:stylesheet version = "2.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
<xsl:output method= "xml" indent = "yes" omit-xml-declaration = "yes" />
<xsl:template match = "Book"></xsl:template>
</xsl:stylesheet>
I read BaseX' documentation on XSLT, but didn't manage to find a solution. How can I run given XSLT?
BaseX has no direct support for XSLT, you have to call it using XQuery functions (which is easy, though). There are two functions for doing this, one for returning XML nodes (xslt:transform(...)), one for returning text as a string (xslt:transform-text(...)). You need the second one.
xslt:transform-text(doc("/home/ioannis/Desktop/BookstoreQ.xml"),
<xsl:stylesheet version = "2.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
<xsl:output method= "xml" indent = "yes" omit-xml-declaration = "yes" />
<xsl:template match = "Book"></xsl:template>
</xsl:stylesheet>
)
Both can either be called with the XSLT as nodes (used here), by passing it as a string or giving a path to a file containing the XSLT code.

XSLT convert SimpleDateTime to GMT-00:00 timezone

I need help on XSLT to reformat time, without much luck.
<names>
<name>
<foo id='x_date'>
<value> 01/23/2011 13:20:00 PDT</value>
</foo>
</name>
</names>
How will I change the date from '01/23/2011 01:23:00 PDT' to '01/23/2011 09:24:00 GMT+00:00' via XSLT?
Please help, it's killing me :-)
If you're open to use a non-XSLT solution using Java's Xalan extensions, for instance, you could opt for the date time functions as documented here:
http://exslt.org/date/index.html
Something along the lines of
<xsl:value-of select="
date:format-date(
date:parse-date(/names/name/foo/value, $inPattern),
$outPattern)" />
In your specific case, you'd probably have to implement your own date formatter in a custom namespace. This is quite simple:
Add Xalan to your classpath
Create a custom date formatter:
package org.example;
public class MyExtension {
public static String myFormat(String date) {
// Do the formatting
}
}
Use the above formatter in an XSLT stylesheet:
<xsl:stylesheet xmlns:myextension="http://org.example.MyExtension">
..
<xsl:value-of select="myextension:myFormat(/names/name/foo/value)"/>
..
</xsl:stylesheet>
More documentation can be found here:
http://exslt.org

XSLT functions and namespaces

I'm kind of new to XSLT, and I've gotten basic transformation done. Next I want to try out date manipulations, since my data will have timestamps. However, I can't seem to get any date functions to work, and it greatly frustrates me. I'm testing using Firefox 3.5, xsltproc 1.1.24, xalan 1.10, and XMLSpy 2009, and they all say that the functions I'm trying to use don't exist.
My xml looks like so:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="datetime.xsl"?>
<watcher>
<event id="1" date="2009-09-04T13:49:10-0500" type="ABCD">This is a test </event>
</watcher>
</code>
My xsl looks like so:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fn="http://www.w3.org/2005/02/xpath-functions"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:template match="event[#type='ABCD']">
<!-- Date: <xsl:value-of select="day-from-dateTime(xs:dateTime(#date))"/> -->
<!-- Date: <xsl:value-of select="day-from-dateTime(#date)"/> -->
Date: <xsl:value-of select="fn:day-from-dateTime(#date)"/>
</xsl:template>
</xsl:stylesheet>
If I make the stylesheet version 2, XMLSpy complains that it can't cast my date: XSLT 2.0 Debugging Error: Error in XPath 2.0 expression (Cast failed, invalid lexical value - xs:dateTime '2009-09-04T13:49:10-0500')
If I leave it as version 1, it complains about a different error: XSLT 1.0 Debugging Error: Error in XPath expression (Unknown function - Name and number of arguments do not match any function signature in the static context - 'day-from-dateTime')
Anytime I try to change the XSL to use a namespace, such as fn:day-from-dateTime, it refuses to work at all, with all of my parsers saying that The function number 'http://www.w3.org/2005/02/xpath-functions:day-from-dateTime' is not available and variants thereof. I know from other tests that I can use the substring() function perfectly, without needing any namespace prefix, and I believe it's in the same namespace as day-from-dateTime.
I feel like it's something incredibly easy, since all of the tutorials show functions being used, but something seems to be eluding me. Could someone show me what I'm missing?
Ouch, nasty versions thing going on here. A lot of the issues you're seeing will be because the XSLT processor you're using doesn't support XPath 2.0, which is where that day-from-dateTime function comes from.
I can get what you're trying to do to work, with a Saxon processor - Saxon-B 9.1.0.6 as my processor instead of Xalan. (Xalan appears to support XPath 1.0 only, according to the documentation)
There are a few errors in your documents:
The source document should have the timezone as 05:00, not 0500
<?xml version="1.0" encoding="UTF-8"?>
<watcher>
<event id="1" date="2009-09-04T13:49:10-05:00" type="ABCD">This is a test </event>
</watcher>
The XSLT should cast the string 2009-09-04T13:49:10-05:00 into a xs:dateTime, which is what type the argument of day-from-dateTime needs to be.
Date: <xsl:value-of select="day-from-dateTime(xs:dateTime(#date))"/>
And then it works
<?xml version="1.0" encoding="UTF-8"?>
Date: 4
Hope that helps,

Xslt transform on special characters

I have an XML document that needs to pass text inside an element with an '&' in it.
This is called from .NET to a Web Service and comes over the wire with the correct encoding &
e.g.
T&O
I then need to use XSLT to create a transform but need to query SQL server through a SP without the encoding on the Ampersand e.g T&O would go to the DB.
(Note this all has to be done through XSLT, I do have the choice to use .NET encoding at this point)
Anyone have any idea how to do this from XSLT?
Note my XSLT knowledge isn’t the best to say the least!
Cheers
<xsl:text disable-output-escaping="yes">&<!--&--></xsl:text>
More info at: http://www.w3schools.com/xsl/el_text.asp
If you have the choice to use .NET you can convert between an HTML-encoded and regular string using (this code requires a reference to System.Web):
string htmlEncodedText = System.Web.HttpUtility.HtmlEncode("T&O");
string text = System.Web.HttpUtility.HtmlDecode(htmlEncodedText);
Update
Since you need to do this in plain XSLT you can use xsl:value-of to decode the HTML encoding:
<xsl:variable name="test">
<xsl:value-of select="'T&O'"/>
</xsl:variable>
The variable string($test) will have the value T&O. You can pass this variable as an argument to your extension function then.
Supposing your XML looks like this:
<root>T&O</root>
you can use this XSLT snippet to get the text out of it:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:template match="root"> <!-- Select the root element... -->
<xsl:value-of select="." /> <!-- ...and extract all text from it -->
</xsl:template>
</xsl:stylesheet>
Output (from Saxon 9, that is):
T&O
The point is the <xsl:output/> element. The defauklt would be to output XML, where the ampersand would still be encoded.