This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Transforming an incorrectly structured document...


Wendell Piez posted:
> Since this is becoming a FAQ (how to get structure out of a flat
> document), I thought I'd post my general levitating-a-flat-structure
> stylesheet. Note: its design supports only regular structures (that
> is, flat files whose nesting is "correct" although only implicit);
> if you need a more general-purpose solution, one could be based on
> the same principles (the key declarations would have to be
> modified).

For interest, this stylesheet does a similar job, but can handle
improperly nested headings to a certain extent (it doesn't create
higher-level sections if they're missing).  One thing that it doesn't
do that Wendell's solution does is include any nodes that occur before
the first h1, which may or may not be an issue.

The breakthrough moment for me came when I remembered that you can
have a number of xsl:key elements with the same name, allowing you to
index different nodes on different things within the same namespace,
and hence to have a single template for all headings, cutting down on
repetition.

Another thing that's possibly of note is that you don't have
explicitly say what elements count as 'data', only that they are not
headers.  There's no need to explicitly match 'stuff' as data
within the 'stuffchildren' (or in my case 'immediate-nodes') key, just
anything that isn't a header.

----
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="levels">
   <xsl:apply-templates select="h1" />
</xsl:template>

<xsl:key name="next-headings" match="h6"
         use="generate-id(preceding-sibling::*[self::h1 or self::h2 or
                                               self::h3 or self::h4 or
                                               self::h5][1])" />
<xsl:key name="next-headings" match="h5"
         use="generate-id(preceding-sibling::*[self::h1 or self::h2 or
                                               self::h3 or self::h4][1])" />
<xsl:key name="next-headings" match="h4"
         use="generate-id(preceding-sibling::*[self::h1 or self::h2 or
                                               self::h3][1])" />
<xsl:key name="next-headings" match="h3"
         use="generate-id(preceding-sibling::*[self::h1 or self::h2][1])" />
<xsl:key name="next-headings" match="h2"
         use="generate-id(preceding-sibling::h1[1])" />

<xsl:key name="immediate-nodes"
         match="node()[not(self::h1 | self::h2 | self::h3 | self::h4 |
                           self::h5 | self::h6)]"
         use="generate-id(preceding-sibling::*[self::h1 or self::h2 or
                                               self::h3 or self::h4 or
                                               self::h5 or self::h6][1])" />

<xsl:template match="h1 | h2 | h3 | h4 | h5 | h6">
   <xsl:variable name="level" select="substring-after(name(), 'h')" />
   <section level="{$level}">
      <head><xsl:apply-templates /></head>
      <xsl:apply-templates select="key('immediate-nodes', generate-id())" />
      <xsl:apply-templates select="key('next-headings', generate-id())" />
   </section>
</xsl:template>

<xsl:template match="stuff">
   <data><xsl:apply-templates /></data>
</xsl:template>

<xsl:template match="node()">
   <xsl:copy-of select="." />
</xsl:template>

</xsl:stylesheet>
----

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]