Reputation: 23
I'm fairly new to xsl and am trying to find a way to hide, or mute, all but two nodes in an wordpress rss feed's xml, structured like so:
?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
>
<channel>
<title>Title</title>
<atom:link href="http://www.alink.com" rel="self" type="application/rss+xml" />
<link>http://www.alink.com</link>
<description>Just another WordPress site</description>
<lastBuildDate>Sun, 21 Apr 2013 22:13:55 +0000</lastBuildDate>
<language>en-US</language>
<sy:updatePeriod>hourly</sy:updatePeriod>
<sy:updateFrequency>1</sy:updateFrequency>
<generator>http://wordpress.org/?v=3.5.1</generator>
<item>
<title>A Title</title>
<link>http://www.alink.com</link>
<comments>comments</comments>
<pubDate>Sun, 21 Apr 2013 22:13:55 +0000</pubDate>
<dc:creator>aUser</dc:creator>
<category><![CDATA[Uncategorized]]></category>
<guid isPermaLink="false">http://www5.uifoundation.org/news/?p=112</guid>
<description><![CDATA[Post[...]]]></description>
<content:encoded> Posted October 10, 2013 </content:encoded>
<wfw:commentRss>http://www.alink.com</wfw:commentRss>
<slash:comments>0</slash:comments>
</item>
But I want to display only the channel/title and channel/link in my transformation. I was thinking something along the lines of using an empty template on all the nodes, like this
<xsl:template match="channel/* EXCEPTION channel/item/title | channel/item/link" />
I'm unsure of how to declare the exception though. If there's a better way of doing this, I'd be open to that too
I really just want the output to be an unordered list of item/title
, with the value of item/link
, with everything else hidden. An example of the output would be:
<ul>
<li>
<a href= "www.aLink.com">A Title</a>
</li>
</ul>
Upvotes: 2
Views: 7350
Reputation: 28004
You can do it using separate templates, some of which are empty, and with different priorities:
<xsl:template match="channel/*" priority="0" /> <!-- swallow these, no output -->
<xsl:template match="channel/item | channel/link" priority="1">
<xsl:copy-of select="." /> <!-- copy to output -->
</xsl:template>
In the case of channel/item
and channel/link
, the second template will override the first because of its higher priority. In the case of other children of channel
, the first template will fire.
(Note that templates have a default priority based on the type of match pattern; and there are also rules for what to do if two templates with equal priority match the same node. However if you make priority explicit wherever there is potential for two templates to match the same node, you won't have to fiddle with those unseen rules.)
In the absence of other templates specifying what to do with <rss>
and <channel>
, the default template will apply, and they will be processed but not copied to the output, except for text nodes. That would be a bit of a mess. If you want to copy those two elements (but not all their descendants) to the output, try this template:
<xsl:template match="rss | channel">
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
Now that the desired output has been specified, I would say the approach should be completely different. Your first template can be:
<xsl:template match="/">
<ul>
<xsl:apply-templates select="rss/channel/item" />
</ul>
</xsl:template>
and your second template transforms each item into an <li>
:
<xsl:template match="item">
<li>
<a href="{link}"><xsl:value-of select="title" /></a>
</li>
</xsl:template>
This is more of a "pull" rather than a "push" approach. You want specific nodes from the input, and the input's structure is highly predictable. By using specific apply-templates select expressions, instead of the generic <xsl:apply-templates select="*" />
, you avoid the need for exception templates, because only the nodes you select will be processed.
Upvotes: 5