xml - 每组的 XSLT 最大值
问题描述
我有 xml 中的数据,其中列出了产品及其价格。寻找可以帮助我为每种产品获得最高价格的 XSLT。尝试了可能的事情,但没有运气。请帮忙。
<?xml version="1.0" encoding="UTF-8"?>
<root>
<Product>
<name>P1</name>
<price>10</price>
</Product>
<Product>
<name>P1</name>
<price>20</price>
</Product>
<Product>
<name>P2</name>
<price>5</price>
</Product>
<Product>
<name>P3</name>
<price>8</price>
</Product>
<Product>
<name>P1</name>
<price>30</price>
</Product>
</root>
预期产出
Product Price
P1 30
P2 5
P3 8
解决方案
使用XSLT 2.0非常简单:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="text"/>
<xsl:template match="root">
<xsl:text>Product Price
</xsl:text>
<xsl:for-each-group select="Product" group-by="name">
<xsl:value-of select="concat(current-grouping-key(),
' ', max(current-group()/price), '
')"/>
</xsl:for-each-group>
</xsl:template>
</xsl:transform>
如您所见,需要一个for-each-group
循环,选择Product
元素并根据子name
元素的值对它们进行分组。
在循环内部,current-grouping-key()
函数提供当前组的键(name
元素的值)并max(current-group()/price)
计算最大价格。
有关工作示例,请参见http://xsltransform.net/pNEhB3c
按照您对 XSLT 版本的评论进行编辑
您的任务也可以在XSLT 1.0中完成,使用所谓的 Muenchian Grouping(有关更详细的描述,请在 Web 上搜索)。
首先要做的是创建一个key,将要分组的元素(Product)放在某个分组键(在我们的例子中 为 name)下:
<xsl:key name="prods" match="Product" use="name"/>
然后可以在for-each
循环中执行实际的分组,使用带有Muenchian Grouping 习语的谓词:
[generate-id()=generate-id(key('prods', name)[1])]
另一个难点是XSLT 1.0的功能非常有限,甚至没有max
功能。
为了规避这个限制,我们必须编写一个模板 (我称之为最大值),它接受一系列元素,对它们进行排序(降序)并输出第一个(最大值)值。
为当前组price
中所有
元素的子元素调用此模板。Product
所以整个脚本如下所示:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text"/>
<xsl:key name="prods" match="Product" use="name"/>
<xsl:template match="root">
<xsl:text>Product Price
</xsl:text>
<xsl:for-each select="Product[generate-id()=
generate-id(key('prods', name)[1])]">
<xsl:value-of select="concat(name, ' ')"/>
<xsl:call-template name="maximum">
<xsl:with-param name="src" select="key('prods', name)/price"/>
</xsl:call-template>
<xsl:value-of select="'
'"/>
</xsl:for-each>
</xsl:template>
<xsl:template name="maximum">
<xsl:param name="src"/>
<xsl:for-each select="$src">
<xsl:sort select="." data-type="number" order="descending"/>
<xsl:if test="position()=1">
<xsl:value-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:transform>
有关工作示例,请参见http://xsltransform.net/pNEhB3c/1
推荐阅读
- vtk - 使用 VTK 格式在单元中心定义数据
- php - Google Analytics 报告 API 仅返回一行
- kubernetes - 在 Kubernetes 上复制命令 crash pod startup
- c# - C# 程序崩溃,因为列表框项目更改
- azure-webjobs - VS2017 Azure WebJob 扩展 - 如何部署 TimerTrigger WebJob?
- c# - 如何使用 Ical.Net 提取数据?
- knockout.js - knockout.js - 组件注册
- talend - 如何在 Talend open studio 7.1.1 中更改日志级别属性
- java - 使用 Spring @Value for Pool size 的线程池无法正常运行
- linux - swi SYS_ERROR0 在 arm linux 内核中做了什么?