开发者

How to parse a delimited string using the index of the delimiter in xslt?

开发者 https://www.devze.com 2023-02-01 06:16 出处:网络
I have a delimited string which looks like below FirstName&LastName&Address1&Address2&City&State&country&

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&amp;LastName&amp;Address1&amp;Address2&amp;City&amp;State&amp;country&amp;' />

Output:

<xsl:variable name="requiredString">
FirstName&amp;LastName&amp;Address1&amp;Address2&amp;
</xsl:variable>

<xsl:variable name="remainingString">
City&amp;State&amp;country&amp;
</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="'&amp;'"/>

  <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&amp;LastName&amp;Address1&amp;Address2&amp;City&amp;State&amp;country&amp;</t>

produces the required two strings that result from splitting /t/text() at the fourth &amp; delimiter:

<t1>FirstName&amp;LastName&amp;Address1&amp;Address2&amp;</t1>
<t2>City&amp;State&amp;country&amp;</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="'&amp;'"/>

  <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&amp;LastName&amp;Address1&amp;Address2&amp;</t1>
    <t2>City&amp;State&amp;country&amp;</t2>
</t>
0

精彩评论

暂无评论...
验证码 换一张
取 消