【问题标题】:How to parse a delimited string using the index of the delimiter in xslt?如何使用 xslt 中分隔符的索引来解析分隔字符串?
【发布时间】:2010-12-24 14:13:36
【问题描述】:

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

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。请参阅我的答案以获得直接的 XSLT 1.0 解决方案。 :)

标签: xslt xslt-1.0


【解决方案1】:

这种转变

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

在第四个&amp;amp;分隔符处拆分/t/text()产生所需的两个字符串

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

【讨论】:

  • +1 好答案。我认为您可以从第二个解决方案中删除复制和粘贴 t1t2 元素。
猜你喜欢
  • 2011-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多