Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XSLT functions and namespaces

Tags:

xslt

xpath

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?

like image 610
hufman Avatar asked Sep 05 '09 16:09

hufman


People also ask

What is namespace in XSLT?

The namespace http://www.w3.org/1999/XSL/Transform is referred to as "the XSLT namespace". The prefix xsl is conventionally used to refer to this namespace (and is so used both within this document and within the XSLT specification), but it has no special status: any prefix may be used.

What is XSLT function?

The XSLT function returns the element that contains the current node. This function is necessary for accessing the current node when it is not the same as the context node provided in the code because both the nodes are the same.

How do you add a namespace in XSLT?

Provided that you're using XSLT 2.0, all you have to do is add the xpath-default-namespace attribute on the document element of each stylesheet: <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xpath-default-namespace="http://example.com"> ...

What is namespace in XPath?

Namespaces provide a way of qualifying names that are used for elements, attributes, data types, and functions in XPath. Names in XPath are called QNames (qualified names) and conform to the syntax that is defined in the W3C Recommendation Namespaces in XML .


1 Answers

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,

like image 120
brabster Avatar answered Sep 20 '22 07:09

brabster