XSLT axis for siblings across trees? - xslt

I am using XSLT to generate some webpages and I need to create links for the next and previous day. The structure is roughly as follows:
year
month
day
day
...
month
day *
day
...
...
...
Tried using the preceding-sibling and following-sibling axis, but then discovered they of course won't work for the first and last day of a month. For example preceding-sibling would return nothing for the day marked with *.
How can I get the previous and next day for a given day, across the year and month "barriers", using XSLT 1.0?

The axis operators you are looking for in this case are preceding and following, which gets the preceding or following node regardless of the level in the hierarchy.
<xsl:copy-of select="following::day[1]" />
<xsl:copy-of select="preceding::day[1]" />

Related

XSLT convert UTC to tz timezone

I have the following variable:
<xsl:variable name="time">
<xsl:value-of select="'2020-12-26T17:33:11Z'"/>
</xsl:variable>
<xsl:variable name="timeZone">
<xsl:value-of select="'America/Los_Angeles'" />
</xsl:variable>
The variable time is in UTC and I would like to convert it to the local timezone. I am using the following but that is not working:
<xsl:value-of select="adjust-dateTime-to-timezone($time), xs:dayTimeDuration($timeZone))"/>
My expected output is: 2020-12-26T09:33:11Z
Nearly all the date/time/timezone functionality in XSLT/XPath is based on absolute numeric timezone offset such as -05:00, not on civil timezones such as CET or America/Los_Angeles. The one exception is format-dateTime(), which is designed to format data for human consumption. The fifth argument to format-dateTime() is "place": XPath 3.1 says:
If the $place argument is supplied in the form of an IANA timezone
name that is recognized by the implementation, then the date or time
being formatted is adjusted to the timezone offset applicable in that
timezone. For example, if the xs:dateTime value 2010-02-15T12:00:00Z
is formatted with the $place argument set to America/New_York, then
the output will be as if the value 2010-02-15T07:00:00-05:00 had been
supplied. This adjustment takes daylight savings time into account
where possible; if the date in question falls during daylight savings
time in New York, then it is adjusted to timezone offset -PT4H rather
than -PT5H. Adjustment using daylight savings time is only possible
where the value includes a date, and where the date is within the
range covered by the timezone database.
Note that this is new in XPath 3.x; the 2.0 specification only allowed a country code to be used, and was much vaguer about what it meant.

Adding a date for the Maximum of three dates in XSLT

Could you please help me on fetching the date +1 for the maximum of three dates?
Description:
I have built a code in XSLT to fetch maximum of three dates.I want to add one date for the maximum date what i get .
Can anyone please help me on this?
Thanks & Regards,
Gowthami H J
Assuming you use XSLT 2 or 3 (which the use of xs:string suggests) you can simply apply the date arithmetic https://www.w3.org/TR/xpath-functions/#dateTime-arithmetic provided in XPath 2 and later for the xs:date/xs:dateTime and the duration data types e.g. in
max(item/xs:date(.)) + xs:dayTimeDuration('P1D')
max(item/xs:date(.)) computes the maximum date of the sequence of item elements and the + operator adds a duration of one day.
http://xsltfiddle.liberty-development.net/pPqsHTX

Sharepoint XSL dropdown populated form a list

I'm trying to use a CEWP to display a list of items as a drop down list.
Specifically im trying to set the value to the url and then the title as the item shown in the drop down.
This is what I have so far
<xsl:template name="HubJumpTo" match="Row[#Style='HubJumpTo']" mode="itemstyle">
<select id="mySelect">
<xsl:for-each select="/item">
<option>
<xsl:attribute name="value"><xsl:value-of select="#value"/></xsl:attribute>
<xsl:value-of select="#name"/>
</option>
</xsl:for-each>
</select>
</xsl:template>
But the CEWP isn't showing any fields for me to specifiy which coloumn in the list should popul;ate value and name. Any suggestions why this might be?
The drop down isn't populating with anything and I assume this is because of this isse.
It might be a typo in your question (in which case, this answer will self-destruct...), but the problem may lie in this line
<xsl:for-each select="/item">
Because the xpath expression starts with a forward slash /, then this represents the document node, and so the expression is looking for the root element of the name item. There is only one root element in the document, and I guessing it is not called item!
You probably need to use a relative expression here, assuming item is a child element of the currently matched Row element.
<xsl:for-each select="item">
Your query seems bit ambiguous, you say CEWP i.e. "Content editor Webpart" how come you can use CEWP with XSLT for rendering list? it should be like, you need to add list view webpart and pass your custom xslt path to it.
also i see match="Row[#Style='HubJumpTo']" so do you have a column named 'Style'? and are there any rows with value "HubJumpTo"
DID this using SP services in the end.

coalesce doesn't work when grouping is used

I have an easy question. I'm trying to use coalesce in combination with a group by clause. I want to get 0 values when the variable is null. Here is my sql server code:
SELECT SUM(COALESCE(NETTOTAL,0)) AS NETTOTAL,DATEPART(MM,RECORD_DATE) MONTH
FROM ORDERS WHERE ORDER_EMPLOYEE_ID=#attributes.record_emp_id#
GROUP BY DATEPART(MM,RECORD_DATE) ORDER BY MONTH
.. and my output:
<tr height="20">
<td>Orders</td>
<cfoutput query="get_orders"><td style="text-align:center;">#tlformat(nettotal,2)# - #month#</td></cfoutput>
</tr>
This code is just for the orders. There is also the sales row. Anyway here is the screenshot to make it more clear:
http://i.stack.imgur.com/VIAmr.png
To make it more clear I added the number of the month. As you can see the order is broken since there are no zero values for the other months...
P.S.Thank you all for the help! i really appreciate it!
Your query is not at fault. You are trying to select from ORDERS based on each employee_id. You are then looping over it.
If a given month has no orders, then there will be no row for it within the result set.
Even if there were only orders for the last 4 months, they would get pushed to the first 4 as you are not checking that the month you are currently outputting matches the column header.
For a bit of metacode, I would go down this route
1 - create an array as follows
arrMonths= [
{orders=0,sales=0},
{orders=0,sales=0}....
]
This will give you a stc you can iterate over later.
2 - I would then loop over each query
<cfoutput query="get_orders">
<cfset arrMonths[month].orders = nettotal>
</cfoutput>
3 - I would then iterate over the array
<tr height="20">
<td>Orders</td>
<cfoutput from="1" to="#ArrayLen(arrMonths)#" index="thisMonth">
<td style="text-align:center;">#tlformat(arrMonths[thisMonth].orders,2)# - #thisMonth#</td>
</cfoutput>
</tr>
This way, every month will ALWAYS have a value even if it's 0. You can also ditch the coalesce as the simple fact that rows with no orders have no records means they default to 0 so your query may become
SELECT
SUM(COALESCE(NETTOTAL)) AS NETTOTAL,
DATEPART(MM,RECORD_DATE) MONTH
FROM ORDERS
WHERE ORDER_EMPLOYEE_ID=<cfqueryparam cfsqltype="cf_sql_integer" value="#attributes.record_emp_id#">
GROUP BY DATEPART(MM,RECORD_DATE)
MONTH is now not necessary as it's just inserting into the array which deals with ordering
TRy ISNULL() Instead of COALESCE .
COALESCE is used for multiple argumentsif multiple arguments are not needed you could use ISNULL
Try to invert the order of the functions Sum and Coalesce.
IsNull might be more readable as well:
SELECT IsNull(SUM(NETTOTAL), 0) AS NETTOTAL,
DATEPART(MM, RECORD_DATE) MONTH
FROM ORDERS
WHERE ORDER_EMPLOYEE_ID = #attributes.record_emp_id#
GROUP BY DATEPART(MM, RECORD_DATE)
ORDER BY MONTH
If there are no elements of NETTOTAL, Coalesce from your code would not be called. So a Sum of no rows will be null.

parsing date and time

Currently In my source file, i am getting date and time values like below.
2010-07-06T19:06:47
i want to put date in one variable and time in another one. Please let me know how to do this.
Assuming the combined date/time value is in variable $date-time...
<xsl:variable name="date" select="substring-before($date-time, 'T')"/>
<xsl:variable name="time" select="substring-after($date-time, 'T')"/>
The quickest and easiest way to do this would be to split/explode the variable into 2 pieces with the date in one and the time in the other.
Date Parsing means converting String into Date. Same Simple DateFormat codes are used to parsing date.
For example,
DateFormat formatter = new SimpleDateFormat("MM/dd/yy");<br/>
Date date = (Date)formatter.parse("07/16/87");<br/>
formatter = new SimpleDateFormat("dd-MMM-yy");<br/>
date = (Date)formatter.parse("16-Jul-87");<br/>
Source : Tutorial Data - Date and Time