Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XSLT substring - take all values before specific string

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

like image 799
Veljko Avatar asked Jul 01 '26 19:07

Veljko


2 Answers

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>
like image 178
Meyer Avatar answered Jul 04 '26 14:07

Meyer


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 /.

like image 40
Eiríkr Útlendi Avatar answered Jul 04 '26 14:07

Eiríkr Útlendi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!