XSLT对于每个出现的子节点都有重复的父元素,但只有其后继兄弟

时间:2018-10-24 11:55:33

标签: 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>   

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

1 个答案:

答案 0 :(得分:1)

在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>或{ {1}},而不是<xsl:element name="{name(..)}">