在 XSLT 中,如何计算给定属性值的每个不同值出现在我的输入 XML 中的次数?

In XSLT, how do I count the number of times each distinct-value of a given attribute value appears in my input XML?

假设我有 XML 中的剧本:

<speech><speaker name="Bob">BOB</speaker> Hey Jim!</speech>
<speech><speaker name="Jim">JIM</speaker> Hey Bob!</speech>
<speech><speaker name="Bob">BOB</speaker> How's Ethel?</speech>

我想使用 XSLT 在 HTML table 中创建发言者的不同值列表,以及每个人发言的次数,如下所示:

<table>
            <tr>
               <th>Speaker</th>
               <th>Frequency</th>
            </tr>
            <tr>
               <td>Bob</td>
               <td>2</td>
            </tr>
            <tr>
               <td>Jim</td>
               <td>1</td>
            </tr> </table>

这是我的模板规则:

<xsl:template match="/">
        <html>
            <head>Speaker analysis</head>
            <body>
<h1>Table of speech frequency</h1>
            <table>
                <tr><th>Speaker</th><th>Frequency</th></tr>
                <xsl:for-each select="distinct-values(//speaker/@name)">
                    <tr><td><xsl:value-of select="."/></td>
                        <td><xsl:value-of select="count(../speech[speaker[@name='.']])"/></td></tr>
                </xsl:for-each>
            </table>
                    </body></html>
    </xsl:template>

问题在于这一行:

<td><xsl:value-of select="count(../speech[speaker[@name='.']])"/></td>

我真正想告诉它做的是“对于在此 for 循环中标识的 @name 的给定不同值,计算它在整个文档中出现的次数”。所以我认为我真的需要从该属性值向上爬回 ancestor:: 轴以计算包含它的 or 元素。但是oXygen给出了错误信息。

一定有办法做到这一点吗?

这是 grouping 的情况,而不是 distinct-values:

<xsl:for-each-group select="//speaker" group-by="@name">
    <tr>
        <td>
            <xsl:value-of select="@name"/>
        </td>
        <td>
            <xsl:value-of select="count(current-group())"/>
        </td>
    </tr>
</xsl:for-each-group>

需要 XSLT 2.0 或更高版本。


P.S。要按照您开始的方式进行操作,您需要定义一个 key 匹配 speaker by name,然后计算 key() 函数返回的序列。

另请注意,distinct-values() 函数 returns 一个独立的值序列,不属于输入树的一部分;这些值没有祖先。