首页 > 解决方案 > XSLT 为每个子节点的出现重复父元素,但只有其以下兄弟节点

问题描述

我的输入 XML 是

<DataArea>
  <ReceiveDelivery>
      <ReceiveDeliveryHeader>
          .....
      </ReceiveDeliveryHeader>
      <ReceiveDeliveryItem>
            ....
      </ReceiveDeliveryItem>
      <ReceiveDeliveryItem>
            ....
      </ReceiveDeliveryItem>
      <ReceiveDeliveryHeader>
          .....
      </ReceiveDeliveryHeader>
      <ReceiveDeliveryItem>
            ....
      </ReceiveDeliveryItem>
 </ReceiveDelivery>
</DataArea>

所需的输出是

<DataArea>
      <ReceiveDelivery>
          <ReceiveDeliveryHeader>
              .....
          </ReceiveDeliveryHeader>
          <ReceiveDeliveryItem>
                ....
          </ReceiveDeliveryItem>
          <ReceiveDeliveryItem>
                ....
          </ReceiveDeliveryItem>
       </ReceiveDelivery>
       <ReceiveDelivery>
          <ReceiveDeliveryHeader>
              .....
          </ReceiveDeliveryHeader>
          <ReceiveDeliveryItem>
                ....
          </ReceiveDeliveryItem>
       </ReceiveDelivery>
     </DataArea>

标题后面可以有 1 个或多个项目。我希望为每个标题和仅跟随该标题的项目复制 ReceiveDelivery 父节点。请帮忙。

感谢马丁您的投入。
我正在使用 XSLT 2.0。这是我的代码

<xsl:stylesheet version="2.0" xmlns="http://schema.infor.com/InforOAGIS/2" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns:xs="http://www.w3.org/2001/XMLSchema" >

    <xsl:output method="xml" />
    <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

    <xsl:template match="ReceiveDelivery">
    <xsl:for-each-group select="*" group-starting-with="ReceiveDeliveryHeader">
      <ReceiveDelivery>         
              <xsl:copy-of select="current-group()"/>           
         </ReceiveDelivery>    
      </xsl:for-each-group> 
    </xsl:template> 
</xsl:stylesheet>   

这是应该的吗?但输出与输入相同。能否请你帮忙?

标签: xslt

解决方案


在 XSLT 2 或 3 中,这是一个简单的分组问题,使用for-each-group group-starting-with

<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:mode on-no-match="shallow-copy"/>

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

  <xsl:template match="ReceiveDelivery">
      <xsl:for-each-group select="*" group-starting-with="ReceiveDeliveryHeader">
          <xsl:copy select="..">
              <xsl:copy-of select="current-group()"/>
          </xsl:copy>
      </xsl:for-each-group>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/94hvTA2

示例是 XSLT 3,但分组对 XSLT 2 的工作方式相同,只是您需要将 拼写xsl:mode为身份转换模板并使用显式文字结果元素<ReceiveDelivery>或 an<xsl:element name="{name(..)}">而不是<xsl:copy select="..">.


推荐阅读