views:

918

answers:

2

Hi,

I need to check if a particular string contains a a particular word for example to check if, SultansOfSwing contains the word Swing.

Let me also mention that the value of the string in question is unknown. As in it can be any word so we do not know the length et cetera.

I understand I can do this by using the contains keyword.

But once I know that this word contains the Swing keyword I want to display the string without this "Swing" word.. thus effectively displaying only "SultansOf".

I have been trying to explore how I can achieve this but not getting any break through.

Could somebody please advise which keyword or function will provide this facility ? How can I remove a particular word from within a string.

Thanks for your help in advance.

Regards.

Dire

+1  A: 

I think this string replacement function is quite exhaustive:

<xsl:template name="string-replace">
  <xsl:param name="string1"     select="''" />
  <xsl:param name="string2"     select="''" />
  <xsl:param name="replacement" select="''" />
  <xsl:param name="global"      select="true()" />

  <xsl:choose>
    <xsl:when test="contains($string1, $string)">
      <xsl:value-of select="substring-before($string1, $string2)" />
      <xsl:value-of select="$replacement" />
      <xsl:variable name="rest" select="substring-after($string1, $string2)" />
      <xsl:choose>
        <xsl:when test="$global">
          <xsl:call-template name="string-replace">
            <xsl:with-param name="string1"     select="$rest" />
            <xsl:with-param name="string2"     select="$string2" />
            <xsl:with-param name="replacement" select="$replacement" />
            <xsl:with-param name="global"      select="$global" />
          </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="$rest" />
        </xsl:otherwise>
      </xsl:choose>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$string1" />
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

It's case-sensitive, mind you. In your case:

<xsl:call-template name="string-replace">
  <xsl:with-param name="string1"     select="'SultansOfSwing'" />
  <xsl:with-param name="string2"     select="'Swing'" />
  <xsl:with-param name="replacement" select="''" />
</xsl:call-template>
Tomalak
Thanks for your answer.. to explain my question better this is what I am trying to do.<xsl:variable name="test"><xsl:value-of:select="converterHelper:executeQuery($DB_QUERY_FOR_EDF, $XPATH_INTERNAL_ID)"/></xsl:variable>Now test will have the value retreieved from my SQL and java query.I want to further filter this variable value by seeing if there is a word ends with _Swing ... If it does then I remove it else I display it. I dont know what the word retreived could be.Could you help me understand this scenairo better ? How to achieve this ?Thanks
The params of this function can themselves be variables, you don't have to hard-code them, just put in the results of your external queries. If the task is just "return everything (before a certain string)" then a mere single-line XPath `substring-before(concat($variable, $stopword), $stopword)` will do.
Tomalak
+1  A: 

Given this for input:

<root>
    <song>SultansOfSwing</song>
    <song>SwingOfSultans</song>
    <song>SultansSwingOf</song>
</root>

The output of this:

<?xml version='1.0' ?>
<root>
    <swing-less-long>SultansOf</swing-less-long>
    <swing-less-long>OfSultans</swing-less-long>
    <swing-less-long>SultansOf</swing-less-long>
</root>

Can be gotten from this. Note the use of substring-before and substring-after.

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
    <xsl:output indent="yes"/>
    <xsl:template match="/">
        <root>
            <xsl:apply-templates select="root/song"/>
        </root>
    </xsl:template>
    <xsl:template match="song">
        <swing-less-long>
            <xsl:if test="contains(., 'Swing')">
                <xsl:call-template name="remove">
                    <xsl:with-param name="value" select="."/>
                </xsl:call-template>
            </xsl:if>
        </swing-less-long>
    </xsl:template>
    <xsl:template name="remove">
        <xsl:param name="value"/>
        <xsl:value-of select="concat(substring-before($value, 'Swing'), substring-after($value, 'Swing'))"/>
    </xsl:template>
</xsl:stylesheet>
lavinio
Thanks for your answer.. to explain my question better this is what I am trying to do. <xsl:variable name="test"> <xsl:value-of:select="converterHelper:executeQuery($DB_QUERY_FOR_EDF, $XPATH_INTERNAL_ID)"/> </xsl:variable> Now test will have the value retreieved from my SQL and java query. I want to further filter this variable value by seeing if there is a word ends with _Swing ... If it does then I remove it else I display it. I dont know what the word retreived could be. Could you help me understand this scenairo better ? How to achieve this ? Thanks
I remove only the _Swing part if it exists else display the complete word.
First, don't do `<xsl:variable name=><xsl:value-of select=></xsl:variable>` - instead use `<xsl:variable name= select=/>`. This is way more efficient for the XSLT engine, because you're not creating a separate document for the variable. Second, `<xsl:if test="ends-with($test, '_Swing'">` will allow you to filter the cases ending in your keyword. Third, `substring-before($test, '_Swing')` will return the portion of the string without the `_Swing` suffix. All the rest of the code is above already.
lavinio
@Dire: BTW - adding extra info right to the question saves you the copy-pasting of equivalent comments to each answer. ;-)
Tomalak
@lavino: Regarding: "This is way more efficient for the XSLT engine, because you're not creating a separate document for the variable." -- can you point me to some evidence that this is actually true? I should think that both calling conventions are equivalent internally in this case.
Tomalak
Great this really helps. I think I will try out the ends-with function and then the sub-string before function. This should help.Thanks guys for your help. Both your answers have made me understand better what xslt can do. :) Thumbs up to both of you !! Yeah I will try and keep all concerns in one question henceforth :)
@Dire: check my comment above. You can do without the "if ends-with()/else ..." logic by using the one-liner I provided there. :)
Tomalak
Cool.. yes you are right... that will work too... lesser code.. I will try that out as well :)..however I was wondering if nothing exists after the word I am trying to exclude wont it give an error ?concat(substring-before($value, 'Swing'), substring-after($value, 'Swing'))"/>As in my case nothing will exist after Swing.
and what if the word Swing doesnt exist in the word in question ? wont that throw an error ?
First I want to know if the word in question conatins swing or not.. and then apply the logic of removing.. if I apply the one liner codeconcat(substring-before($value, 'Swing'), substring-after($value, 'Swing'))"/> for a word which does not have "Swing" as its part then it will not print the word at all...
@Dire: How about this: You can actually try it out! You'll see what happens.
Tomalak
@Tomalak - `xsl:variable select=` vs `xsl:variable xsl:value-of select=` - http://markmail.org/message/mfi5f7yyoap7jc4n
lavinio
Thanks for your help guys. I am able to do the check as required. Thanks for your help all of you :)