So, it's 2008 and I was still running into the same problems these gentlemen were having with the XML module in 2005 (mainly lack of XSL 2.0 functionality). So, After doing a bunch or research, I got the XML module to implement my own functions using the XsltArgumentList.AddExtensionObject() feature. All you have to do it make a quick edit to the ParameterList.vb file in the App_Code/XML/Parameters directory.
Example:
Public Function ToXsltArgumentList() As System.Xml.Xsl.XsltArgumentList
Dim xslArg As New System.Xml.Xsl.XsltArgumentList
For Each param As ParameterInfo In Me
If param.IsValidDefinition Then
Dim value As String = param.GetValue
If value.Length > 0 Then xslArg.AddParam(System.Xml.XmlConvert.EncodeName(param.Name), "", param.GetValue)
End If
Next
Dim obj As New XslFunctions()
xslArg.AddExtensionObject("urn:XslFunctions", obj)
Return xslArg
End Function
Here is a sample of my XslFunctions object:
Option Strict On
Option Explicit On
Imports System
Imports System.Text
Imports System.IO
Imports System.Xml
Imports DotNetNuke.Entities.Users
Namespace DotNetNuke.Modules.XML
'MY STUPID FIX TO DNN AND MICROSOFT'S LACK OF XSL/XPATH SUPPORT
Public Class XslFunctions
'DATE TIME FUNCTIONS
Public Function GetCurrentDate() As String
Return Date.Now.Year.ToString("0000") + "-" + Date.Now.Month.ToString("00") + "-" + Date.Now.Day.ToString("00")
End Function
Public Function GetDayInFuture(ByVal noOfDays As Double) As String
Dim dtp1 As DateTime = DateTime.Now.AddDays(noOfDays)
Dim newDay As String = dtp1.Year.ToString("0000") + "-" + dtp1.Month.ToString("00") + "-" + dtp1.Day.ToString("00")
Return newDay
End Function
Public Function ParseDate(ByVal strDate As String) As DateTime
Dim year As Integer = Int16.Parse(strDate.Substring(0, 4))
Dim month As Integer = Int16.Parse(strDate.Substring(5, 2))
Dim day As Integer = Int16.Parse(strDate.Substring(8, 2))
Dim hour As Integer = Int16.Parse(strDate.Substring(11, 2))
Dim minute As Integer = Int16.Parse(strDate.Substring(14, 2))
Dim second As Integer = Int16.Parse(strDate.Substring(17, 2))
Return New DateTime(year, month, day, hour, minute, second)
End Function
Public Function GetCurrentTime() As String
Return Date.Now.Hour.ToString("00") + ":" + Date.Now.Minute.ToString("00")
End Function
Public Function Space(ByVal count As Integer) As String
Dim spaces As String = ""
For i As Integer = 1 To count
spaces &= " "
Next i
Return spaces
End Function
Public Function GetDateObj(ByVal offset As Integer) As DateTime
Return DateTime.Now.AddDays(offset)
End Function
Public Function GetDate(ByVal dt As DateTime) As String
Return dt.Year.ToString("0000") + "-" + dt.Month.ToString("00") + "-" + dt.Day.ToString("00")
End Function
Public Function GetTime(ByVal tm As DateTime) As String
Return tm.Hour.ToString("00") + ":" + tm.Minute.ToString("00")
End Function
Public Function ParseAndGetDate(ByVal iso8601dtg As String) As String
Dim dtg As DateTime = ParseDate(iso8601dtg)
Return GetDate(dtg)
End Function
'Many of these are just the basic .NET string functions...
Public Function SubString(ByVal original As String, ByVal startIndex As Integer) As String
Return original.Substring(startIndex)
End Function
Public Function SubString(ByVal original As String, ByVal startIndex As Integer, ByVal length As Integer) As String
Return original.Substring(startIndex, length)
End Function
Public Function Replace(ByVal original As String, ByVal oldValue As String, ByVal newValue As String) As String
Return original.Replace(oldValue, newValue)
End Function
Public Function Remove(ByVal original As String, ByVal startIndex As Integer) As String
Return original.Remove(startIndex)
End Function
Public Function Remove(ByVal original As String, ByVal startIndex As Integer, ByVal length As Integer) As String
Return original.Remove(startIndex, length)
End Function
Public Function ToUpper(ByVal original As String) As String
Return original.ToUpper()
End Function
Public Function ToLower(ByVal original As String) As String
Return original.ToLower()
End Function
Public Function Trim(ByVal original As String) As String
Return original.Trim()
End Function
Public Function IndexOf(ByVal original As String, ByVal value As String) As Integer
Return original.IndexOf(value)
End Function
Public Function IndexOf(ByVal original As String, ByVal value As String, ByVal startIndex As Integer) As Integer
Return original.IndexOf(value, startIndex)
End Function
Public Function IndexOf(ByVal original As String, ByVal value As String, ByVal startIndex As Integer, ByVal count As Integer) As Integer
Return original.IndexOf(value, startIndex, count)
End Function
Public Function Insert(ByVal original As String, ByVal startIndex As Integer, ByVal value As String) As String
Return original.Insert(startIndex, value)
End Function
Public Function Length(ByVal original As String) As Integer
Return original.Length
End Function
Public Function StartsWith(ByVal original As String, ByVal value As String) As Boolean
Return original.StartsWith(value)
End Function
Public Function EndsWith(ByVal original As String, ByVal value As String) As Boolean
Return original.EndsWith(value)
End Function
Public Function Contains(ByVal original As String, ByVal value As String) As Boolean
Return original.Contains(value)
End Function
End Class 'XslFunctions
End Namespace
Not too difficult. Here's an example of it's implementation in the XSL File:
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fn="urn:XslFunctions">
<xsl:output method="html" encoding="iso-8859-1"/>
<!-- This template matches all planets elements -->
<xsl:template match="/">
<!-- GRAB CURRENT DATE AND TEST TO SEE IF THERE ARE RESULTS -->
<xsl:variable name="today" select="fn:GetCurrentDate()" />
<xsl:variable name="todayPlus1" select="fn:GetDayInFuture(1)" />
<xsl:variable name="todayPlus2" select="fn:GetDayInFuture(2)" />
<!-- etc, etc, etc, -->
<xsl:value-of select="fn:GetDayOfWeek(fn:GetDateObj(0))" />,<xsl:value-of select="$sp" />
<xsl:value-of select="fn:getMonthName(fn:GetMonthInt(fn:GetDateObj(0)))" /><xsl:value-of select="$sp" />
<xsl:value-of select="fn:GetDay(fn:GetDateObj(0))" />
<!-- etc, etc, etc, -->
</xsl:template>
</xsl:stylesheet>
The cool thing about the whole technique is that you can expose a much richer (and specific) set of functions than even what XSL 2.0 supports. If there was a way I could attach the files to this post, I would give you the full source. Sorry!
Richard