Re: [xsl] a table-of-contents for XHTML problem

Subject: Re: [xsl] a table-of-contents for XHTML problem
From: "Ivan Shmakov" <oneingray@xxxxxxxxx>
Date: Mon, 16 Jun 2008 08:39:36 +0700
>>>>> G Ken Holman <gkholman@xxxxxxxxxxxxxxxxxxxx> writes:

 > At 2008-06-16 01:46 +0700, Ivan Shmakov wrote:

 >> I wonder, what would be the simplest way to transform a sequence of
 >> sibling nodes, e. g.:

 >> ...

 >> into a nested list, like:

 >> ...

 >> in XSLT 1.0?

 >> The following conditions are assumed to be true:

 >> * all the `hN' nodes are the children of a single `body' node;

 >> * for any consequent elements `hN' and `hM', M <= 1 + N; the first
 >> child of the `body' node is `h1'; i. e., it's assumed that, e. g.,
 >> the following input could never happen:

 >> <body>
 >>   <h1>Foo</h1>
 >>   <h3>Bar</h3>
 >> </body>

 > Those criteria you state make this quite straightforward ... the
 > stylesheet below addresses these quite succinctly.  You don't mention
 > where you are having problems in your stylesheet so I'm not sure
 > where to advise.

        It seems that I've overlooked the `preceding-sibling' axis in
        the XPath specification (I've started to study XSLT a couple of
        days ago, so I'm not quite fluent in it.)

        What I've actually tried was to process each `body's child in a
        somewhat tricky manner, like:

  <xsl:template name="process-body-node">
    <xsl:param name="index" />
    <!-- pass more state here -->
    <xsl:variable name="body" select="/xhtml:html/xhtml:body" />
    <xsl:variable name="last" select="count($body)" />
    <xsl:if "$index &lt;= $last">
      <!-- ... do something with $body[position() = $index]... -->
      <!-- next iteration -->
      <xsl:call-template name="process-body-node">
        <xsl:with-param name="index" select="1 + $index" />
        <!-- pass even more state here -->
      </xsl:call-template>
    </xsl:if>
  </xsl:template>

        (Only that it has several `process-body-node' invocations, one
        for the inner nodes, and one for the ``siblings''.)

        I've got the program working, but it became quite large.

 > I don't think your indentation is significant so I didn't try to copy
 > the indentation in my solution.

 > This approach takes advantage of the ability to have multiple
 > declarations for the same key table.  This is different from
 > approaches I've taken in the past as I thought this might be far more
 > straightforward than trying to descend recursively ... since your
 > give the criterion that no levels of nesting are going to be missed
 > in the input.

 > I hope this helps.

        It surely will.  Thanks!

[...]

 > <?xml version="1.0" encoding="US-ASCII"?>
 > <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
 >                  version="1.0">

 > <xsl:output indent="yes"/>

 > <!--for each possible child, indicate who they are a child of-->
 > <xsl:key name="nested" match="h2"
 > use="generate-id(preceding-sibling::h1[1])"/>
 > <xsl:key name="nested" match="h3"
 > use="generate-id(preceding-sibling::h2[1])"/>
 > <xsl:key name="nested" match="h4"
 > use="generate-id(preceding-sibling::h3[1])"/>
 > <xsl:key name="nested" match="h5"
 > use="generate-id(preceding-sibling::h4[1])"/>
 > <xsl:key name="nested" match="h6"
 > use="generate-id(preceding-sibling::h5[1])"/>

        ... And it's a reverse axis...

[...]

 > </xsl:stylesheet>

[...]

Current Thread