Filtering set of rows with XSLT - 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.

Related

combine multiple fields with the same name using regexp

I have multiple fields with the same name "item" inside json object, how can I combine their values under one field (as an array) using regex
sample input:
{"item":"A","item":"B","item":"C"}
expected output:
"item": ["A","B","C"]
note that we could have more than 3 items on above sample
I have tried {"item":"(.*?)","item":"(.*?)","item":"(.*?)"} but here I'm limited with 3 items, I need something to work for any number of items.
Thanks
The conversion you want can be performed quite easily in XSLT 2.0 or higher using:
<xsl:text>"item": [</xsl:text>
<xsl:value-of select="for $i in tokenize(translate($input, '{}', ''), ',') return substring-after($i, ':')" separator=","/>
<xsl:text>]</xsl:text>
Demo: https://xsltfiddle.liberty-development.net/eiorv1e
Of course, if your ultimate goal is to parse the input in order to use its values, then it's not necessary to put it back as JSON.

Date compare in XSLT

I want to compare two dates in XSLT (1.0). Here I have mentioned hard coded dates
<xsl:variable name="DATE1" select="ms:format-date(16-FEB-19, 'dd-MMM-yy')" />
<xsl:variable name="DATE2" select="ms:format-date(01-MAY-19, 'dd-MMM-yy')" />
<xsl:if test="$DATE1 $lt; $DATE2">
</xsl:if>
I tried above but not getting proper result.
It looks like you're using some kind of extension function ms:format-date to format the dates. If you can format them as pure numeric YYYYMMDD then you can compare them as numbers. XSLT 1.0 does not offer a "<" operator for strings, let alone for dates.
Do think about moving forward to a later XSLT version (available from third parties) rather than asking the StackOverflow community to help you use a 20-year old version of the language.

Modify date as per matching a attribute name value in XSLT

I have an array of element where a:value element can have different values in it. In case the element contains date in Zulu format i.e.: 2019-04-17T10:42:48.0135859, I need to change it to YYYY-MM-DD format. I have already come up with a solution. However, I am more interested in the matching i:type="b:dateTime" in my condition. Which means if i:type is equal to or contains b:dateTime then the XSLT will fetch the date and do the required transformation.
The input XML is:
<Properties
xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
>
<a:KeyValueOfstringanyType>
<a:Key>dtDynamicModifyDate</a:Key>
<a:Value i:type="b:dateTime"
xmlns:b="http://www.w3.org/2001/XMLSchema"
>2019-04-17T10:42:48.0135859</a:Value>
</a:KeyValueOfstringanyType>
<a:KeyValueOfstringanyType>
<a:Key>tiEnrollmentStatus</a:Key>
<a:Value i:type="b:string"
xmlns:b="http://www.w3.org/2001/XMLSchema"
>Enrolled</a:Value>
</a:KeyValueOfstringanyType>
<a:KeyValueOfstringanyType>
<a:Key>tiNumberOfEnrollments</a:Key>
<a:Value i:type="b:int"
xmlns:b="http://www.w3.org/2001/XMLSchema"
>1</a:Value>
</a:KeyValueOfstringanyType>
<a:KeyValueOfstringanyType>
<a:Key>dtModifyDate</a:Key>
<a:Value i:type="b:dateTime"
xmlns:b="http://www.w3.org/2001/XMLSchema"
>2019-04-16T15:57:39.331-04:00</a:Value>
</a:KeyValueOfstringanyType>
</Properties>
The transformation is available here: https://xsltfiddle.liberty-development.net/ncdD7mC/1
Instead of this condition, I want the above condition to be checked (i:type is equal to or contains b:dateTime)
<xsl:when test="contains($payload/*[local-name()='Value'], '-') and contains($payload/*[local-name()='Value'], 'T') and contains($payload/*[local-name()='Value'], ':')">
Any pointer for the XPATH will be appreciated.
Cheers,
Sierra
The expression I think you are looking for is this...
<xsl:when test="$payload/*[local-name()='Value']/#*[name()='i:type'] ='b:dateTime'">
However, this would fail if the namespace prefix changed, so perhaps you should do this:
<xsl:when test="$payload/*[local-name()='Value']/#*[local-name()='type'] ='b:dateTime'">
But this could potentially not give you the right results if you had two attributes named type in different namespace. The only real solution is to declare the xmlns:i namespace in the XSLT, then you would do this:
<xsl:when test="$payload/*[local-name()='Value']/#i:type ='b:dateTime'">

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">

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]')"/>