XSLT删除重复项并选择更高的值

时间:2019-06-18 08:33:58

标签: xslt xslt-1.0 xslt-2.0 xslt-grouping muenchian-grouping

我是XSLT的新手,并且正在寻求帮助,以根据其子级的组合值从xml文档中删除async function filterByAllowedDomain(context) { var domains = await context.tables('domains') .where({ allowed: true }) .read(); var categories = await context.tables('categories') .where(function (ids) { return this.domainId in ids; }, domains.map(d => d.id)) .read(); context.query.where(function (ids) { return this.categoryId in ids; }, categories.map(c => c.id)); return context.execute(); } 的重复项。必须从具有相同值的每一组元素中输出tables的最大值的元素。下面是我的示例xml文档和相应的所需输出。

<EMP>

所需的输出(基于合并的AIB_Position/AIB<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元素):

<Emp_Name>

2 个答案:

答案 0 :(得分:1)

我认为您想要这样(直接使用XPath 2.0 max() function ):

<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>

答案 1 :(得分:0)

在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详细介绍了如何在字符串X-LT 2中实现字符串组合,从而在XSLT 2中实现XSLT 3的组合分组密钥。