使用xslt的多标记字符串的唯一值

时间:2012-02-28 04:46:12

标签: xslt

我有xml喜欢

<programs>
 <program name="breaking laws" id="97;#ttt;#98;#tpl;#41;#fel" />
   <program name="advanced technology" id="89;#hjk;#95;#uio;#81;#lpk" />
 <program name="Emerging companies " id="88;#ple;#98;#tpl;#41;#fel" />
 <program name="breakinglaws" id="97;#ttt" />
 <program name="breakinglaws" id="97;#ttt;#98;#tpl;#81;#lpk" />
 <program name="breakinglaws" id="99;#hklo;#95;#uio" />
</programs>

我想使用xslt 1.0找到所有唯一的id文本,即

TTT TPL 魔 赫尔辛基 UIO LPK PLE hklo

我试图使用键和输出标记做某事

<xsl:template name="output-tokens">
        <xsl:param name="list" />
        <xsl:variable name="newlist" select="concat(normalize-space($list), ' ')" />
        <xsl:variable name="first" select="substring-before($newlist, ';#')" />
        <xsl:variable name="remaining" select="substring-after($newlist, ';#')" />
        <id>
            <xsl:value-of select="$first" />
        </id>
        <xsl:if test="$remaining">
            <xsl:call-template name="output-tokens">
                <xsl:with-param name="list" select="$remaining" />
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

1 个答案:

答案 0 :(得分:1)

这是一个解决方案

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="/programs">
      <!-- Variable containing concateneated list of all program elements**
      <xsl:variable name="allprograms">
         <xsl:apply-templates select="program"/>
      </xsl:variable>

      <!-- Call recursive template to split the list -->
      <xsl:call-template name="output-tokens">
         <xsl:with-param name="list" select="$allprograms" />
      </xsl:call-template>
   </xsl:template>

   <!-- Template used to concatenate all program elements -->
   <xsl:template match="program">
      <xsl:value-of select="concat(@id, ';#') "/>
   </xsl:template>

   <!-- Recursive template to split out list into unique elements -->
   <xsl:template name="output-tokens">
      <!-- List to split -->
      <xsl:param name="list"/>
      <!-- List of all currently processed elements -->
      <xsl:param name="newlist" select="';#'" />

      <!-- Get first variable in list, and also the remaining part of the list -->
      <xsl:variable name="first" select="substring-before($list, ';#')"/>
      <xsl:variable name="remaining" select="substring-after($list, ';#')"/>

      <!-- Check if first variable is not a number, and is not contained in currently processed list -->
      <xsl:if test="number($first) != number($first) and not(contains($newlist, concat(';#', $first, ';#')))">
         <id>
            <xsl:value-of select="$first"/>
         </id>
      </xsl:if>

      <!-- If there are still elements left in the list, call the template recursively -->
      <xsl:if test="$remaining">
         <xsl:call-template name="output-tokens">
            <xsl:with-param name="list" select="$remaining"/>
            <xsl:with-param name="newlist" select="concat($newlist, $first, ';#')"/>
         </xsl:call-template>
      </xsl:if>
   </xsl:template>
</xsl:stylesheet>

这个想法是你首先建立一个包含所有连接在一起的程序元素的字符串。然后调用一个递归模板,该模板从列表中获取第一个元素,然后检查它是否尚未处理(这是通过包含已处理元素变量的模板实现的)

当XSLT应用于您的示例XML时,将输出以下内容:

<id>ttt</id>
<id>tpl</id>
<id>fel</id>
<id>hjk</id>
<id>uio</id>
<id>lpk</id>
<id>ple</id>
<id>hklo</id>