如何在XSL中对标题级别进行分组

时间:2014-12-10 07:09:57

标签: xslt xpath xslt-2.0 xpath-2.0

我有以下过程的HTML。

<p class="Ahead">Heading 1</p>
<p class="txt">Lorem ipsum dolor sit amet, consectetuer adipiscing elit</p>
<p class="Bhead">Heading 1.1</p>
<p class="txt">Nibh euismod tincidunt ut laoreet dolore magna aliquam</p>
<p class="list">Investigationes demonstraverunt lectores legere</p>
<p class="Chead">Heading 1.1.1</p>
<p class="txt">Typi non habent claritatem insitam</p>
<p class="Bhead">Heading 1.2</p>
<p class="txt">Lorem ipsum dolor sit amet</p>

标题最多可达5个级别。不同的属性位于标题之间。

输出应如下所示。

<section>
  <section-title>Heading 1</section-title>
    <p class="txt">Lorem ipsum dolor sit amet, consectetuer adipiscing elit</p>
  <section>
   <section-title>Heading 1.1</section-title>
    <p class="txt">Nibh euismod tincidunt ut laoreet dolore magna aliquam</p>
    <p class="list">Investigationes demonstraverunt lectores legere</P>
    <section>
      <section-title>Heading 1.1.1</section-title>
      <p class="txt">Typi non habent claritatem insitam</p>
    </section>
  </section>
  <section>
    <section-title>Heading 1.2</section-title>
    <p class="txt">Lorem ipsum dolor sit amet</p>
  </section>
</section>

提前致谢。

1 个答案:

答案 0 :(得分:2)

此样式表使用XSLT 2.0,改编自Michael Kay的 XSLT 2.0和XPath 2.0程序员参考.pdf ,第341-342页。

当下面的样式表应用于您的输入XML时(我已将一个名为root的根节点添加到您的示例输入XML中):

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

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

    <xsl:template match="/root">
        <xsl:for-each-group select="*" group-starting-with="p[@class='Ahead']">
            <xsl:choose>
                <xsl:when test="self::p[@class='Ahead']">
                    <xsl:apply-templates select="." mode="group"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates select="current-group()"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each-group>
    </xsl:template>

    <xsl:template match="p[@class='Ahead']|p[@class='Bhead']|p[@class='Chead']" mode="group">
        <xsl:variable name="this_att" select="substring-before(@class, 'head')"/>
        <xsl:variable name="next" select="concat(translate($this_att, 'ABCDEFGH', 'BCDEFGHI'), 'head')"/>
        <xsl:element name="section">
            <section-title><xsl:apply-templates/></section-title>
            <xsl:for-each-group select="current-group() except ." group-starting-with="p[@class = $next]">
                <xsl:apply-templates select="." mode="group"/>
            </xsl:for-each-group>
        </xsl:element>
    </xsl:template>

    <xsl:template match="p[not(ends-with(@class, 'head'))]" mode="group">
        <xsl:copy-of select="current-group()"/>
    </xsl:template>

</xsl:stylesheet>

它产生:

<?xml version="1.0" encoding="UTF-8"?>
<section>
   <section-title>Heading 1</section-title>
   <p class="txt">Lorem ipsum dolor sit amet, consectetuer adipiscing elit</p>
   <section>
      <section-title>Heading 1.1</section-title>
      <p class="txt">Nibh euismod tincidunt ut laoreet dolore magna aliquam</p>
      <p class="list">Investigationes demonstraverunt lectores legere</p>
      <section>
         <section-title>Heading 1.1.1</section-title>
         <p class="txt">Typi non habent claritatem insitam</p>
      </section>
   </section>
   <section>
      <section-title>Heading 1.2</section-title>
      <p class="txt">Lorem ipsum dolor sit amet</p>
   </section>
</section>