[Libvir] PATCH: Autogenerate table of contents for docs

Daniel P. Berrange berrange at redhat.com
Wed Apr 30 13:05:12 UTC 2008


Alot of the docs pages have manually written table of contents linking to
headings with the page. I figured this is a good candidate for being
auto-generated.

The basic idea is that given a document with  a series of headings

   <h2><a name="xxx">Foo</a></h2>
   ..
   <h3><a name="xxx">Bar</a></h3>
   ..
   <h3><a name="xxx">Wizz</a></h3>
   ..
   <h2><a name="xxx">Oooh</a></h2>
   ..
   <h3><a name="xxx">Ahhh</a></h3>

Then, generate a table of contents with a nested set of lists <ul>. THe
XSL below attempts todo this for heading levels h2 -> h6, and splices the
TOC into the page where it sees an <ul id='toc'></ul> element (typically
just after <h1>).

I'm kind of out of practice with XSL, so there's probably a nicer way
to write the 'toc' template below...

Dan.

Index: docs/page.xsl
===================================================================
RCS file: /data/cvs/libvirt/docs/page.xsl,v
retrieving revision 1.7
diff -u -r1.7 page.xsl
--- docs/page.xsl	28 Apr 2008 08:29:35 -0000	1.7
+++ docs/page.xsl	30 Apr 2008 12:55:20 -0000
@@ -59,6 +59,54 @@
     </ul>
   </xsl:template>
 
+  <xsl:template name="toc">
+    <ul>
+      <xsl:for-each select="/html/body/h2[count(a) = 1]">
+        <xsl:variable name="thishead" select="."/>
+        <li>
+          <a href="#{a/@name}"><xsl:value-of select="a/text()"/></a>
+          <xsl:if test="count(./following-sibling::h3[preceding-sibling::h2[1] = $thishead and count(a) = 1]) > 0">
+            <ul>
+              <xsl:for-each select="./following-sibling::h3[preceding-sibling::h2[1] = $thishead and count(a) = 1]">
+                <xsl:variable name="thissubhead" select="."/>
+                <li>
+                  <a href="#{a/@name}"><xsl:value-of select="a/text()"/></a>
+                  <xsl:if test="count(./following-sibling::h4[preceding-sibling::h3[1] = $thissubhead and count(a) = 1]) > 0">
+                    <ul>
+                      <xsl:for-each select="./following-sibling::h4[preceding-sibling::h3[1] = $thissubhead and count(a) = 1]">
+                        <li>
+                          <a href="#{a/@name}"><xsl:value-of select="a/text()"/></a>
+                          <xsl:if test="count(./following-sibling::h5[preceding-sibling::h4[1] = $thissubhead and count(a) = 1]) > 0">
+                            <ul>
+                              <xsl:for-each select="./following-sibling::h5[preceding-sibling::h4[1] = $thissubhead and count(a) = 1]">
+                                <li>
+                                  <a href="#{a/@name}"><xsl:value-of select="a/text()"/></a>
+                                  <xsl:if test="count(./following-sibling::h6[preceding-sibling::h5[1] = $thissubhead and count(a) = 1]) > 0">
+                                    <ul>
+                                      <xsl:for-each select="./following-sibling::h6[preceding-sibling::h5[1] = $thissubhead and count(a) = 1]">
+                                        <li>
+                                          <a href="#{a/@name}"><xsl:value-of select="a/text()"/></a>
+                                        </li>
+                                      </xsl:for-each>
+                                    </ul>
+                                  </xsl:if>
+                                </li>
+                              </xsl:for-each>
+                            </ul>
+                          </xsl:if>
+                        </li>
+                      </xsl:for-each>
+                    </ul>
+                  </xsl:if>
+                </li>
+              </xsl:for-each>
+            </ul>
+          </xsl:if>
+        </li>
+      </xsl:for-each>
+    </ul>
+  </xsl:template>
+
   <!-- This is the master page structure -->
   <xsl:template match="/" mode="page">
     <xsl:param name="pagename"/>
@@ -93,7 +141,16 @@
             </xsl:apply-templates>
           </div>
           <div id="content">
-            <xsl:copy-of select="html/body/*"/>
+            <xsl:for-each select="html/body/*">
+              <xsl:choose>
+                <xsl:when test="name() = 'ul' and @id = 'toc'">
+                  <xsl:call-template name="toc"/>
+                </xsl:when>
+                <xsl:otherwise>
+                  <xsl:copy-of select="."/>
+                </xsl:otherwise>
+              </xsl:choose>
+            </xsl:for-each>
           </div>
         </div>
         <div id="footer">


-- 
|: Red Hat, Engineering, Boston   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list