在XSL中隐藏XML元素?

时间:2013-04-22 14:38:28

标签: xml xslt xml-parsing rss

我是xsl的新手,我正试图找到一种方法来隐藏或静音wordpress rss feed的xml中的两个节点,结构如下:

?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>

但我想在转换中只显示频道/标题和频道/链接。我正在考虑在所有节点上使用空模板的方法,比如这个

<xsl:template match="channel/* EXCEPTION channel/item/title | channel/item/link" />

我不确定如何声明异常。如果有更好的方法,我也会对此持开放态度

我真的只希望输出为item/title的无序列表,其值为item/link,其他所有内容都隐藏起来。输出的一个例子是:

<ul>
  <li>
    <a href= "www.aLink.com">A Title</a>
  </li>
</ul> 

1 个答案:

答案 0 :(得分:5)

您可以使用单独的模板来完成,其中一些模板是空的,具有不同的优先级:

<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>

对于channel/itemchannel/link,第二个模板将覆盖第一个模板,因为它具有更高的优先级。对于channel的其他子项,第一个模板将会触发。

(请注意,模板具有基于匹配模式类型的默认优先级;如果两个具有相同优先级的模板与同一节点匹配,则还有一些规则可用。但是,如果您在可能存在的情况下明确优先级两个匹配同一节点的模板,你不必摆弄那些看不见的规则。)

如果没有其他模板指定如何处理<rss><channel>,则默认模板将应用,并且它们将被处理但不会复制到输出,文本节点除外。那会有点混乱。如果要将这两个元素(但不是所有后代)复制到输出中,请尝试以下模板:

<xsl:template match="rss | channel">
  <xsl:copy>
    <xsl:apply-templates />
  </xsl:copy>
</xsl:template>

修改

既然已经指定了所需的输出,我会说这种方法应该是完全不同的。您的第一个模板可以是:

<xsl:template match="/">
  <ul>
    <xsl:apply-templates select="rss/channel/item" />
  </ul>
</xsl:template>

,您的第二个模板会将每个项目转换为<li>

<xsl:template match="item">
  <li>
    <a href="{link}"><xsl:value-of select="title" /></a> 
  </li>
</xsl:template>

这更像是一种“拉动”而非“推动”的方法。您需要输入中的特定节点,并且输入的结构具有高度可预测性。通过使用特定的apply-templates选择表达式而不是通用<xsl:apply-templates select="*" />,您可以避免使用异常模板,因为只会处理您选择的节点。