如何计算节点中的不同值?
Posted
技术标签:
【中文标题】如何计算节点中的不同值?【英文标题】:How to count distinct values in a node? 【发布时间】:2010-09-14 06:25:03 【问题描述】:如何在 XSLT 中计算节点中的不同值?
示例:我想统计 Country 节点中现有国家的数量,在本例中为 3。
<Artists_by_Countries>
<Artist_by_Country>
<Location_ID>62</Location_ID>
<Artist_ID>212</Artist_ID>
<Country>Argentina</Country>
</Artist_by_Country>
<Artist_by_Country>
<Location_ID>4</Location_ID>
<Artist_ID>108</Artist_ID>
<Country>Australia</Country>
</Artist_by_Country>
<Artist_by_Country>
<Location_ID>4</Location_ID>
<Artist_ID>111</Artist_ID>
<Country>Australia</Country>
</Artist_by_Country>
<Artist_by_Country>
<Location_ID>12</Location_ID>
<Artist_ID>78</Artist_ID>
<Country>Germany</Country>
</Artist_by_Country>
</Artists_by_Countries>
【问题讨论】:
【参考方案1】:如果您的文档很大,您可能希望使用通常用于分组的“Muenchian 方法”来识别不同的节点。声明一个键,通过不同的值来索引您想要计数的事物:
<xsl:key name="artists-by-country" match="Artist_by_Country" use="Country" />
然后您可以使用以下方式获取具有不同国家/地区的<Artist_by_Country>
元素:
/Artists_by_Countries
/Artist_by_Country
[generate-id(.) =
generate-id(key('artists-by-country', Country)[1])]
您可以通过将其包装在对count()
函数的调用中来计算它们。
当然在 XSLT 2.0 中,它就这么简单
count(distinct-values(/Artists_by_Countries/Artist_by_Country/Country))
【讨论】:
我的眼睛在上面的一堆线条上闪闪发光,然后我在最后找到了金块【参考方案2】:在 XSLT 1.0 中这并不明显,但以下内容应该让您了解需求:
count(//Artist_by_Country[not(Location_ID=preceding-sibling::Artist_by_Country/Location_ID)]/Location_ID)
XML 中的元素越多,所需的时间就越长,因为它会检查每个元素的每个前面的兄弟元素。
【讨论】:
不确定性能,但对于 XSLT 1.0,这似乎比在投票最多的解决方案中要求试试这样的:
count(//Country[not(following::Country/text() = text())])
“给我所有 Country 节点的计数,没有以下 Country 和匹配的文本”
IMO 这个表达式的有趣之处在于 following 轴。
您也可以删除第一个/text()
,并将第二个替换为.
【讨论】:
这仅在节点已排序并且类似的 Country 值因此是连续的情况下才有效。 不,它总是有效的。 following:: 作用于整个文档,如果上下文之一之后有任何国家具有相同的值,则该节点将不被计算在内。 这应该是公认的答案,尽管 2.0 选项非常适合可以使用它的人。【参考方案4】:如果您在第一次出现国家/地区时可以控制 xml 生成,则可以向国家节点添加一个属性,例如 distinct='true' 将国家标记为“已使用”,如果您随后不添加 distinct 属性再次遇到那个国家。
你可以这样做
<xsl:for-each select="Artists_by_Countries/Artist_by_Country/Country[@distinct='true']" />
【讨论】:
以上是关于如何计算节点中的不同值?的主要内容,如果未能解决你的问题,请参考以下文章
在 XSLT 中,如何计算给定属性值的每个不同值出现在输入 XML 中的次数?