使用xslt 2.0基于xml注释节点拆分节点

时间:2018-07-18 20:50:15

标签: xml xslt-2.0

我有一个需要一些XSLT转换的XML文档。 这是XML:

<docs>
  <!-comment->
  <doc>
     <node add="1"/>
     <node add="2"/>
     <!-comment->
     <node add="3"/>
     <node add="4"/>
     <node add="5"/>
     <!-comment->
     <node add="6"/>
     <node add="7"/>
     <node add="8"/>
  </doc>
</docs>

转换后,以上结构应如下所示:

<docs>
  <!-comment->
  <doc>
     <node add="1"/>
     <node add="2"/>
  </doc>
  <!-comment->
  <doc>
     <node add="3"/>
     <node add="4"/>
     <node add="5"/>
  </doc>
  <!-comment->
  <doc>
     <node add="6"/>
     <node add="7"/>
     <node add="8"/>
  </doc>
</docs>

到目前为止,我的代码是:

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

    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="@* | node()" mode="#all">
        <xsl:copy>
            <xsl:apply-templates select="@* , node()" mode="#current"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="docs">
       <xsl:for-each select="comment">
            <doc>
             <xsl:copy-of select="following-sibling::node[not(following-sibling::comment)]"/>
            <doc>
       <xsl:for-each>
    </xsl:template>

此代码确实复制了节点,但是它复制了注释后的所有节点(这是错误的)。从结构上讲,我可以说出我在做错什么,但是我无法提出正确的模式来对节点进行分组并相应地放置它们。而且,节点数可以针对不同的XML进行更改。

1 个答案:

答案 0 :(得分:1)

针对这些情况发明了XSLT元素xsl:for-each-group。有关更多信息,请参见https://www.saxonica.com/html/documentation/xsl-elements/for-each-group.html

我的解决方案:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>

<xsl:template match="/">
    <xsl:apply-templates/>
</xsl:template>

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

<xsl:template match="doc">
    <xsl:for-each-group select="node|comment()" group-starting-with="comment()">
       <xsl:copy-of select="current-group()[self::comment()]"/>
       <doc>
          <xsl:copy-of select="current-group()[self::element()]"/>
       </doc>
    </xsl:for-each-group>
</xsl:template>

</xsl:stylesheet>