合并具有相同属性的元素

时间:2018-02-17 12:56:23

标签: xml xslt xpath xquery

我有一个xml文档:

<bans>
  <ban job="gh:test/test#1">
    <login>user1</login>
    <reason>reason one</reason>
  </ban>
  <ban job="gh:test/test#1">
    <login>user1</login>
    <reason>reason two</reason>
  </ban>
  <ban job="gh:test/test#1">
    <login>user2</login>
    <reason>reason three</reason>
  </ban>
  <ban job="gh:test/test#2">
    <login>user1</login>
    <reason>reason four</reason>
  </ban>
  <ban job="gh:test/test#1">
    <login>user2</login>
    <reason>reason five</reason>
  </ban>
</bans>

如何与ban属性和job值相同的所有login元素合并xslt并从最新选择reason值?

在这个示例中,我想首先合并第二个ban元素,因为它们都有job="gh:test/test#1"<login>user1</login>,第三个是第五个,所以转换的结果应该是这样的:

<bans>
  <ban job="gh:test/test#1">
    <login>user1</login>
    <reason>reason two</reason>
  </ban>
  <ban job="gh:test/test#2">
    <login>user1</login>
    <reason>reason four</reason>
  </ban>
  <ban job="gh:test/test#1">
    <login>user2</login>
    <reason>reason five</reason>
  </ban>
</bans>

1 个答案:

答案 0 :(得分:2)

使用XSLT 3,您可以使用<xsl:for-each-group select="ban" group-by="@job, login" composite="yes">

xsl:for-each-group

  

如果存在group-bygroup-adjacent属性,则对于群体中的每个项目,计算一组分组键,如下所示:包含的表达式在group-bygroup-adjacent属性中评估;结果是雾化的;并且任何xs:untypedAtomic值都会转换为xs:string

     

如果指定了composite="yes",则只有一个分组键,其值为结果序列;否则,有一组分组键,由结果序列中存在的不同原子值组成。

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

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="bans">
      <xsl:copy>
          <xsl:for-each-group select="ban" composite="yes" group-by="@job, login">
              <xsl:copy-of select="current-group()[last()]"/>
          </xsl:for-each-group>
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

http://xsltfiddle.liberty-development.net/nbUY4ks