Subject: Re: [xsl] Nested sections from flat structure From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx> Date: Mon, 14 May 2001 11:30:00 +0100 |
Hi Linda, > My source documents are a bit troublesome. They have a structure > like HTML. There are two elements that indicate start of a section, > <head> and <a name="">. Both appear inside a p element. A source > document can be: > - without subsections > - with subsections indicated by <head> > - with subsections indicated by <a name=""> > - with subsections indicated by <a name="">, and <head> subsections > inside the first subsections > - with subsections indicated by <head>, and <a name=""> subsections > inside the first subsections When you have troublesome source then it's sometimes better to take a two-pass approach on the problem - transform it into something more approachable, and then transform *that* into the output that you want. Your source would be a lot more approachable if it was clear what was a 'top' section and what were sections underneath them. In the following stylesheet, I first convert the source into: <GeneralSection/> <Paragraph>first some intro text</Paragraph> <TopSection/> <SectionTitle>A</SectionTitle> <Paragraph>goes with A.</Paragraph> <SubSection ID="A.1"/> <Paragraph>Text with A.1</Paragraph> <Paragraph>More text with A.1</Paragraph> <SubSection ID="A.2"/> <Paragraph>text with A.2</Paragraph> <Paragraph>Goes with A.2</Paragraph> <TopSection/> <SectionTitle>B</SectionTitle> <Paragraph>Goes with B.</Paragraph> <Paragraph>Goes with B.</Paragraph> <TopSection/> <SectionTitle>C</SectionTitle> <Paragraph>Goes with C</Paragraph> <Paragraph>Goes with C</Paragraph> And from there using the Muenchian method to create the hierarchy. The advantage is that both transformations are relatively straight-forward; the disadvantage is that you need to either use a node-set extension in your stylesheet or split the stylesheet in two and use the second on the output of the first. If you want to use a one-pass approach, like your stylesheet is at the moment, the only suggestion I'd make for simplifying it is to split up all those xsl:for-eaches into separate templates, using modes to distinguish between the different types of processing you do within each. Anyway, here's my approach (unless you're using a processor that supports exsl:node-set(), you'll need to change the namespace for the node-set() function): <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl"> <xsl:output method="xml" indent="yes" /> <xsl:strip-space elements="*" /> <xsl:variable name="top" select="topic/text/p[head or a/@name][1]" /> <xsl:template match="/"> <xsl:variable name="sections"> <GeneralSection /> <xsl:apply-templates mode="convert" /> </xsl:variable> <xsl:apply-templates select="exsl:node-set($sections)/GeneralSection" mode="group" /> </xsl:template> <xsl:template match="p" mode="convert"> <Paragraph><xsl:apply-templates /></Paragraph> </xsl:template> <xsl:template match="p[head]" mode="convert"> <xsl:choose> <xsl:when test="$top/head"><TopSection /></xsl:when> <xsl:otherwise><SubSection /></xsl:otherwise> </xsl:choose> <SectionTitle><xsl:apply-templates select="head" /></SectionTitle> <Paragraph> <xsl:apply-templates select="node()[not(self::head)]" /> </Paragraph> </xsl:template> <xsl:template match="p[a/@name]" mode="convert"> <xsl:choose> <xsl:when test="$top/a/@name"> <TopSection ID="{a/@name}" /> </xsl:when> <xsl:otherwise><SubSection ID="{a/@name}" /></xsl:otherwise> </xsl:choose> </xsl:template> <xsl:key name="children" match="Paragraph | SectionTitle" use="generate-id(preceding-sibling::* [self::GeneralSection or self::TopSection or self::SubSection][1])" /> <xsl:key name="children" match="TopSection" use="generate-id(preceding-sibling::GeneralSection[1])" /> <xsl:key name="children" match="SubSection" use="generate-id(preceding-sibling::TopSection[1])" /> <xsl:template match="GeneralSection | TopSection | SubSection" mode="group"> <GeneralSection> <xsl:copy-of select="@*" /> <xsl:apply-templates select="key('children', generate-id())" mode="group" /> </GeneralSection> </xsl:template> <xsl:template match="Paragraph" mode="group"> <xsl:copy-of select="." /> </xsl:template> </xsl:stylesheet> I hope that helps, Jeni --- Jeni Tennison http://www.jenitennison.com/ XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] Nested sections from flat str, Linda van den Brink | Thread | RE: [xsl] Nested sections from flat, Vane Lashua |
Re: [xsl] Performance Issue (if any, Jeni Tennison | Date | RE: [xsl] SVG graphs, DPawson |
Month |