Reputation: 1020
I've xml like follows,
<doc>
<h1>header 1</h1>
<p>para</p>
<p>para</p>
<h1>header 2</h1>
<p>para</p>
<h2>header 2 sub h1</h2>
<h2>header 2 sub h2</h2>
<h1>header 3</h1>
<p>para</p>
<p>para</p>
<h1>header 4</h1>
<h2>header 4 sub h1</h2>
<p>para</p>
</doc>
what I need is get all <h1>
and <h2>
nodes respectively and create an unordered list with links,
so the desired output is,
<doc>
<ul>
<li><h1><a href="page-header1-1">header 1</a></h1></li>
<li><h1><a href="page-header1-2">header 2</a></h1></li>
<ul>
<li><h2><a href="page-header2-1">header 2 sub h1</a></h2></li>
<li><h2><a href="page-header2-2">header 2 sub h2</a></h2></li>
</ul>
<li><h1><a href="page-header1-3">header 3</a></h1></li>
<li><h1><a href="page-header1-4">header 4 sub h1</a></h1></li>
<ul>
<li><h2><a href="page-header2-3">zz</a></h2></li>
</ul>
</ul>
</doc>
I've written following xsl to achieve this task,
<xsl:template match="doc">
<div>
<ul>
<xsl:for-each-group select="*" group-starting-with="h1">
<li><a href="page-header1-{count(preceding::h1)+1}"> <xsl:copy-of select="."/></a> </li>
<ul>
<li><a href="page-header2-{count(preceding::h2)+1}"><xsl:apply-templates select="current-group()[self::h2]"/></a></li>
</ul>
</xsl:for-each-group>
</ul>
</div>
</xsl:template>
my output is looks like this,
<doc>
<ul>
<li><a href="page-header1-1"><h1>header 1</h1></a></li>
<ul><li><a href="page-header2-1"/></li></ul>
<li><a href="page-header1-2"><h1>header 2</h1></a></li>
<ul>
<li>
<a href="page-header2-1">
<h2>header 2 sub h1</h2>
<h2>header 2 sub h2</h2>
</a>
</li>
</ul>
<li><a href="page-header1-3"><h1>header 3</h1></a></li>
<ul><li><a href="page-header2-3"/></li></ul>
<li><a href="page-header1-4"><h1>header 4</h1></a></li>
<ul>
<li>
<a href="page-header2-3">
<h2>header 4 sub h1</h2>
</a>
</li>
</ul>
</ul>
</doc>
I've identified 2 errors there
1) it adds empty <a href="page-header2-x"></a>
values where there are no following siblings for <h1>
s. (see the results of 1st and 3rd <h1>
s)
2) <a>
are not separately added to <h2>
nodes. but it adds <a>
to group of <h2>
s which are consecutively placed. (see under 2nd <h1>
in the result) But I need to add <a>
to separately for every <h2>
.
I've used <xsl:apply-templates select="current-group()[self::h2]"/>
to get the <h2>
s and it seems it returns all <h2>
as a group but not returns separately.
Can anyone suggest me a method to sort out this problem..
Upvotes: 0
Views: 202
Reputation: 167516
Change <ul>
<li><a href="page-header2-{count(preceding::h2)+1}"><xsl:apply-templates select="current-group()[self::h2]"/></a></li>
</ul>
to
<xsl:variable name="h2" select="current-group()[self::h2]"/>
<xsl:if test="$h2">
<ul>
<xsl:apply-templates select="$h2"/>
</ul>
</xsl:if>
and add a template
<xsl:template match="h2">
<li><a href="page-header2-{position()"><xsl:copy-of select="."/></a></li>
</xsl:template>
Upvotes: 1