在XSL中隐藏XML元素?

Haw*_*ick 2 xml xslt rss xml-parsing

我是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>
Run Code Online (Sandbox Code Playgroud)

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

<xsl:template match="channel/* EXCEPTION channel/item/title | channel/item/link" />
Run Code Online (Sandbox Code Playgroud)

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

我真的只是希望输出是一个无序的列表item/title,其值为item/link,其他一切都隐藏了.输出的一个例子是:

<ul>
  <li>
    <a href= "www.aLink.com">A Title</a>
  </li>
</ul> 
Run Code Online (Sandbox Code Playgroud)

Lar*_*rsH 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>
Run Code Online (Sandbox Code Playgroud)

在的情况下,channel/itemchannel/link,第二个模板将覆盖第一,因为其优先级较高.对于其他孩子channel,第一个模板将会触发.

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

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

<xsl:template match="rss | channel">
  <xsl:copy>
    <xsl:apply-templates />
  </xsl:copy>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

编辑

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

<xsl:template match="/">
  <ul>
    <xsl:apply-templates select="rss/channel/item" />
  </ul>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

并且您的第二个模板将每个项目转换为<li>:

<xsl:template match="item">
  <li>
    <a href="{link}"><xsl:value-of select="title" /></a> 
  </li>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

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

  • @HawkEyeNick请记住点击旁边的复选标记,将Lars的答案标记为已接受. (2认同)