xslt umbraco.library:FormatDateTime and the use of / (slash) - xslt

This may not be a real XSLT question but more of an Umbraco question.
This function as written will output another format as expexted:
<xsl:value-of select="umbraco.library:FormatDateTime(data [#alias = 'kursusgangTilmeldingsfrist'], 'dd/MM/yyyy')"/>
When called with these three "second arguments" on the current date
'dd MM yyyy'
'dd-MM-yyyy'
'dd/MM/yyyy'
Then output will be:
10 02 2009
10-02-2009
10-02-2009 (and this should have been with "/" and not a "-")
Br. Anders

Solution is to escape using a backslash so function is called like this:
<xsl:value-of select="umbraco.library:FormatDateTime(data [#alias = 'kursusgangTilmeldingsfrist'], 'dd\/MM\/yyyy')"/>
And this will output correct date as:
10/02/2009

Related

How do l compare year of a date in xsl?

How do I compare the year of a given date to int?
<if test="year(#varDate)>=1900">
true
</if>
Where the format of the date in the input file is:
<date varDate="31/12/1999" />
If you are stuck with XSLT 1.0, the most common way is to extract the year-part, like so:
substring-before('1994-12-31', '-')
Or, if your format is, let's say dd/MM/yyyy, you can do1:
substring-after('31/12/1999', '/')
In your case that would be something along those lines:
<xsl:if test="substring-after('31/12/1999', '/') > 1900">
true
</xsl:if>
Since you didn't provide input data, I assume you can work out the details yourself. Your original question was tagged xslt-1.0, but this has since changed. If that means that you can use XSLT 2.0 or higher, and you have an actual typed xs:date value, you can also use fn:year-from-date:
<xsl:if test="year-from-date(xs:date('1994-12-31')) > 1900">
true
</xsl:if>
1 This is not enough as there are two slashes, use substring-after(substring-after('31/12/1999', '/'), '/'), as seen in Michael's post (credit to him).
it turns out my date is in a different format that in solution above
(dd/mm/yyyy).
If that's really your date format - i.e.both days and month are always padded to two digits - you can use:
<if test="substring(#varDate, 7) >= 1900">
as your test.
If not, you'll need:
<if test="substring-after(substring-after(#varDate, '/'), '/') >= 1900">

add xslt filtering between two dates

I am trying to filter the list using xslt so that it only shows the item within two dates. But somehow the result is incorrect where only one item displayed. the statement I used is:
<xsl:variable name="Rows"
select="/dsQueryResponse/Rows/Row[(number(concat(substring(ddwrt:FormatDateTime(string(ddwrt:Today()), 1033, 'yyyy'),0,5),substring(ddwrt:FormatDateTime(string(#DateOfBirth), 1033, 'MM'),0,3),substring(ddwrt:FormatDateTime(string(#DateOfBirth),1033,'dd'),1,3))))
>= (number(translate(ddwrt:FormatDateTime(string(ddwrt:Today()),1033,'yyyyMMdd'),' ','')))
and(number(concat(substring(ddwrt:FormatDateTime(string(ddwrt:Today()), 1033, 'yyyy'),0,5),substring(ddwrt:FormatDateTime(string(#DateOfBirth), 1033, 'MM'),0,3),substring(ddwrt:FormatDateTime(string(#DateOfBirth),1033,'dd'),1,3))))
<= (number(translate(ddwrt:FormatDateTime(string(ddwrt:Today()),1033,'yyyyMMdd'),'',''))+7)]"/>
What I am trying to do is to display the employee who is celebrating their birthday this week by concatenate the day and month of their birthdate with today's year and convert this to number. then check if this new date is >= today's date (also convert to number) and <= today's date + 7 days.
I am new in xslt and been trying to solve this problem more than a week now. I am really appreciate if anyone can help me.
I believe you can use an XSLT extension to solve your problem more elegantly.
Some extension functions are provided by the ddwrt namespace, but none of them are very useful for date arithmetic.
Since I have no SharePoint to test any code with, I'm showing a script extension based on VBScript. Here is an IsAnniversary() function along with some supporting code.
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:udf="http://tempuri.org/udf"
exclude-result-prefixes="ddwrt msxsl udf"
>
<xsl:template match="/">
<xsl:for-each select="
/dsQueryResponse/Rows/Row[udf:IsAnniversary(#DateOfBirth, 7)]
">
<xsl:value-of select="#DateOfBirth" />
</xsl:for-each>
</xsl:template>
<msxsl:script language="VBScript" implements-prefix="udf">
<![CDATA[
Option Explicit
Function FirstValue(Input)
If IsObject(Input) Then ' it's an IXMLDOMNodeList
If Input.length > 0 Then FirstValue = Input.item(0).text Else FirstValue = Empty
Else
FirstValue = Input
End If
End Function
Function ParseDate(Input)
Input = FirstValue(Input)
Input = Split(Input & "T", "T")(0) ' handle ISO 8601 datetimes
If IsDate(Input) Then ParseDate = CDate(Input) Else ParseDate = Empty
End Function
Function ParseInt(Input)
Input = FirstValue(Input)
If IsNumeric(Input) Then ParseInt = CInt(Input) Else ParseInt = Empty
End Function
Function IsAnniversary(Input, WithinDays)
Dim TheDate, Diff
IsAnniversary = False
TheDate = ParseDate(Input)
WithinDays = ParseInt(WithinDays)
If Not (IsEmpty(TheDate) Or IsEmpty(WithinDays)) Then
TheDate = DateAdd("yyyy", Year(Now()) - Year(TheDate), TheDate)
Diff = DateDiff("d", Now(), TheDate)
If WithinDays >= 0 Then
IsAnniversary = Diff >= 0 And Diff <= WithinDays
Else
IsAnniversary = Diff <= 0 And Diff >= WithinDays
End If
End If
End Function
]]>
</msxsl:script>
</xsl:stylesheet>
The above quite well-tested and robust and it probably already does what you need(*), still you could re-implement the whole thing as a proper, XSLT-aware SharePoint extension based on the .NET Framework.
Here's an article on how to do that with respect to SharePoint: http://blog.mastykarz.nl/extending-content-query-web-part-xslt-custom-functions/ - it's from 2009 so it might not be a 100% fit with current versions of SharePoint, but it might start you off.
(*) I recommend you keep all your dates in ISO 8601 format (YYYY-MM-DD) so that CDate() recognizes them correctly.

Filtering set of rows with XSLT

i have troubles filtering with XSLT, basically i have an xml, where i would like to get only those items where the Due Date falls into interval of 3 months ... i've written the following:
<xsl:variable name="TaskRows" select="/dsQueryResponse/Tasks/Rows/Row[#DueDate > $IsoBeginQuartDate AND #DueDate < $IsoEndQuartDate]"/>
But I get an error: "Failed seting processor stylesheet: expected token ']' found 'NAME' ...
IsoDates are calculated and formated dates in ISO format ...
Any idea, how to do it, or i can't use "AND" when filtering?
PS: i'm using XSLT 1.0
There is case-sensitivity at work here! Try using 'and' instead of 'AND'.
Unfortunately in XSLT 1.0, you can't compare dates to see if a date is between two values.
What you could do is something like this:
<!-- Make sure to format this variables as YYYYMMDD -->
<xsl:variable name="$IsoBeginQuartDate">20130101</xsl:variable>
<xsl:variable name="$IsoBeginQuartDate">20131231</xsl:variable>
<!-- Make sure #DueDate also has the format YYYYMMDD, in this example I assume the DueDate has format YYYY-MM-DD -->
<xsl:variable name="TaskRows" select="/dsQueryResponse/Tasks/Rows/Row[translate(#DueDate, '-', '') > $IsoBeginQuartDate and translate(#DueDate, '-', '') < $IsoEndQuartDate]"/>
You now get errors, because > and < or not supported for strings or dates.

How to Get Correctly formatted date using Xslt?

I have a xslt code for getting the date from the database.the code is working correctly and I got the output ,but the problem is the date is not in correct format.here is the result.
output: 2013-05-07T11:27:46.7+02:00
my code is
<xsl:variable name="lastchange" select="shop:ExecStoredProcedure('kt_Lastchange',concat('#account:',$accid,',#itemnumber:',id))"></xsl:variable>
<textarea>
<xsl:value-of select ="$lastchange"/>
</textarea>
anyone can help for getting the correctly format of date?
If you are using
XSLT 1.0 version, use EXSLT - date:format-date date extension
XSLT 2.0 version, use built-in: Formatting Dates and Times date extension
Code
<xsl:variable name="dt" as="xs:dateTime" select="xs:dateTime('2012-10-21T22:10:15')"/>
<xsl:value-of select="format-dateTime($dt, '[Y0001]/[M01]/[D01]')"/>

Counting XML based on date conditionals with xslt

I'm working with xslt for the first time. I have 2.0, but that's about the only advantage I have access to with the c# transform library we have. I'm trying to count a number of child nodes in the XML document which contain a date more than 12 years ago and have a certain type attribute.
Sample xml structure:
<xml version=\"1.0\" encoding=\"utf-8\"?>
<... />
<Dependents>
<Dependent><DOB>1964-04-01</DOB><DependentType>Spouse</DependentType></Dependent>
<Dependent><DOB>2000-01-01</DOB><DependentType>Child</DependentType></Dependent>
<Dependent><DOB>2012-01-01</DOB><DependentType>Child</DependentType></Dependent>
</Dependents>
<... />
where <... /> signifies some extra unrelated stuff.
So essentially, I want the number of children younger than 12 years old. (I have the count of dependenttype = child of all ages working, it's just the under 12 that's giving me trouble). The approach that was suggested to me was to construct a variable that stands for 12 years ago from today and use that as a basis for comparison in the count() function. That sounds reasonable, but I'm stuck constructing the date without the use of 3rd party libraries (e.g. exslt) that are so often linked in questions like this for the easy, handy-dandy answers.
The xslt I've gotten so far for this is:
<xsl:variable name="today" select="current-dateTime()" as="xs:dateTime" />
<xsl:variable name="twelveyearsago" select="xs:dateTime(concat(year-from-dateTime($today) - 12, '-', month-from-dateTime($today), '-', day-from-dateTime($today)))" />
<xsl:text>12yearsago=</xsl:text><xsl:value-of select="$twelveyearsago" />
And it's not working because the month-from-dateTime (and presumable day-from-dateTime) don't add leading zeros. For today, March 21 2012 I'm getting back: Saxon.Api.DynamicError : Invalid dateTime value "2000-3-21" (Month must be two digits) (The W3Schools xpath function reference implies that they should, but they don't.)
What I would like to output is:
<xsl:text>&numberofchildren=</xsl:text><xsl:value-of select="count(//InsuranceRequest/HealthInsurance/Dependents/Dependent/DependentType[text() = 'Child'])" />
<xsl:text>&childrenunder12=</xsl:text><xsl:value-of select="children under twelve" />
The more I pound my head against this, the more I feel like there's a simpler approach that I'm just not seeing.
Edit: I cleaned up the xslt syntax so it's valid and not a doubly-quoted c# string.
You can simply substract a duration of 12 years as in <xsl:variable name="twelveyearsago" select="$today - xs:yearMonthDuration('P12Y')"/>, then use e.g. //Dependent[DependentType = 'Child' and xs:date(DOB) >= $twelveyearsago].
[edit]
Here is a template that compiles and executes fine for with Saxon 9.4:
<xsl:template match="/">
<xsl:variable name="today" select="current-date()"/>
<xsl:variable name="twelve-years-ago" select="$today - xs:yearMonthDuration('P12Y')"/>
<xsl:value-of select="count(//Dependent[DependentType = 'Child' and xs:date(DOB) >= $twelve-years-ago])"/>
</xsl:template>