根据条件聚合XML节点

时间:2014-06-25 13:32:15

标签: xml xslt

我手头有一项非常简单的任务,我无法在XSLT中解决这个问题。我必须根据相邻的时间戳(ns1:ValidUntil = ns1:ValidFrom)和相等的名称(ns1:名称)聚合XML节点。

我玩过递归模板和xpath轴导航(previous-sibling / following-sibling),但我无法解决手头的问题。

对任何建议都会非常高兴。

输入XML:

<ns1:Zone>
    <ns1:ID>xyz</ns1:ID>
    <ns1:Direction>abc</ns1:Direction>

    <ns1:Elem>
        <ns1:Name>Z01</ns1:Name>
        <ns1:ValidFrom>2013-11-20T06:00:00.000+01:00</ns1:ValidFrom>
        <ns1:ValidUntil>2014-01-01T06:00:00.000+01:00</ns1:ValidUntil>
    </ns1:Elem>

    <ns1:Elem>
        <ns1:Name>Z01</ns1:Name>
        <ns1:ValidFrom>2016-01-13T06:00:00.000+01:00</ns1:ValidFrom>
        <ns1:ValidUntil>2018-11-20T06:00:00.000+01:00</ns1:ValidUntil>
    </ns1:Elem>

    <ns1:Elem>
        <ns1:Name>Z02</ns1:Name>
        <ns1:ValidFrom>2014-01-13T06:00:00.000+01:00</ns1:ValidFrom>
        <ns1:ValidUntil>2014-11-20T06:00:00.000+01:00</ns1:ValidUntil>
    </ns1:Elem>
    <ns1:Elem>
        <ns1:Name>Z02</ns1:Name>
        <ns1:ValidFrom>2014-11-20T06:00:00.000+01:00</ns1:ValidFrom>
        <ns1:ValidUntil>2015-11-20T06:00:00.000+01:00</ns1:ValidUntil>
    </ns1:Elem>

    <ns1:Elem>
        <ns1:Name>Z03</ns1:Name>
        <ns1:ValidFrom>2016-01-13T06:00:00.000+01:00</ns1:ValidFrom>
        <ns1:ValidUntil>2016-11-20T06:00:00.000+01:00</ns1:ValidUntil>
    </ns1:Elem>
</ns1:Zone>

1 个答案:

答案 0 :(得分:1)

我认为你可以分组如下:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
  xpath-default-namespace="http://example.com/ns1"
  xmlns:ns1="http://example.com/ns1"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xs">

<xsl:output indent="yes"/>

<xsl:template match="Zone">
  <xsl:copy>
    <xsl:copy-of select="* except Elem"/>
    <xsl:for-each-group select="Elem" group-adjacent="Name">
      <xsl:for-each-group select="current-group()" group-adjacent="ValidUntil = following-sibling::Elem[1]/ValidFrom or ValidFrom = preceding-sibling::Elem[1]/ValidUntil">
        <xsl:choose>
          <xsl:when test="current-grouping-key()">
            <xsl:copy>
              <xsl:copy-of select="Name"/>
              <xsl:copy-of select="ValidFrom, current-group()[last()]/ValidUntil"/>
            </xsl:copy>
          </xsl:when>
          <xsl:otherwise>
            <xsl:copy-of select="current-group()"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each-group>
    </xsl:for-each-group>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>