xslt将多个兄弟节点从一个特定节点包装到下一个特定节点的出现

时间:2018-04-13 21:16:27

标签: xml xslt xpath

我在这里读了一些关于移动节点向下/包裹元素的答案,但是无法找出我的问题的解决方案。这是:我想用xslt(2.0)在“深层”层次结构中转换平面文档层次结构。问题是将兄弟姐妹的搜索限制为某个兄弟姐妹,在我的情况下:搜索从h1到下一个h1节点的所有兄弟姐妹。

XML代码

<root>
   <h1>A heading</h1>
   <para>Some text.</para>
   <h2>More text</h2>         
   <table>Content</table>
   <pic>a picture</pic>
   <h1>Another heading.</h1>
   <para>Some text again.</para>
   <para>More text.</para>
   ...
</root>

真实文档要长得多,标题最多有五个级别,没有固定的元素顺序,而且在现实生活中我不仅要移动h1-sections,还需要移动h2-sections等等。 我尝试了几次类似表达式的尝试,但我是xslt的新手。那么如何使用section-element和h2-elements以截面元素的相同方式将所有h1元素及其兄弟包装到下一个h1元素?

所需的输出

<root>
   <chapter>
      <h1>A heading</h1>
      <para>Some text.</para>
      <section>
         <h2>More text</h2>         
         <table>Content</table>
         <pic>a picture</pic>
      </section>
   </chapter>
   <chapter>
      <h1>Another heading.</h1>
      <para>Some text again.</para>
      <para>More text.</para>
   </chapter>
   ...
</root>

1 个答案:

答案 0 :(得分:1)

您可以使用的方法是两个嵌入式for-each-group命令:

  • 适用于root的所有元素,适用于以h1开头的群组。
  • 第二个是当前组的内容(从第一个开始) loop),适用于以h2开头的群组。

for-each-group加上group-starting-with的一个重要特征 当源内容不是以指定的标签开头时 group-starting-with,然后是&#34;起始部分&#34; (没有指定的开始 tag)是第一组。

区分这个&#34;初始&#34;组(实际上以h1开头) 和以h2开头的群组,我使用了xsl:choose

所以整个脚本可能如下所示:

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

  <xsl:template match="root">
    <xsl:copy>
      <xsl:for-each-group select="*" group-starting-with="h1">
        <chapter>
          <xsl:for-each-group select="current-group()" group-starting-with="h2">
            <xsl:choose>
              <xsl:when test="name()='h1'">
                <xsl:copy-of select="current-group()"/>
              </xsl:when>
              <xsl:otherwise>
                <section>
                  <xsl:copy-of select="current-group()"/>
                </section>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:for-each-group>
        </chapter>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>
</xsl:transform>

有关工作示例,请参阅http://xsltransform.net/pNvs5w8