如何使用xslt中分隔符的索引解析分隔的字符串?

时间:2010-12-24 14:13:36

标签: xslt xslt-1.0

我有一个分隔的字符串,如下所示

FirstName&LastName&Address1&Address2&City&State&country&

我需要根据分隔符的出现次数来分割字符串。

说,如果我需要字符串中的前四个值,我应该得到输出 两个不同的变量,其中第一个变量应该有字符串 前四个值和第二个变量具有剩余的字符串。

我不想使用exslt或任何其他扩展名。 请帮我一个简单的解决方案。

    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>

1 个答案:

答案 0 :(得分:2)

此转化

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

应用于此XML文档时

<t>FirstName&amp;LastName&amp;Address1&amp;Address2&amp;City&amp;State&amp;country&amp;</t>

生成所需的两个字符串,这些字符串是在第四个/t/text()分隔符处拆分&amp;而产生的:

<t1>FirstName&amp;LastName&amp;Address1&amp;Address2&amp;</t1>
<t2>City&amp;State&amp;country&amp;</t2>

您可以定义一个变量,例如vrtfSplitResult,其主体是将模板应用于包含该字符串的文本节点的结果。然后,如果您可以使用xxx:node-set()扩展名,则要定义的两个变量是:

<xsl:variable name="requiredString" 
     select="xxx:node-set($vrtfSplitResult)/*/t1">

<xsl:variable name="remainingString" 
     select="xxx:node-set($vrtfSplitResult)/*/t2">

如果您甚至不允许使用xxx:node-set()扩展功能,那么您应该使用类似的命名模板:getStartingString。这几乎是上面splitAt模板的逻辑:

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

将此转换应用于同一XML文档时,会再次生成所需的正确结果

<t>
    <t1>FirstName&amp;LastName&amp;Address1&amp;Address2&amp;</t1>
    <t2>City&amp;State&amp;country&amp;</t2>
</t>