我是 XSLT 的新手,正在寻求帮助,以根据其子级的组合值从 xml 文档中删除<EMP>
的重复项。从具有相同值的每组元素中,必须输出具有最高值的元素AIB_Position/AIB
。下面是我的示例 xml 文档和相应的所需输出。
<Row_entry>
<Employees>
<Emp>
<Emp_id>E1</Emp_id>
<Emp_Name>Name1</Emp_Name>
<Country>C1</Country>
<AIB_Position>
<AIB>1500</AIB>
</AIB_Position>
</Emp>
<Emp>
<Emp_id>E2</Emp_id>
<Emp_Name>Name2</Emp_Name>
<Country>C2</Country>
<AIB_Position>
<AIB>1700</AIB>
</AIB_Position>
</Emp>
<Emp>
<Emp_id>E2</Emp_id>
<Emp_Name>Name2</Emp_Name>
<Country>C2</Country>
<AIB_Position>
<AIB>1800</AIB>
</AIB_Position>
</Emp>
</Employees>
</Row_entry>
所需输出(根据组合的<Emp_id>
、<Emp_Name>
、<Country>
值删除重复的 Emp 元素(:
<Row_entry>
<Employees>
<Emp>
<Emp_id>E1</Emp_id>
<Emp_Name>Name1</Emp_Name>
<Country>C1</Country>
<AIB_Position>
<AIB>1500</AIB>
</AIB_Position>
</Emp>
<Emp>
<Emp_id>E2</Emp_id>
<Emp_Name>Name2</Emp_Name>
<Country>C2</Country>
<AIB_Position>
<AIB>1800</AIB>
</AIB_Position>
</Emp>
</Employees>
</Row_entry>
我想你想要这个(直接使用 XPath 2.0 max(( 函数(:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output indent="yes"/>
<xsl:template match="Employees">
<xsl:copy>
<xsl:for-each-group select="Emp" group-by="concat(Emp_id, '+', Emp_Name, '+', Country)">
<xsl:copy-of select="current-group()
[AIB_Position/AIB/number() = max(current-group()/AIB_Position/AIB/number())][1]"/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
如果您怀疑您的 XSLT 处理器是愚蠢的,例如多次计算 max((,请使用以下更精确的定向转换:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output indent="yes"/>
<xsl:template match="Employees">
<xsl:copy>
<xsl:for-each-group select="Emp"
group-by="concat(Emp_id, '+', Emp_Name, '+', Country)">
<xsl:copy-of select=
"for $max in max(current-group()/AIB_Position/AIB/number())
return
current-group()[AIB_Position/AIB/number() = $max][1]"/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
在 XSLT 2 或更高版本中,使用 for-each-group
,例如在 XSLT 3 中使用复合分组键,然后对每个组进行排序并输出最大值:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:output indent="yes"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="Employees">
<xsl:copy>
<xsl:for-each-group select="Emp" composite="yes" group-by="Emp_id, Emp_Name, Country">
<xsl:for-each select="current-group()">
<xsl:sort select="AIB_Position/AIB" order="descending"/>
<xsl:if test="position() = 1">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
使用支持高阶sort
函数的 XSLT 3 处理器,您可以缩短该代码以使用
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:output indent="yes"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="Employees">
<xsl:copy>
<xsl:for-each-group select="Emp" composite="yes" group-by="Emp_id, Emp_Name, Country">
<xsl:sequence select="sort(current-group(), (), function($emp) { xs:integer($emp/AIB_Position/AIB) })[last()]"/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
https://stackoverflow.com/tags/xslt-grouping/info 提供了有关如何在 XSLT 2 中通过字符串联接密钥组件来实现 XSLT 3 的复合分组键的一些详细信息(如果您仅限于 XSLT 2(。