使用嵌套的XSLT2分组创建结构化文档

时间:2014-12-30 09:39:21

标签: html xslt-2.0

我有格式良好的HTML文件:

<html xmlns="http://www.w3.org/1999/xhtml">
<body>
    <h1>h1.1</h1>
    <p>p1.1</p>
    <p>p1.2</p>
    <h2>h2.1.1</h2>
    <p>p2.1.1</p>
    <p>p2.1.2</p>
    <h2>h2.2</h2>
    <p>p2.1.2a</p>
    <p>p2.1.2b</p>
    <h1>h1.2</h1>
    <p>p1.2a</p>
    <p>p1.2b</p>
    <h2>2.1</h2>
    <p>p2.2.1a</p>
    <p>p2.2.2b</p>
</body>

并希望创建结构化HTML,其中h1和h2代表不同的嵌套级别 - 类似于

<html xmlns="http://www.w3.org/1999/xhtml">
<body>
    <div class="h1">
        <h1>h1.1</h1>
        <p>p1.1</p>
        <p>p1.2</p>
        <div class="h2">
            <h2>h2.1.1</h2>
            <p>p2.1.1</p>
            <p>p2.1.2</p>
        </div>
        <div class="h2">
            <h2>h2.2</h2>
            <p>p2.1.2a</p>
            <p>p2.1.2b</p>
        </div>
    </div>
    <div class="h1">
        <h1>h1.2</h1>
        <p>p1.2a</p>
        <p>p1.2b</p>
        <div class="h2">
            <h2>2.1</h2>
            <p>p2.2.1a</p>
            <p>p2.2.2b</p>
        </div>
    </div>
</body>

除了包含h1和h2之外,文档中没有规律性。我可以使用XSLT2分组来嵌套h1元素,但希望将h1 / h2 / h3的2级(或更多级)组合在一起。我可以通过变换器的多次传递来做到这一点(即重新运行撒克逊人,并为h1和h2分别进行分组),但如果可能的话,他们更愿意一次性完成。我目前的实验(显示我一直在尝试)是:

  <xsl:template match="h:body">
<h:div class="xml-content" >
  <xsl:for-each-group select="h:*" group-starting-with="h:h1">
     <!-- h:div needs to go here? -->
      <xsl:for-each select="current-group()[not(self::h:h1)]">
          <xsl:for-each-group select="self::h:*" group-starting-with="h:h2">
     <!-- h:div needs to go here? -->
              <xsl:for-each select="current-group()">
                <xsl:copy>
                    <xsl:apply-templates select="@*|*|text()"/>
                </xsl:copy>
              </xsl:for-each> 
            </hb>
          </xsl:for-each-group>
          </ha>
      </xsl:for-each> 
    </h:section>
  </xsl:for-each-group>
</h:div>

但这仅对h1和h2进行分组,而不是以下元素。我怎么能这样做?

1 个答案:

答案 0 :(得分:1)

编写递归函数为每个级别执行分组或嵌套for-each-groups元素:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    xmlns="http://www.w3.org/1999/xhtml"
    xpath-default-namespace="http://www.w3.org/1999/xhtml"
    version="2.0">

<xsl:output method="xhtml" 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-starting-with="h1">
      <div class="h1">
        <xsl:apply-templates select="."/>
        <xsl:for-each-group select="current-group() except ." group-starting-with="h2">
          <xsl:choose>
            <xsl:when test="self::h2">
              <div class="h2">
                <xsl:apply-templates select="current-group()"/>
              </div>
            </xsl:when>
            <xsl:otherwise>
              <xsl:apply-templates select="current-group()"/>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:for-each-group>
      </div>
    </xsl:for-each-group>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>

输出是

<html xmlns="http://www.w3.org/1999/xhtml">

   <body>
      <div class="h1">
         <h1>h1.1</h1>
         <p>p1.1</p>
         <p>p1.2</p>
         <div class="h2">
            <h2>h2.1.1</h2>
            <p>p2.1.1</p>
            <p>p2.1.2</p>
         </div>
         <div class="h2">
            <h2>h2.2</h2>
            <p>p2.1.2a</p>
            <p>p2.1.2b</p>
         </div>
      </div>
      <div class="h1">
         <h1>h1.2</h1>
         <p>p1.2a</p>
         <p>p1.2b</p>
         <div class="h2">
            <h2>2.1</h2>
            <p>p2.2.1a</p>
            <p>p2.2.2b</p>
         </div>
      </div>
   </body>

</html>