How to parse a delimited string using the index of the delimiter in xslt?
I have a delimited string which looks like below
FirstName&LastName&Address1&Address2&City&State&country&
I need to split the string based on the index of occurrence of the delimiter.
Say, if i need the first four values in the string, i should get the output in two different variables, whe开发者_JS百科re the first variable should have the string with first four values and the second variable having the remaining string.
I don't want to use exslt or any other extensions. Please help me with a simple solution.
Input:
<xsl:variable name="index" select='4' />
<xsl:variable name="delimitedString" select='FirstName&LastName&Address1&Address2&City&State&country&' />
Output:
<xsl:variable name="requiredString">
FirstName&LastName&Address1&Address2&
</xsl:variable>
<xsl:variable name="remainingString">
City&State&country&
</xsl:variable>
This transformation:
<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:param name="pSplitIndex" select="4"/>
<xsl:template match="text()" name="splitAt">
<xsl:param name="pLeft" select="''"/>
<xsl:param name="pRight" select="."/>
<xsl:param name="pSplitAt" select="$pSplitIndex"/>
<xsl:param name="pDelim" select="'&'"/>
<xsl:choose>
<xsl:when test=
"not(string-length($pRight))
or
not(contains($pRight, $pDelim))
">
<t1>
<xsl:value-of select="concat($pLeft, $pRight)"/>
</t1>
<t2/>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="$pSplitAt = 0">
<t1><xsl:value-of select="$pLeft"/></t1>
<t2><xsl:value-of select="$pRight"/></t2>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="splitAt">
<xsl:with-param name="pLeft" select=
"concat($pLeft, substring-before($pRight, $pDelim), $pDelim)
"/>
<xsl:with-param name="pRight"
select="substring-after($pRight, $pDelim)"/>
<xsl:with-param name="pSplitAt" select="$pSplitAt -1"/>
<xsl:with-param name="pDelim" select="$pDelim"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
when applied on this XML document:
<t>FirstName&LastName&Address1&Address2&City&State&country&</t>
produces the required two strings that result from splitting /t/text()
at the fourth &
delimiter:
<t1>FirstName&LastName&Address1&Address2&</t1>
<t2>City&State&country&</t2>
You can define a variable, say vrtfSplitResult
whose body is the result of applying templates to the text node containing the string. Then, if you can use the xxx:node-set()
extension, the two variables you want to define are:
<xsl:variable name="requiredString"
select="xxx:node-set($vrtfSplitResult)/*/t1">
<xsl:variable name="remainingString"
select="xxx:node-set($vrtfSplitResult)/*/t2">
In case you are not allowed to use even the xxx:node-set()
extension function, then you should use a similar, named template: getStartingString
. This has pretty much the logic of the splitAt
template above:
<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:param name="pSplitIndex" select="4"/>
<xsl:template match="text()">
<xsl:variable name="vrequiredString">
<xsl:call-template name="getStartingString"/>
</xsl:variable>
<xsl:variable name="vremainingString" select=
"substring-after(.,$vrequiredString)"/>
<t>
<t1><xsl:value-of select="$vrequiredString"/></t1>
<t2><xsl:value-of select="$vremainingString"/></t2>
</t>
</xsl:template>
<xsl:template name="getStartingString">
<xsl:param name="pLeft" select="''"/>
<xsl:param name="pRight" select="."/>
<xsl:param name="pSplitAt" select="$pSplitIndex"/>
<xsl:param name="pDelim" select="'&'"/>
<xsl:choose>
<xsl:when test=
"not(string-length($pRight))
or
not(contains($pRight, $pDelim))
">
<xsl:value-of select="$pLeft"/>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="$pSplitAt = 0">
<xsl:value-of select="$pLeft"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="getStartingString">
<xsl:with-param name="pLeft" select=
"concat($pLeft, substring-before($pRight, $pDelim), $pDelim)
"/>
<xsl:with-param name="pRight"
select="substring-after($pRight, $pDelim)"/>
<xsl:with-param name="pSplitAt" select="$pSplitAt -1"/>
<xsl:with-param name="pDelim" select="$pDelim"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
when this transformation is applied on the same XML document, the wanted, correct result is produced again:
<t>
<t1>FirstName&LastName&Address1&Address2&</t1>
<t2>City&State&country&</t2>
</t>
精彩评论