How to extract value using xslt 1.0 - xslt

How to extract number 500 using xslt 1.0 from a large text
"o:errorCode" : "500"

Perhaps you're looking for:
<xsl:value-of select="substring-before(substring-after($largeText, '"o:errorCode" : "'), '"')"/>
This extracts the substring between the first occurrence of "o:errorCode" : " in $largeText and the first " that follows it.
Note that this will fail if the formatting of the input changes.

Related

How find XPATH with random number value in attribute?

I have div blocks on website like this: <div id="banner-XXX-1"></div>
So I need to query this banner, where XXX is any digit number.
How to do that? Currently I use this way:
//div[contains(#id,'banner-') and contains(#id,'-1')]
But this way is not good if XXX starts with 1. So, is there any way to do like this: //div[contains(#id,'banner-' + <any_decimal> + '-1')]?
It seems match operator on popular Chrome plugin XPath Helper does not work, so I use v1.0
https://chrome.google.com/webstore/detail/xpath-helper/hgimnogjllphhhkhlmebbmlgjoejdpjl?hl=en
XPath 1.0
This XPath 1.0 expression,
//div[ starts-with(#id,'banner-')
and translate(substring(#id, 8, 3), '0123456789', '') = ''
and substring(#id, 11) = '-1']
selects all div elements whose id attribute value
starts with banner-,
followed by 3 digits, which a translate() trick mapped to nothing,
followed by -1,
as requested.
XPath 2.0
This XPath 2.0 expression,
//div[matches(#id,'^banner-\d{3}-1$')]
selects all div elements whose id attribute value matches the shown regex and
starts (^) with banner-,
followed by 3 digits, (\d{3}),
and ends ($) with -1,
as requested.

XSLT white space in concat

I have the following code
<xsl:value-of select="concat(string($var15_cond_result_exists), string($var16_cond_result_exists))"/>
which is concatenating 2 strings. Examle John and Smith to JohnSmith.
What i want is a space between first name and last name.
I can do this with adding ,' ', between them in concat. Howered there is posibility that there is no first name or last name so I don't need the white space.
How can i solve this problem?
Is it possible to use some conditions or there is easier solution.
Wrap the concat in normalize-space() which will trim any excess spaces at the start or end
<xsl:value-of
select="normalize-space(concat(string($var15_cond_result_exists), ' ', string($var16_cond_result_exists)))"/>
Note, you may be able to drop the string function inside the concat. Try this too
<xsl:value-of
select="normalize-space(concat($var15_cond_result_exists, ' ', $var16_cond_result_exists))"/>
You don't say which XSLT version you are using. In XSLT 2.0 you can do
<xsl:value-of select="$var15_cond_result_exists, $var16_cond_result_exists"/>
which will automatically insert a space if and only if both items exist. The conversion to string is automatic in both 1.0 and 2.0.

Xpath search for duplicate

I have the following xml:
<log>
<logentry revision="11956">
<author>avijendran</author>
<date>2013-05-20T10:25:19.678089Z</date>
<msg>
JIRA-1263 - did something
</msg>
</logentry>
<logentry revision="11956">
<author>avijendran</author>
<date>2013-05-20T10:25:19.678089Z</date>
<msg>
JIRA-1263 - did something 22 again
</msg>
</logentry>
</log>
I want to ignore any occurrence of the JIRA-1263 after the first one.
The xpath I am trying is (Which works if the duplicates nodes are following. But if you have duplicates else where(deep down), then it is ignored:
<xsl:variable name="uniqueList" select="//msg[not(normalize-space(substring-before(., '
')) = normalize-space(substring-before(following::msg, '
')))]" />
If you want to get each msg use //msg[starts-with(normalize-space(.), 'JIRA-1263')] to get output JIRA-1263 - did something and JIRA-1263 - did something 22 again.
And if you want to get any element with same codition use //*[starts-with(normalize-space(.), 'JIRA-1263')] which give same result as previous one.
At the end, if you want to get first msg with same condition use //logentry/msg[starts-with(normalize-space(.), 'JIRA-1263')][not(preceding::msg)] to get output JIRA-1263 - did something
You can define a key at the top level of your stylesheet that groups log entries by their first word:
<xsl:key name="logentryByCode" match="logentry"
use="substring-before(normalize-space(msg), ' ')" />
Now you need to select all logentry elements where either
the msg does not start JIRA-nnnn (where nnnn is a number) or
this entry is the first one whose msg starts with this word (i.e. the first occurrence of "JIRA-1234 - anything" for each ticket number)
(note that these two conditions need not be mutually exclusive):
<xsl:variable name="uniqueList" select="log/logentry[
(
not(
starts-with(normalize-space(msg), 'JIRA-') and
boolean(number(substring-before(substring(normalize-space(msg), 6), ' ')))
)
)
or
(
generate-id() = generate-id(key('logentryByCode',
substring-before(normalize-space(msg), ' '))[1])
)
]/msg" />
The boolean(number(...)) part checks whether a string of text can be parsed as a valid non-zero number (the text in this case being the part of the first word of the message that follows JIRA-), and the generate-id trick is a special case of the technique known as Muenchian grouping.
Equally, you could group the msg elements instead of the logentry elements, using match="msg" in the key definition and normalize-space(.) instead of normalize-space(msg).
And here another interpretation of what you try to do.
Find any first logentry which start with JIRA-XXXX.
If this it right try this:
log/logentry[
starts-with(normalize-space(msg), 'JIRA-') and
not
(
substring-before( normalize-space(msg), ' ')= substring-before( normalize-space(preceding::msg), ' ')
)]
This will find any logentry which starts with JIRA- but has not preceding one with the same substring before the first space (JIRA-XXXX) in your example.

How to remove character from string using xslt?

<Scheduled>
<xsl:value-of select="//RequestParameters/Identifier/DepartureDate">
</xsl:value-of>
</Scheduled>
In this xslt code iam getting a last character as 'z' in "//RequestParameters/Identifier/DepartureDate" i want to remove z and please help on this.
If the value of //RequestParameters/Identifier/DepartureDate contains 'z' only at the end, you can use substring-before function.
<xsl:value-of select="substring-before(//RequestParameters/Identifier/DepartureDate, 'z')">
edit:
If you want to get the first 10 characters of the value, you can use substring function.
<xsl:value-of select="substring(//RequestParameters/Identifier/DepartureDate, 1, 10)">
In general, you may want to convert an element value in ISO 8601 date format to another format by adding a javascript function to your xslt, and call that function in your Xpath expression.
For instance, when you have added a (javascript) function convertToDate that extracts the date part of the input value in the format yyyymmdd, the Xpath expression
convertToDate (//RequestParameters/Identifier/DepartureDate)
will result in a value
20111016
assuming there is only one DepartureDate element in the input, having value
2011-10-16T09:40:00.000Z

Find number of characters matching pattern in XSLT 1

I need to make an statement where the test pass if there is just one asterisk in a string from the source document.
Thus, something like
<xslt:if test="count(find('\*', #myAttribute)) = 1)>
There is one asterisk in myAttribute
</xslt:if>
I need the functionality for XSLT 1, but answers for XSLT 2 will be appreciated as well, but won't get acceptance unless its impossible in XSLT 1.
In XPath 1.0, we can do it by removing all asterisks using translate and comparing the length:
string-length(#myAttribute) - string-length(translate(#myAttribute, '*', '')) = 1
In XPath 2.0, I'd probably do this:
count(string-to-codepoints(#myAttribute)[. = string-to-codepoints('*')]) = 1
Another solution that should work in XPath 1.0:
contains(#myAttribute, '*') and not(contains(substring-after(#myAttribute, '*'), '*'))