This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: Adding structure to a docment based on attributes
- To: <xsl-list at lists dot mulberrytech dot com>
- Subject: [xsl] Re: Adding structure to a docment based on attributes
- From: "Yang" <sfyang at unisvr dot net dot tw>
- Date: Tue, 25 Sep 2001 14:09:26 +0800
- Reply-To: xsl-list at lists dot mulberrytech dot com
Nichloas;
Following Wendell following suggestions
>Check out my contribution to the list at
>http://www.biglist.com/lists/xsl-list/archives/200012/msg00138.html and
>Jeni's improvements at
>http://www.biglist.com/lists/xsl-list/archives/200012/msg00175.html.
>This is basically a grouping problem. The secret is to think of the problem
>not as working by "closing the logical structure at the right place", but
>by correctly identifying which nodes go into which logical structure, and
>pulling just those nodes in when you create it.
I submit two xslts for your reference using Wendell and Jeni algorithms
which are written based on explicit element h1,h2,...h6.
It is a litter bit different from yours which hierarchical relations built
inside of **style** attributes.
Wendell, Jeni ; your comment on my xslt are certainly appreciated. Thanks.
*** xslt based on Wendell's algorithm **
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<!--i.e., convert the attribute into element, it's value is related to p-->
<xsl:key name="Body" match="p[@style='Body']"
use="generate-id((..|preceding-sibling::p[@style='Heading1']|preceding-sibli
ng::p[@style='Heading2']
|preceding-sibling::p[@style='Heading3']|preceding-sibling::p[@style='Headin
g4']|preceding-sibling::p[@style='Heading5']
|preceding-sibling::p[@style='Heading6'])[last()])" />
<xsl:key name="h2" match="p[@style='Heading2']"
use="generate-id(preceding-sibling::p[@style='Heading1'][1])"/>
<xsl:key name="h3" match="p[@style='Heading3']"
use="generate-id(preceding-sibling::p[@style='Heading2'][1])"/>
<xsl:key name="h4" match="p[@style='Heading4']"
use="generate-id(preceding-sibling::p[@style='Heading3'][1])"/>
<xsl:key name="h5" match="p[@style='Heading5']"
use="generate-id(preceding-sibling::p[@style='Heading4'][1])"/>
<xsl:key name="h6" match="p[@style='Heading6']"
use="generate-id(preceding-sibling::p[@style='Heading5'][1])"/>
<!-- Wendell Piez algorithm -->
<xsl:template match="doc">
<main>
<xsl:apply-templates select="key('Body',generate-id())" mode="Body"/>
<xsl:apply-templates select="p[@style='Heading1']" mode="h1"/>
</main>
</xsl:template>
<xsl:template match="p" mode="h1">
<section level="1"><head><xsl:apply-templates/></head>
<xsl:apply-templates select="key('Body',generate-id())" mode="Body"/>
<xsl:apply-templates select="key('h2',generate-id())" mode="h2"/>
</section>
</xsl:template>
<xsl:template match="p" mode="h2">
<section level="2"><head><xsl:apply-templates/></head>
<xsl:apply-templates select="key('Body',generate-id())" mode="Body"/>
<xsl:apply-templates select="key('h3',generate-id())" mode="h3"/>
</section>
</xsl:template>
<xsl:template match="p" mode="h3">
<section level="3"><head><xsl:apply-templates/></head>
<xsl:apply-templates select="key('Body',generate-id())" mode="Body"/>
<xsl:apply-templates select="key('h4',generate-id())" mode="h4"/>
</section>
</xsl:template>
<xsl:template match="p" mode="h4">
<section level="4"><head><xsl:apply-templates/></head>
<xsl:apply-templates select="key('Body',generate-id())" mode="Body"/>
<xsl:apply-templates select="key('h5',generate-id())" mode="h5"/>
</section>
</xsl:template>
<xsl:template match="p" mode="h5">
<section level="5"><head><xsl:apply-templates/></head>
<xsl:apply-templates select="key('Body',generate-id())" mode="Body"/>
<xsl:apply-templates select="key('h6',generate-id())" mode="h6"/>
</section>
</xsl:template>
<xsl:template match="p" mode="h6">
<section level="6"><head><xsl:apply-templates/></head>
<xsl:apply-templates select="key('Body',generate-id())" mode="Body"/>
</section>
</xsl:template>
<xsl:template match="p" mode="Body">
<text><xsl:apply-templates/></text>
</xsl:template>
</xsl:stylesheet>
*** xslt 2 - Using Jeni's algorithm ***
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<!--i.e., convert the attribute into element, it's value is related to p-->
<xsl:key name="next-headings" match="p[@style='Heading2']"
use="generate-id(preceding-sibling::p[@style='Heading1'
or @style='Heading2' or @style='Heading3' or @style='Heading4' or
@style='Heading5' or @style='Heading6'][1])"/>
<xsl:key name="next-headings" match="p[@style='Heading3']"
use="generate-id(preceding-sibling::p[@style='Heading1'
or @style='Heading2' or @style='Heading3' or @style='Heading4' or
@style='Heading5' or @style='Heading6'][1])"/>
<xsl:key name="next-headings" match="p[@style='Heading4']"
use="generate-id(preceding-sibling::p[@style='Heading1'
or @style='Heading2' or @style='Heading3' or @style='Heading4' or
@style='Heading5' or @style='Heading6'][1])"/>
<xsl:key name="next-headings" match="p[@style='Heading5']"
use="generate-id(preceding-sibling::p[@style='Heading1'
or @style='Heading2' or @style='Heading3' or @style='Heading4' or
@style='Heading5' or @style='Heading6'][1])"/>
<xsl:key name="next-headings" match="p[@style='Heading6']"
use="generate-id(preceding-sibling::p[@style='Heading1'
or @style='Heading2' or @style='Heading3' or @style='Heading4' or
@style='Heading5' or @style='Heading6'][1])"/>
<xsl:key name="immediate-nodes" match="node()[not(@style='Heading1') and
not(@style='Heading2') and not(@style='Heading3') and
not(@style='Heading4') and not(@style='Heading5') and
not(@style='Heading6')]"
use="generate-id(preceding-sibling::p[@style='Heading1' or @style='Heading2'
or @style='Heading3' or @style='Heading4' or @style='Heading5' or
@style='Heading6'][1])"/>
<!-- Jeni's Algorithm -->
<xsl:template match="doc">
<main>
<xsl:apply-templates select="p[@style='Heading1']" />
</main>
</xsl:template>
<xsl:template match="p" >
<xsl:variable name="level"
select="substring-after(@*[name()='style'],'ing')"/>
<section level="{$level}">
<head><xsl:apply-templates/></head>
<xsl:apply-templates select="key('immediate-nodes',generate-id())"
mode="Body"/>
<xsl:apply-templates select="key('next-headings',generate-id())" />
</section>
</xsl:template>
<xsl:template match="node()">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="p" mode="Body">
<text><xsl:apply-templates/></text>
</xsl:template>
</xsl:stylesheet>
** xml ***
<doc>
<p style="Heading1">Top Level Heading</p>
<p style="Body">Some text at this level</p>
<p style="Heading2">Sub Heading 1</p>
<p style="Body">Some text here</p>
<p style="Heading2">Sub heading 2</p>
<p style="Body">Some text here</p>
<p style="Heading3">Sub Heading 3</p>
<p style="Body">Body 3 text</p>
<p style="Heading4">Sub Heading 4</p>
<p style="Body">Body 4 text</p>
<p style="Heading1">Another Heading</p>
<p style="Body">Some more text here</p>
</doc>
Sun-fu Yang
sfyang@unisvr.net.tw
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list