@Pavel_Minaev provided XPath 1.0 amd XPath 2.0 solutions that work if it is known in advance that the number of underscores is 2.
Here are solutions for a more complex problem, where the number of undrscores is not statically known (can be any number):
XPath 2.0 :
translate(substring($s, 1, index-of(string-to-codepoints($s), string-to-codepoints('_') )[last()] -1 ), '_', '' )
XSLT 1.0 :
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > <xsl:output method="text"/> <xsl:variable name="s" select="'ABC_12345_Q-10'"/> <xsl:template match="/"> <xsl:call-template name="stripLast"> <xsl:with-param name="pText" select="$s"/> </xsl:call-template> </xsl:template> <xsl:template name="stripLast"> <xsl:param name="pText"/> <xsl:param name="pDelim" select="'_'"/> <xsl:if test="contains($pText, $pDelim)"> <xsl:value-of select="substring-before($pText, $pDelim)"/> <xsl:call-template name="stripLast"> <xsl:with-param name="pText" select= "substring-after($pText, $pDelim)"/> <xsl:with-param name="pDelim" select="$pDelim"/> </xsl:call-template> </xsl:if> </xsl:template> </xsl:stylesheet>
when this conversion is applied to any XML document (not used), the desired, correct result is obtained :
ABC12345
Dimitre novatchev
source share