XSLT substring - take all values before specific string

Question

I have elements:

<A>11511/direction=sink</A>
<B>110/direction=src</B>

Of course there are some elements without /direction suffix that is importnat to mention.

If elements A and B contain string /direction... I want to have the value before string /direction. If elements do not contain /direction then take regular value as usual. What should I add in value-of clause ?

<newElementA><xsl:value-of select="A"/></newElementA>
<newElementB><xsl:value-of select="B"/></newElementB>

I tried with <xsl:value-of select="substring-before(A,'/')"/> but then values which do not have value /direction are set with value null which is not correct

I also tried this but then getting error:

     <newelementA><xsl:value-of select="if (contains(A,'/')) 
then substring-before(A,'/') else A"/></newelementA>

I want to have values 11511and110 in result.

Thanks


Show source
| xml   | xslt   | substring   2016-12-18 16:12 2 Answers

Answers ( 2 )

  1. 2016-12-18 23:12

    If you can use XSLT 2.0 or newer, the regular-expression function replace gives you the flexibility you need.

    Example:

    <xsl:value-of select="replace(., '(.*?)/.*$', '$1')"/>
    

    I've confirmed that this produces the output you say you want for any string 1235sdfa/sdff93rjdf, and also for any string asda98273jasdf that does not contain a /.

  2. 2016-12-18 23:12

    One possibility is to use conditional processing, and choose between alternative actions depending on the content.

    For example, this input (only using A for simplicity):

    <root>
      <A>11511/direction=sink</A>
      <A>test</A>
    </root>
    

    with this stylesheet:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
      <xsl:output method="xml" indent="yes"/>
    
      <xsl:template match="root">
        <newRoot>
          <xsl:apply-templates select="*"/>
        </newRoot>
      </xsl:template>
    
      <!-- Create newElementA -->
      <xsl:template match="A">
        <newElementA>
          <xsl:call-template name="chooseContent"/>
        </newElementA>
      </xsl:template>
    
      <!-- Reusable template to determine element content -->
      <xsl:template name="chooseContent">
        <xsl:choose>
          <xsl:when test="contains(.,'/direction')">
            <xsl:value-of select="substring-before(.,'/direction')"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="."/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:template>
    
      <!-- Ignore unknown elements -->
      <xsl:template match="*"/>
    </xsl:stylesheet>
    

    results in:

    <newRoot>
      <newElementA>11511</newElementA>
      <newElementA>test</newElementA>
    </newRoot>
    
◀ Go back