Adee
Adee

Reputation: 67

substring before last space xslt

I have a name field of length 30 as below:

<Name>Rainbow Charity             </Name>
<Name>Ben Tromy Jig               </Name>

I need to substring before the last space. So I need the below using xslt:

<Name>Rainbow Charity</Name>
<Name>Ben Tromy Jig</Name>

Upvotes: 1

Views: 368

Answers (2)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243479

I. Here is a pure XSLT 1.0 solution:

<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="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="Name/text()" name="trimRight">
    <xsl:param name="pText" select="."/>
    
     <xsl:choose>
        <xsl:when test="not(substring($pText, string-length($pText)) = ' ')">
          <xsl:value-of select="$pText"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:call-template name="trimRight">
            <xsl:with-param name="pText" 
                 select="substring($pText, 1, string-length($pText) -1)"/>
          </xsl:call-template>
        </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the below XML document (derived from the OP-provided one, but with varying number of spaces in the intermediate whitespace segments):

<t>
    <Name>Rainbow   Charity             </Name>
    <Name>Ben  Tromy Jig               </Name>
</t>

The wanted, correct result is produced:

<t>
   <Name>Rainbow   Charity</Name>
   <Name>Ben  Tromy Jig</Name>
</t>

Do note: Unlike using normalize-space() which removes all spaces but one from any longest contiguous substring containing only whitespace, this solution preserves all intermediate segments of spaces.


II. An XSLT 2.0 solution:

<xsl:stylesheet version="2.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="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="Name/text()">
     <xsl:sequence select="replace(., '\s+$', '')"/>
  </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the same XML document (above), the same correct result is produced:

<t>
   <Name>Rainbow   Charity</Name>
   <Name>Ben  Tromy Jig</Name>
</t>

Upvotes: 2

al.truisme
al.truisme

Reputation: 484

I agree with @michael.hor257k

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="#all">

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="Name/text()">
    <xsl:sequence select="normalize-space(.)" />
  </xsl:template>
  
</xsl:stylesheet>

With input

<example>
  <Name>Rainbow Charity             </Name>
  <Name>Ben Tromy Jig               </Name>
</example>

produces

<example>
  <Name>Rainbow Charity</Name>
  <Name>Ben Tromy Jig</Name>
</example>

Upvotes: 1

Related Questions