Reputation: 3848
I'm trying to figure out how to apply a styling element to different structure elements.
My XML looks like this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<catalog>
<cd>
<title>Empire Burlesque</title>
<artist><bold>Bob</bold> Dylan</artist>
</cd>
<cd>
<title>Hide your <bold>heart</bold></title>
<artist>Bonnie Tyler</artist>
</cd>
</catalog>
And my lastest XSLT attempt looks like this
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="bold">
<b><xsl:value-of select="." /></b>
</xsl:template>
<xsl:template match="/catalog">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>Artist</th>
</tr>
<xsl:for-each select="cd">
<tr>
<td><xsl:value-of select="title" /><xsl:apply-templates/></td>
<td><xsl:value-of select="artist" /><xsl:apply-templates/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
But the result duplicates the data instead of just having the desired parts in bold.
Upvotes: 0
Views: 70
Reputation: 163262
You're processing it once using xsl:value-of and then once again using xsl:apply-templates; if you don't want it processed twice, then just cut one of these out.
Upvotes: 0
Reputation: 60414
Here's another option that uses fewer explicit element matches. In many cases, this will be what you want, because it's simpler and more flexible. In some cases, this won't be what you want, because you'll want to handle each element individually. YMMV.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/catalog">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>Artist</th>
</tr>
<xsl:apply-templates />
</table>
</body>
</html>
</xsl:template>
<xsl:template match="cd">
<tr><xsl:apply-templates /></tr>
</xsl:template>
<xsl:template match="cd/*">
<td><xsl:apply-templates /></td>
</xsl:template>
<xsl:template match="bold">
<b><xsl:apply-templates /></b>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1
Reputation: 86744
Here's what you need:
<xsl:for-each select="cd">
<tr>
<td><xsl:apply-templates select="title"/></td>
<td><xsl:apply-templates select="artist"/></td>
</tr>
</xsl:for-each>
Since you don't have any templates matching title
or artist
the default will be to copy their text nodes to the output. You don't need to do that yourself.
Here's a modification that uses more idiomatic "push" processing:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="bold">
<b><xsl:value-of select="." /></b>
</xsl:template>
<xsl:template match="/catalog">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>Artist</th>
</tr>
<xsl:apply-templates select="cd"/>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="cd">
<tr>
<td><xsl:apply-templates select="title"/></td>
<td><xsl:apply-templates select="artist"/></td>
</tr>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1