Reputation: 522
I have am XML file that contains a child element nested within another element inside a <p>
element. My XSLT is pulling the <p>
element fine, but it's ignoring the <span>
. I know it has something to do with the xPath, but I can't figure out how to do it with this XSLT structure.
<newsItem>
<inlineXml>
<h2>Calendar</h2>
<p><strong><span class="dates">June 16-18:</span>National Conference, Denver</strong></p>
<p><strong><span class="dates">June 19-21:</span>Local Event, Chicago</strong></p>
<inlineXml>
</newsItem>
Here is my XSLT:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="no"/>
<xsl:strip-space elements="*"/>
<xsl:template match="newsItem">
<newsItem><xsl:apply-templates/></newsItem>
</xsl:template>
<xsl:template match="h2">
<h2><xsl:value-of select="normalize-space(.)"/></h2>
</xsl:template>
<xsl:template match="p/strong/span">
<date><xsl:value-of select="."/></date>
</xsl:template>
<xsl:template match="p">
<p><xsl:value-of select="normalize-space(.)"/></p>
</xsl:template>
</xsl:stylesheet>
Here's the desired result:
<newsItem>
<inlineXml>
<h2>Calendar</h2>
<p><date>June 16-18:</date>National Conference, Denver</p>
<p><date>June 19-21:</date>Local Event, Chicago</p>
<inlineXml>
</newsItem>
This is probably very simple, but it's stumping me.
Thanks
Upvotes: 0
Views: 1074
Reputation: 12729
This XSLT 1.0 stylesheet ...
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="html" version="5" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<html>
<head>
<title>Inline XML</title>
</head>
<body>
<xsl:apply-templates />
</body>
</html>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="strong[span/@class='dates']">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="strong/span[@class='dates']">
<date>
<xsl:apply-templates />
</date>
</xsl:template>
</xsl:stylesheet>
... will transform this input document ...
<newsItem>
<inlineXml>
<h2>Calendar</h2>
<p><strong><span class="dates">June 16-18:</span>National Conference, Denver</strong></p>
<p><strong><span class="dates">June 19-21:</span>Local Event, Chicago</strong></p>
</inlineXml>
</newsItem>
... into this output html page ...
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Inline XML</title>
</head>
<body>
<newsItem>
<inlineXml>
<h2>Calendar</h2>
<p>
<date>June 16-18:</date>National Conference, Denver
</p>
<p>
<date>June 19-21:</date>Local Event, Chicago
</p>
</inlineXml>
</newsItem>
</body>
</html>
date
element is intended to be a microformat,
you should consider the html 5 element time
.Upvotes: 0
Reputation: 116993
If you change:
<xsl:template match="p">
<p><xsl:value-of select="normalize-space(.)"/></p>
</xsl:template>
to:
<xsl:template match="p">
<p><xsl:apply-templates/></p>
</xsl:template>
your result will become:
<?xml version="1.0"?>
<newsItem>
<h2>Calendar</h2>
<p><date>June 16-18:</date>National Conference, Denver</p>
<p><date>June 19-21:</date>Local Event, Chicago</p>
</newsItem>
which is very close to the expected result, except the <inlineXml>
wrapper is missing. This is because there's no template matching it, so if you add:
<xsl:template match="inlineXml">
<inlineXml><xsl:apply-templates/></inlineXml>
</xsl:template>
you will get the expected result exactly.
Note that now you have three very similar templates:
<xsl:template match="newsItem">
<newsItem><xsl:apply-templates/></newsItem>
</xsl:template>
<xsl:template match="p">
<p><xsl:apply-templates/></p>
</xsl:template>
<xsl:template match="inlineXml">
<inlineXml><xsl:apply-templates/></inlineXml>
</xsl:template>
which could be rolled together into one:
<xsl:template match="newsItem | inlineXml | p">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
See also: https://en.wikipedia.org/wiki/Identity_transform
Upvotes: 1