Use ends with in XSLT v1.0
Asked Answered
K

6

24

I am trying to edit a current XSLT. The functionality I want is when the value of "//code_no" ends with 01 I want to edit the current city location. Currently this functionality does not exist. I have tried using string and substring but it gives me an error saying ends with functionality does not exist. Please help

The value coming from the xml is

<code_no>
1870410001
</code_no>

in the xsl, I want to print this when the value ends with 01.

<td align="left" width="33%"><SPAN style="font-size: 12pt; font-family: Arial;">
    <a> <b><u><xsl:value-of select="//city"/>, <xsl:value-of select="//state"/> 
    </u></b></a></SPAN></td>
Kossuth answered 7/8, 2012 at 15:2 Comment(3)
Seriously, help us to help you. You haven't posted your input XML or desired output, which makes it impossible to answer.Sazerac
currently i am getting the value of code no by using <xsl:value-of select=".//code_no"/> Now i want to use this code no and if this code no ends with 01, i want to change the default value <xsl:value-of select=".//city"/> to something elseKossuth
I mean we need to see your input XML and desired output. Please edit the question to include this. See other XSLT questions if you're not sure what sort of code you should be posting.Sazerac
R
44

The XPath 1.0 equivalent of (the XPath 2.0) expression:

ends-with($s, $t)

is:

$t = substring($s, string-length($s) - string-length($t) +1)

You need just to substitute $s and $t in the last XPath expression with, respectively, the string to be tested, and the ending to be tested.

Here is a complete example:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="x|y">
     <xsl:value-of select="name()"/> ends-with '_01': <xsl:value-of select=
     "'_01' = substring(., string-length() - 2)"/>
=============   
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on the following XML document (none was provided in the question!!!):

<t>
 <x>abcd_01</x>
 <y>abcd_11</y>
</t>

the wanted, correct result is produced:

x ends-with '_01': true
=============   
 y ends-with '_01': false
=============   
Rickirickie answered 8/8, 2012 at 3:13 Comment(3)
On my machine, the following was wrong: $t = substring($s, string-length() - string-length($t) +1) The source-string needs to be argument of the first string-length call. So this worked: $t = substring($s, string-length($s) - string-length($t) +1)Wenn
@FrederikSchøning: Yes, the expression in the answer assumes that $s is the string value of the context node (or context item). I'll correct this shortly.Rickirickie
Almost there now - just need '$s' instead of 's' in the parentheses :)Wenn
W
3

I used

contains($string, $part) and normalize-space(substring-after($string, $part)) = ''

Where

we are checking if $string ends with $part

Wrangler answered 27/2, 2014 at 12:7 Comment(4)
"we are checking if $string ends with $part" Not really. You are checking if $string ends with $part OR $string does not contain $part. When $string = "abc" and $part ="d" your test returns a false positive.Vivanvivarium
@Vivanvivarium you are right. Just edited for correcting it. Thanks for saving me a bug. Cheers :)Wrangler
That looks much better - and I believe you could shorten it to: contains($string, $part) and not(substring-after($string, $part)). See also: #21828998Vivanvivarium
if $part is in the $string more than once you get a false negativePrecocious
B
2

XSLT 1.0 uses XPath 1.0, which does not include any function named ends-with. You can fake it using the technique found here:

Beautifully answered 7/8, 2012 at 15:11 Comment(5)
i tried using <xsl:when test="code_no[substring(@code_no, string-length(@code_no) -2)='_01']"> but it gives an errorKossuth
Expected token '$' found 'NAME'. substring(-->$code<--_no, string-length($code_no)-2) = '_01'Kossuth
@user1582320: You still haven't shown us your input XML. We've seen .//code_no, @code_no, and $code_no. What does the actual input XML look like???Winger
the actual input from the xml is <code_no>324253452345 </code_no> thts all there is nothing else that i can give youKossuth
ok i got it... i used substring and took care of it. The problem was that they had initially used xmlns:start-date="urn:schemas-microsoft-com:datatypes"> which is amost incompatible with anything. so anyway thanks.Kossuth
S
2

I know this question is actually an old one, but now I was looking for the same.

However, in the end I came up with something else that may be used by someone in the future.

Please see this:

contains(concat($str1, '$'), concat($str2, '$'))

Fast, simple, no calculation required.

Example of use:

    <xsl:variable name="str1" select="string('Some text to test.')" />
    <xsl:variable name="str2" select="string('test.')" />

    <xsl:if test="contains(concat($str1, '$'), concat($str2, '$'))">
        <xsl:value-of select="concat('Yes, text: &quot;', $str1, '&quot; ends with: &quot;', $str2, '&quot;.')"/>
    </xsl:if>

Of course you can use any sign instead of $ for concat() function.

Segal answered 21/1, 2022 at 10:0 Comment(2)
This answer is similar to the one suggested by VladoS.Vivanvivarium
Indeed. Unfortunately, I missed it. However, isn't my answer clearer?Segal
C
0

Not exactly ends with, but nicer look than the substring-solution and still suitable for certain situations:

<xsl:template match="*[contains(name(), 'substr')]"/>
Chestnut answered 7/1, 2014 at 11:4 Comment(2)
It's not about looks. contains() will produce a false positive when, for example, the substring is "_01" and the string is "3_01_02".Vivanvivarium
Absolutely, but I found it easier to write and read for my situation, in which I knew 'substr' would occur at the end only.Chestnut
J
0

In special cases, if you know that some character can not be contained in tag for example § you can do this:

<xsl:if test="contains(concat(code_no,'§'),'01§')">
  <td align="left" width="33%"><SPAN style="font-size: 12pt; font-family: Arial;">
    <a> <b><u><xsl:value-of select="//city"/>, <xsl:value-of select="//state"/> 
    </u></b></a></SPAN></td>
</xsl:if>
Joplin answered 28/3, 2019 at 13:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.