Reputation: 3
I have encountered a section of HTML from a well-known Sci-Fi publisher that attempts to mimic an ordered list using paragraphs as anonymous tags. A sample is as follows:
<p class="NL1">1. first list item.</p>
<p class="NL">2. second list item.</p>
<p class="NL">3. third list item.</p>
<p class="NLL">4. last list item.</p>
I want to use XSLT to convert this abomination to a real ordered list. What I have tried is:
<xsl:template name="makeLi">
<li>
<xsl:apply-templates/>
</li>
</xsl:template>
<xsl:template match="p[@class='NL1'
and preceding-sibling::node()[not(self::p[@class='NL1'])]]" >
<ol>
<xsl:call-template name="makeLi"/>
<xsl:apply-templates select="following-sibling::node()[(self::p[@class='NL'])
or (self::p[@class='NLL'])]"/>
</ol>
</xsl:template>
<xsl:template match="p[@class='NL'
and preceding-sibling::node()[not(self::p[@class='NL'])]
and preceding-sibling::node()[not(self::p[@class='NL1'])]]" >
<xsl:call-template name="makeLi"/>
</xsl:template>
<xsl:template match="p[@class='NLL' and preceding-sibling::node()[not(self:::p)]]" >
<xsl:call-template name="makeLi"/>
</xsl:template>
When I apply this transformation, what I end up with is:
<ol>
<li>1. first list item.</li>
<li>2. second list item.</li>
<li>3. third list item.</li>
<li>4. fourth list item.</li>
</ol>
<ul>
<li>2. second list item.</li>
<li>3. third list item.</li>
<li>4. fourth list item.</li>
</ul>
How can I prevent the "NL" and "NLL" classes from being processed a second time?
Upvotes: 0
Views: 72
Reputation: 163342
With XSLT 1.0, sibling recursion is the way to go, and you're on the right lines. Not tested, but something like this:
<xsl:template match="p[@class='NL1']" mode="normal">
<ol>
<xsl:call-template name="makeLi"/>
<xsl:apply-templates select="following-sibling::p[1]" mode="list"/>
</ol>
</xsl:template>
<xsl:template match="p[@class='NL']" mode="list">
<xsl:call-template name="makeLi"/>
<xsl:apply-templates select="following-sibling::p[1]" mode="list"/>
</xsl:template>
<xsl:template match="p[@class='NLL']" mode="list">
<xsl:call-template name="makeLi"/>
</xsl:template>
<xsl:template match="p[@class='NL' or @class='NLL']" mode="normal"/>
I added mode="normal"
for the default processing mode just for emphasis, you should leave it out if using the default (unnamed) mode.
Upvotes: 1