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>
Kerem
  • 11,377
  • 5
  • 59
  • 58
user1582320
  • 241
  • 1
  • 2
  • 4
  • 1
    Seriously, help us to help you. You haven't posted your input XML or desired output, which makes it impossible to answer. – Mitya Aug 07 '12 at 15:04
  • currently i am getting the value of code no by using Now i want to use this code no and if this code no ends with 01, i want to change the default value to something else – user1582320 Aug 07 '12 at 15:06
  • 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. – Mitya Aug 07 '12 at 15:09

6 Answers6

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
=============   
Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
  • 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) – Frederik Struck-Schøning Jul 30 '14 at 12:32
  • 1
    @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. – Dimitre Novatchev Jul 30 '14 at 14:09
  • Almost there now - just need '$s' instead of 's' in the parentheses :) – Frederik Struck-Schøning Jul 30 '14 at 14:11
3

I used

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

Where

we are checking if $string ends with $part

Jyotsna Sonawane
  • 303
  • 1
  • 3
  • 17
  • "*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. – michael.hor257k Feb 27 '14 at 12:18
  • @michael.hor257k you are right. Just edited for correcting it. Thanks for saving me a bug. Cheers :) – Jyotsna Sonawane Feb 28 '14 at 13:04
  • 1
    That looks much better - and I believe you could shorten it to: `contains($string, $part) and not(substring-after($string, $part))`. See also: http://stackoverflow.com/questions/21828498/in-xslt-how-to-find-if-text-contains-full-stop-at-the-end/21830314#21830314 – michael.hor257k Feb 28 '14 at 16:30
  • 4
    if $part is in the $string more than once you get a false negative – Mike May 11 '15 at 12:29
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:

Community
  • 1
  • 1
Wayne
  • 59,728
  • 15
  • 131
  • 126
  • i tried using but it gives an error – user1582320 Aug 07 '12 at 15:15
  • Expected token '$' found 'NAME'. substring(-->$code<--_no, string-length($code_no)-2) = '_01' – user1582320 Aug 07 '12 at 20:07
  • @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??? – LarsH Aug 08 '12 at 02:57
  • the actual input from the xml is 324253452345 thts all there is nothing else that i can give you – user1582320 Aug 08 '12 at 14:06
  • 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. – user1582320 Aug 13 '12 at 21:17
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.

wtct
  • 167
  • 1
  • 3
0

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

<xsl:template match="*[contains(name(), 'substr')]"/>
CodeManX
  • 11,159
  • 5
  • 49
  • 70
  • 1
    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". – michael.hor257k Jan 07 '14 at 11:18
  • 1
    Absolutely, but I found it easier to write and read for my situation, in which I knew 'substr' would occur at the end only. – CodeManX Jan 07 '14 at 11:37
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>
VladoS
  • 13
  • 3