分组和计数两个XML元素使用XSLT。

huangapple go评论57阅读模式
英文:

Grouping & counting by two XML elements with XSLT

问题

以下是您要求的XSLT代码,以实现按姓氏和年龄进行分组和计数:

<xsl:key name="custs-by-lastname-age" match="cust" use="concat(lastname, '|', age)"/>

<xsl:template match="/">
    <html>
        <body>
            <table border="1">
                <tr>
                    <th>Name</th>
                    <th>Age</th>
                    <th>#</th>
                </tr>
                <xsl:for-each select="/root/cust[count(. | key('custs-by-lastname-age', concat(lastname, '|', age))[1]) = 1]">
                    <xsl:sort select="lastname"/>
                    <tr>
                        <td>
                            <xsl:value-of select="lastname"/>
                        </td>
                        <td>
                            <xsl:value-of select="age"/>
                        </td>
                        <td>
                            <xsl:value-of select="count(key('custs-by-lastname-age', concat(lastname, '|', age)))"/>
                        </td>
                    </tr>
                </xsl:for-each>
            </table>
        </body>
    </html>
</xsl:template>

这将按照姓氏和年龄进行分组和计数,以实现您所期望的输出。

英文:

This is my input XML:

&lt;root&gt;
	&lt;cust&gt;
		&lt;firstname&gt;bob&lt;/firstname&gt;
		&lt;lastname&gt;smith&lt;/lastname&gt;
		&lt;age&gt;40&lt;/age&gt;
	&lt;/cust&gt;
	&lt;cust&gt;
		&lt;firstname&gt;joe&lt;/firstname&gt;
		&lt;lastname&gt;smith&lt;/lastname&gt;
		&lt;age&gt;75&lt;/age&gt;
	&lt;/cust&gt;
	&lt;cust&gt;
		&lt;firstname&gt;joe&lt;/firstname&gt;
		&lt;lastname&gt;brown&lt;/lastname&gt;
		&lt;age&gt;25&lt;/age&gt;
	&lt;/cust&gt;
	&lt;cust&gt;
		&lt;firstname&gt;pete&lt;/firstname&gt;
		&lt;lastname&gt;smith&lt;/lastname&gt;
		&lt;age&gt;40&lt;/age&gt;
	&lt;/cust&gt;
&lt;/root&gt;

Runnning it through the following XSLT:

&lt;xsl:key name=&quot;custs-by-lastname&quot; match=&quot;cust&quot; use=&quot;lastname&quot;/&gt;

&lt;xsl:template match=&quot;/&quot;&gt;
	&lt;html&gt;&lt;body&gt;
		&lt;table border=&quot;1&quot;&gt;
			&lt;tr&gt;&lt;th&gt;Name&lt;/th&gt;&lt;th&gt;#&lt;/th&gt;&lt;/tr&gt;
			&lt;xsl:for-each select=&quot;/root/cust[count(. | key(&#39;custs-by-lastname&#39;, lastname)[1]) = 1]&quot;&gt;
				&lt;xsl:sort select=&quot;lastname&quot;/&gt;
				&lt;tr&gt;
					&lt;td&gt;&lt;xsl:value-of select=&quot;lastname&quot;/&gt;&lt;/td&gt;
					&lt;td&gt;&lt;xsl:value-of select=&quot;count(key(&#39;custs-by-lastname&#39;, lastname))&quot;/&gt;&lt;/td&gt;
				&lt;/tr&gt;
			&lt;/xsl:for-each&gt;
		&lt;/table&gt;
	&lt;/body&gt;&lt;/html&gt;
&lt;/xsl:template&gt;

will result in this output:

Name   #
brown  1
smith  3

So what the XSLT does is grouping by lastname and counting.

What I would like to achieve is this output (order unimportant):

Name   Age  #
smith  40   2
brown  25   1
smith  75   1 

so grouping by lastname AND age.

I've tried to fiddle with combining lastname and age in the key-function, but I was unable to come up with a solution.

答案1

得分: 2

如果你想按姓名和年龄进行分组,那么请使用姓名和年龄的连接作为键值:

XSLT 1.0

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

<xsl:key name="cust" match="cust" use="concat(lastname, age)"/>

<xsl:template match="/root">
    <html>
        <body>
            <table border="1">
                <tr>
                    <th>姓名</th>
                    <th>年龄</th>
                    <th>#</th>
                </tr>
                <xsl:for-each select="cust[count(. | key('cust', concat(lastname, age))[1]) = 1]">
                    <xsl:sort select="lastname"/>
                    <tr>
                        <td>
                            <xsl:value-of select="lastname"/>
                        </td>
                        <td>
                            <xsl:value-of select="age"/>
                        </td>
                        <td>
                            <xsl:value-of select="count(key('cust', concat(lastname, age)))"/>
                        </td>
                    </tr>
                </xsl:for-each>
            </table>
        </body>
    </html>
</xsl:template>

</xsl:stylesheet>

请注意,这假设没有以数字结尾的姓名。通常,连接的键值会包含一个分隔符(例如 concat(lastname, '|', age))以防止误匹配。

英文:

If you want to group by name and age, then use the concatenation of name and age as the key value:

XSLT 1.0

&lt;xsl:stylesheet version=&quot;1.0&quot; 
xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt;

&lt;xsl:key name=&quot;cust&quot; match=&quot;cust&quot; use=&quot;concat(lastname, age)&quot;/&gt;

&lt;xsl:template match=&quot;/root&quot;&gt;
	&lt;html&gt;
		&lt;body&gt;
			&lt;table border=&quot;1&quot;&gt;
				&lt;tr&gt;
					&lt;th&gt;Name&lt;/th&gt;
					&lt;th&gt;Age&lt;/th&gt;
					&lt;th&gt;#&lt;/th&gt;
				&lt;/tr&gt;
				&lt;xsl:for-each select=&quot;cust[count(. | key(&#39;cust&#39;, concat(lastname, age))[1]) = 1]&quot;&gt;
					&lt;xsl:sort select=&quot;lastname&quot;/&gt;
					&lt;tr&gt;
						&lt;td&gt;
							&lt;xsl:value-of select=&quot;lastname&quot;/&gt;
						&lt;/td&gt;
						&lt;td&gt;
							&lt;xsl:value-of select=&quot;age&quot;/&gt;
						&lt;/td&gt;
						&lt;td&gt;
							&lt;xsl:value-of select=&quot;count(key(&#39;cust&#39;, concat(lastname, age)))&quot;/&gt;
						&lt;/td&gt;
					&lt;/tr&gt;
				&lt;/xsl:for-each&gt;
			&lt;/table&gt;
		&lt;/body&gt;
	&lt;/html&gt;
&lt;/xsl:template&gt;

&lt;/xsl:stylesheet&gt;

Note that this assumes that no name ends with a digit. Usually, a concatenated key value will include a separator (e.g. concat(lastname, &#39;|&#39;, age) to prevent false matches.

huangapple
  • 本文由 发表于 2023年6月27日 21:41:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/76565485.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定