XSL copy template

A

Anna

Hi all.
I am trying to write a stylesheet that will structure the input HTML
file in the following way:
For each heading of level n it needs to enclose the heading and all
its content until the next heading of the same level within the level
tag.

Example

input file:

<body>
<h1>First heading</h1>
Some text for first heading.
<h2>Second heading</h2>
<p>Some text for second heading</p>
<h3>Small heading</h3>
<div>Small text</div>

<h1>Another big heading</h1>
<span>Some text for big heading</span>
<h2>Sub heading for second big heading</h2>
</body>

output file:
<body>
<level1>
<h1>First heading</h1>
Some text for first heading.
<level2>
<h2>Second heading</h2>
<p>Some text for second heading</p>
<level3>
<h3>Small heading</h3>
<div>Small text</div>
</level3>
</level2>
</level1>
<level1>
<h1>Another big heading</h1>
<span>Some text for big heading</span>
<level2>
<h2>Sub heading for second big heading</h2>
</level2>
</level1>
</body>

I am trying to build an xsl which will call apply-templates for inner
elements with another mode, but fail to do it cleanly - I get a lot of
text nodes output multiple times.

Is there a neat way to do such a thing?

Thank you very much for help and sorry if this is an inapropriate
question.

Anna
 
P

Patrick TJ McPhee

[...]

% I am trying to build an xsl which will call apply-templates for inner
% elements with another mode, but fail to do it cleanly - I get a lot of
% text nodes output multiple times.

Most likely this is because you're using value-of to copy the text,
but the text is also being processed by the default template for text(),
which copies text to the result tree. Try adding

<xsl:template match='text()'/>

% Is there a neat way to do such a thing?

You could do something like

<xsl:template match='node()'>
<xsl:copy>
<xsl:apply-template select='node()|@*'/>
</xsl:copy>
</xsl:template>

<xsl:template match='h1'>
<level1>
<xsl:copy>
<xsl:apply-template select='node()|@*'/>
</xsl:copy>
</level1>
</xsl:tempalte>

<!-- etc. -->


You could use some of the text-processing functions in XPath along
with xsl:element to have one header template work for all headings.
 
M

Marrow

Hi Anna,

Trying to structure a flat XML into smething more structure based on certain
'start' elements can be tricky - and the XPaths get a bit compicated ;) but
try something like...

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:eek:utput method="xml" indent="yes"/>
<xsl:template match="body">
<xsl:copy>
<xsl:apply-templates select="h1"/>
</xsl:copy>
</xsl:template>

<xsl:template match="*[starts-with(local-name(),'h') and
number(substring(local-name(),2)) = number(substring(local-name(),2))]">
<xsl:variable name="level" select="number(substring(name(),2))"/>
<xsl:element name="level{$level}">
<xsl:copy-of select="."/>
<xsl:variable name="this-name" select="local-name()"/>
<xsl:variable name="this-id" select="generate-id()"/>
<xsl:variable name="next-name" select="concat('h',$level + 1)"/>
<xsl:apply-templates
select="following-sibling::node()[generate-id(preceding-sibling::*[starts-wi
th(local-name(),'h') and number(substring(local-name(),2)) =
number(substring(local-name(),2))][1]) = $this-id and
not(starts-with(local-name(),'h') and number(substring(local-name(),2)) =
number(substring(local-name(),2)))] |
following-sibling::*[local-name() =
$next-name][generate-id(preceding-sibling::*[local-name() = $this-name][1])
= $this-id]"/>
</xsl:element>
</xsl:template>

<xsl:template match="@* | text() | comment() | processing-instruction()">
<xsl:copy/>
</xsl:template>

<xsl:template match="*">
<xsl:copy>
<xsl:apply-templates select="@* | node()" mode="no_level"/>
</xsl:copy>
</xsl:template>

<xsl:template match="*" mode="no_level">
<xsl:copy>
<xsl:apply-templates select="@* | node()" mode="no_level"/>
</xsl:copy>
</xsl:template>

<xsl:template match="@* | text() | comment() | processing-instruction()"
mode="no_level">
<xsl:copy/>
</xsl:template>

</xsl:stylesheet>


HTH
Marrow
http://www.marrowsoft.com - home of Xselerator (XSLT IDE and debugger)
http://www.topxml.com/Xselerator
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top