使用XSLT合并相邻的同级节点

使用XSLT合并相邻的同级节点,xslt,Xslt,我有一个问题让我头疼得厉害。请帮帮我。输入为: <body> <p class="section"> section 1 </p> <p class="code"> some code </p> <p class="code"> following code </p> <p class="code"> following code </p> <p class="sectio

我有一个问题让我头疼得厉害。请帮帮我。输入为:

<body>
 <p class="section"> section 1 </p>
 <p class="code"> some code </p>
 <p class="code"> following code </p>
 <p class="code"> following code </p>
 <p class="section"> section 2 </p>
 <p class="code"> other code </p>
 <p class="code"> following code </p>
 <p class="code"> following code </p>
 <p class="section"> section 3 </p>
 <p class="code"> still other code </p>
 <p class="code"> following </p>
 <p class="code"> following </p>
</body>
<body>
 <p class="section"> section 1 </p>
 <pre> some code following code following code </pre>
 <p class="section"> section 2 </p>
 <pre> other code following code following code </pre>
 <p class="section"> section 3 </p>
 <pre> still other code following following </pre>
</body>

第1节

<body>
 <p class="section"> section 1 
  <p class="code"> some code </p>
  <p class="code"> following code </p>
  <p class="code"> following code </p>
 </p>
 <p class="section"> section 2
  <p class="code"> other code </p>
  <p class="code"> following code </p>
  <p class="code"> following code </p>
 </p>
 <p class="section"> section 3
  <p class="code"> still other code </p>
  <p class="code"> following </p>
  <p class="code"> following </p>
 </p>
</body>

一些代码

以下代码

以下代码

第2节

<xsl:template match="body">
    <xsl:apply-templates select="p[@class='section']" />
</xsl:template>

<xsl:template match="p[@class='section']">
    <xsl:copy-of select="."/>
    <pre>
        <xsl:variable name="code" select="following-sibling::p[@class='code']" />
        <xsl:for-each select="following-sibling::p">
            <xsl:variable name="index" select="position()"/>
            <xsl:if test="generate-id(.)=generate-id($code[$index])">
                <xsl:value-of select="."/>
            </xsl:if>
        </xsl:for-each>
    </pre>
</xsl:template>

其他代码

以下代码

以下代码

第3节

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

  <xsl:output indent="yes"/>

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

  <xsl:template match="body">
    <xsl:copy>
      <xsl:for-each-group select="*" group-adjacent="boolean(self::p[@class = 'code'])">
        <xsl:choose>
          <xsl:when test="current-grouping-key()">
            <pre>
              <xsl:apply-templates select="current-group()/node()"/>
            </pre>
          </xsl:when>
          <xsl:otherwise>
            <xsl:apply-templates select="current-group()"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

还有其他代码

以下内容

以下内容

我想要的输出:


第1节

<body>
 <p class="section"> section 1 
  <p class="code"> some code </p>
  <p class="code"> following code </p>
  <p class="code"> following code </p>
 </p>
 <p class="section"> section 2
  <p class="code"> other code </p>
  <p class="code"> following code </p>
  <p class="code"> following code </p>
 </p>
 <p class="section"> section 3
  <p class="code"> still other code </p>
  <p class="code"> following </p>
  <p class="code"> following </p>
 </p>
</body>
一些代码遵循代码遵循代码 第2节

<xsl:template match="body">
    <xsl:apply-templates select="p[@class='section']" />
</xsl:template>

<xsl:template match="p[@class='section']">
    <xsl:copy-of select="."/>
    <pre>
        <xsl:variable name="code" select="following-sibling::p[@class='code']" />
        <xsl:for-each select="following-sibling::p">
            <xsl:variable name="index" select="position()"/>
            <xsl:if test="generate-id(.)=generate-id($code[$index])">
                <xsl:value-of select="."/>
            </xsl:if>
        </xsl:for-each>
    </pre>
</xsl:template>
其他代码跟随代码跟随代码跟随代码 第3节

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

  <xsl:output indent="yes"/>

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

  <xsl:template match="body">
    <xsl:copy>
      <xsl:for-each-group select="*" group-adjacent="boolean(self::p[@class = 'code'])">
        <xsl:choose>
          <xsl:when test="current-grouping-key()">
            <pre>
              <xsl:apply-templates select="current-group()/node()"/>
            </pre>
          </xsl:when>
          <xsl:otherwise>
            <xsl:apply-templates select="current-group()"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>
下面还有其他代码

问题是将所有相邻的

标记折叠成一个
标记。没有找到使用XSLT实现这一点的方法。您认为存在解决方案吗?

问题在于您的XML结构不足以满足简单XSLT解决方案的需要

不同的“部分”并不是以一种容易提取的方式设置的。如果您可以控制输入XML,请查看是否可以将其更改为以下内容:


第1节

一些代码

以下代码

以下代码

第2节

其他代码

以下代码

以下代码

第3节

还有其他代码

以下内容

以下内容


这将允许您为“section”定义一个
xsl模板,在该模板中,您可以对“code”类定义
xsl-foreach

您不需要重新生成XML,请看这里:。

类似的操作应该可以:


使用XSLT 2.0,您可以对相邻的每个组使用以下命令:



您可以将XSLT 2.0与。

结合使用,但是:混合简单的内容和元素看起来不是一个好主意;我正在尝试清理的是html。所以…挑战在于解决这个问题。我正在使用XSLT2.0和Saxon9。所以我试了一下。集成到我真正的xsl中稍微困难一些,但最终还是成功了。对于每个组,都有一个有用的XSLT2.0元素,以便更好地了解。谢谢