Reputation: 1706
I am creating a html page with xslt to format my xml into a html page, however I am getting a value repeated and I can't find why, below are my xsl, xml, and html. I have indicated where my repeat value occurs directly below, Thanks for everyone's help!
<fieldset>
<legend>Joys of a MAD man</legend><ol>
Joys of a MAD man *********** Why is the title repeated? ************
<li>Slow Moving<a href="./Music/Splintz - Joys of a MAD Man/Slow Moving.mp3">
[Download]
</a></li>
</ol></fieldset>
My XML
<albums>
<album>
<title>Joys of a MAD man</title>
<track>Slow Moving</track>
</album>
<album>
<title>Single</title>
<track>None</track>
</album>
</albums>
and finally my xsl
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="album">
<fieldset>
<legend><xsl:value-of select="title/text()" /></legend>
<ol>
<xsl:apply-templates />
</ol>
</fieldset>
</xsl:template>
<xsl:template match="track">
<li>
<xsl:value-of select="text()" />
<a>
<xsl:attribute name="href">
<xsl:text>./Music/Splintz - Joys of a MAD Man/</xsl:text>
<xsl:value-of select="text()"/>
<xsl:text>.mp3</xsl:text>
</xsl:attribute>
[Download]
</a>
</li>
</xsl:template>
</xsl:stylesheet>
Upvotes: 2
Views: 615
Reputation: 243459
As pointed out by other people, the default XSLT processing is selecting for execution the built-in XSLT templates and this results in outputting text nodes.
As your code isn't relying on the XSLT built-in template for a text node, the simplest possible solution is to override this template with one that has no body.
Add the following to your code:
<xsl:template match="text()"/>
Now your full code becomes this:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="album">
<fieldset>
<legend>
<xsl:value-of select="title/text()" />
</legend>
<ol>
<xsl:apply-templates />
</ol>
</fieldset>
</xsl:template>
<xsl:template match="track">
<li>
<xsl:value-of select="text()" />
<a>
<xsl:attribute name="href">
<xsl:text>./Music/Splintz - Joys of a MAD Man/</xsl:text>
<xsl:value-of select="text()"/>
<xsl:text>.mp3</xsl:text>
</xsl:attribute>
[Download]
</a>
</li>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
and the result doesn't contain the unwanted repeated text:
<fieldset>
<legend>Joys of a MAD man</legend>
<ol>
<li>Slow Moving<a href="./Music/Splintz - Joys of a MAD Man/Slow Moving.mp3">
[Download]
</a>
</li>
</ol>
</fieldset>
<fieldset>
<legend>Single</legend>
<ol>
<li>None<a href="./Music/Splintz - Joys of a MAD Man/None.mp3">
[Download]
</a>
</li>
</ol>
</fieldset>
Upvotes: 1
Reputation: 66714
There are built-in default template rules that copy text to the result document.
<xsl:apply-templates/>
is short for <xsl:apply-templates select="child::node()"/>
.
You used xsl:apply-templates
inside the template match for album
. When you are "standing" on the album
element, title
is one of the child nodes that get processed.
The built-in template matched title
output it's text()
"Joys of a MAD man" the second time.
There are a number of ways to prevent the title
text from being output the second time. You could:
title
to your stylesheet to prevent the built-in template from matching:
<xsl:template match="title"/>
title
from your apply-templates
:
<xsl:apply-templates select="node()[not(self::title)]"/>
track
child elements:
<xsl:apply-templates select="track"/>
Upvotes: 2
Reputation: 18430
Because you apply <xsl:apply-templates />
to the same context name album
as you do the value-of
above. It strips all text nodes from all descendants.
Say explicitly <xsl:apply-templates match="track" />
.
Upvotes: 1