计算XSLT中的不同项目并仅列出一次

时间:2010-07-16 15:24:59

标签: xslt xslt-grouping xslkey

我有以下XML:

<assessment>
    <section>
        <item>
            <attributes>
                <variables>
                    <variable>
                        <variable_name value="MORTIMER"/>
                    </variable>
                </variables>
            </attributes>
        </item>
        <item>
            <attributes>
                <variables>
                    <variable>
                        <variable_name value="FRED"/>
                    </variable>
                </variables>
            </attributes>
        </item>
        <item>
            <attributes>
                <variables>
                    <variable>
                        <variable_name value="MORTIMER"/>
                    </variable>
                </variables>
            </attributes>
        </item>
    </section>
</assessment>

我有以下XSLT来处理该XML:

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

 <xsl:key name="kValueByVal" match="item//variables//variable_name" 
          use="@value"/>

 <xsl:template match="assessment">
     <xsl:for-each select="
      .//item//variables//variable_name/@value
      ">
        <xsl:value-of select=
        "concat(., ' ', count(key('kValueByVal', .)), '&#xA;')"/>
         <br/>
     </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

它输出以下内容,这几乎是我想要的:

MORTIMER 2
FRED 1
MORTIMER 2

它列出了每个variable_names以及每个variable_names发生的次数。唯一的问题是,每次发生variable_name而不是只发生一次时,它会给这个计数一次。

这就是我想要输出的内容:

MORTIMER 2
FRED 1

如何修改XSLT代码以便为我提供?请注意,我们正在使用XSLT 1.0。

以下解决方案看起来应该可行,但不输出任何内容:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:key name="kValueByVal" match="item//variables//variable_name"
          use="@value"/>

 <xsl:template match="assessment">
     <xsl:for-each select=".//item//variables//variable_name/@value[generate-id()
                                                                    =
                                                                    generate-id(key('kValueByVal',.)[1])]">
        <xsl:value-of select=
        "concat(., ' ', count(key('kValueByVal', .)), '&#xA;')"/>
         <br/>
     </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

5 个答案:

答案 0 :(得分:2)

你真的需要了解Muenchian分组是如何工作的,否则你会永远地问相同问题的变体。

请阅读 Jeni Tennison's tutorial

以下是您最新问题的解决方案:

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

 <xsl:key name="kVarNameByVal" match="variable_name"
          use="@value"/>

 <xsl:template match=
  "variable_name[generate-id()
                =
                 generate-id(key('kVarNameByVal', @value)[1])
                ]
  ">
        <xsl:value-of select=
        "concat(@value, ' ', count(key('kVarNameByVal', @value)), '&#xA;')"/>
         <br/>
 </xsl:template>
</xsl:stylesheet>

在提供的XML文档上执行此转换时,将生成所需的结果:

MORTIMER 2
FRED 1

答案 1 :(得分:1)

看到你正在使用XSLT 2.0,我会使用内置的grouping features。 (对于早期版本,您可能希望查看Muenchian分组。)

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

 <xsl:key name="kValueByVal" match="item//variables//variable_name" 
          use="@value"/>

 <xsl:template match="assessment">
     <xsl:for-each-group select=".//item//variables//variable_name" group-by="@value">
                <xsl:value-of select="concat(current-grouping-key(), ' ', count(current-group()), '&#xA;')"/>
        <br/>
     </xsl:for-each-group>
 </xsl:template>
</xsl:stylesheet>

答案 2 :(得分:1)

你得到的是你要求的:

<xsl:for-each select=".//item//variables//variable_name/@value"> 

这意味着:对于这些属性中的每一个

分组时,您必须说:对于这些中的每一种

而且,你怎么知道这是独一无二的?用Muenchian方法:

<xsl:for-each select=".//item//variables//variable_name/@value[generate-id()
                                                               =
                                                               generate-id(key('kValueByVal',.)[1])]">

这意味着:那些是第一个拥有该密钥的人。

编辑:另外,当您知道输入架构时,请避免//

编辑:现在我可以看到你改变了密钥...那么,对于你的新密钥,谁是第一个?是! variable_name元素:

<xsl:for-each select=".//item//variables//variable_name[generate-id()
                                                        =
                                                        generate-id(key('kValueByVal',@value)[1])]">

答案 3 :(得分:1)

这将在XSLT 1.0中完成。

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

 <xsl:key name="kValueByVal" match="item//variables//variable_name" 
          use="@value"/>

 <xsl:template match="assessment">
     <xsl:for-each select="
      //item//variables//variable_name[not(@value=ancestor::item/preceding-sibling::item//variables//variable_name/@value)]
      ">
        <xsl:value-of select=
        "concat(@value, ' ', count(key('kValueByVal', @value)), '&#xA;')"/>
         <br/>
     </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

我得到的输出是

MORTIMER 2
<br />FRED 1
<br />

请注意,它假定了一些关于文档结构(祖先:: item位)的更多内容,但您应该可以从那里获取它。

答案 4 :(得分:0)

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:key name="kValueByVal" match="item//variables//variable_name" 
          use="@value"/>

 <xsl:template match="assessment">
     <xsl:for-each 
              select="//item//variables//variable_name[
                          generate-id() = 
                              generate-id(key('kValueByVal', @value)[1])]">
        <xsl:value-of select=
        "concat(./@value, ' ', count(key('kValueByVal', ./@value)), '&#xA;')"/>
         <br/>
     </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>