用于合并具有相同名称和属性值的同级元素的XSLT 2.0解决方案

Ten*_*nch 4 xslt xslt-2.0

我正在寻找一个可以转变的解决方案

<p>
<hi rend="bold">aa</hi>
<hi rend="bold">bb</hi>
<hi rend="bold">cc</hi>
Perhaps some text.
<hi rend="italic">dd</hi>
<hi rend="italic">ee</hi>
Some more text.
<hi rend="italic">ff</hi>
<hi rend="italic">gg</hi>
Foo.
</p>
Run Code Online (Sandbox Code Playgroud)

<p>
<hi rend="bold">aabbcc</hi>
Perhaps some text.
<hi rend="italic">ddee</hi>
Perhaps some text.
<hi rend="italic">ffgg</hi>
Foo. 
</p>
Run Code Online (Sandbox Code Playgroud)

但我的解决方案应该_不硬编码元素和属性值的名称(斜体,粗体).XSLT应该真正连接具有相同名称和相同属性值的所有兄弟元素.其他一切都应保持不变.

我已经看过那里已经存在的解决方案,但它们似乎都没有满足我的所有要求.

如果有人有一个方便的XSLT样式表,我会非常感激.

Sea*_*kin 6

此XSLT 2.0样式表将使用公共rend属性合并相邻元素.

<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:strip-space elements="*" />  

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

<xsl:template match="*[*/@rend]">
  <xsl:copy>
    <xsl:apply-templates select="@*" />
    <xsl:for-each-group select="node()" group-adjacent="
       if (self::*/@rend) then
           concat( namespace-uri(), '|', local-name(), '|', @rend)
         else
           ''">
      <xsl:choose>
        <xsl:when test="current-grouping-key()" >
          <xsl:for-each select="current-group()[1]">
            <xsl:copy>
              <xsl:apply-templates select="@* | current-group()/node()" />
            </xsl:copy>
          </xsl:for-each>
        </xsl:when>
        <xsl:otherwise>
         <xsl:apply-templates select="current-group()" />
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each-group>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

这个解决方案优于Martin的优点是:

  • 这将合并所有父元素,而不仅仅是p元素.
  • 快点.合并是通过单个xsl:for-each而不是两个嵌套的xsl:for-each完成的
  • 头可合并元素的非rend属性被复制到输出.

另请注意:

  • 为了确定具有公共名称和rend属性值的"相邻"元素而排除的纯空白节点的测试完全被xsl:strip-space指令所避免.因此xsl:for-each指令相当简单和可读.
  • 作为组相邻属性值的替代,您可以使用...

    <xsl:for-each-group select="node()" group-adjacent="
       string-join(for $x in self::*/@rend return
         concat( namespace-uri(), '|', local-name(), '|', @rend),'')">
    
    Run Code Online (Sandbox Code Playgroud)

    使用您个人认为更具可读性的表格.