xslt 通过子节点和位置选择 rss 项目
Posted
技术标签:
【中文标题】xslt 通过子节点和位置选择 rss 项目【英文标题】:xslt select rss item by both child node and position 【发布时间】:2013-11-01 17:08:54 【问题描述】:将 XSLT 1.0 与 RSS 日历提要一起使用,我想排除过期的项目 - 那些在当前日期之前具有 pubDates 的项目 - 然后只包括三个当前项目。结果应该是接下来的三个未来事件。我使用http://exslt.org/date/index.html 为当前系统日期创建了一个变量。问题是,当我选择 =“item[not(position() > 4)] 和 substring(item/pubDate,5,11) >= $current" 时,如果第一个项目中的任何一个,我最终得到的项目少于三个那些已经过期了。显然我的代码选择了三个项目,然后删除了过期的项目,这不是我想要的。是否可以保存未过期项目的副本,然后选择其中三个?
由于XSLT 1.0 doesn't provide inequality string comparison operators,我可能无法查看诸如“2013 年 10 月 30 日”之类的值是否大于“2013 年 10 月 29 日”,我可以将值格式化为 30102013 和 29102013,但似乎仍然我试图在选择之前连接频道/项目/pubDate。因此,如果可能的话,了解如何分两个阶段处理 XML/RSS 会很有帮助。
我尝试了几种技术,结果相似:
<xsl:for-each select="substring(item/pubDate,5,11) >= $current and item[not(position() > 4)]">
<xsl:template match="item[not(position() > 4)]">
<xsl:apply-templates select="item"/>
<xsl:for-each select="substring(item/pubDate,5,11) >= $current">
<xsl:if test=" item[not(position() > 4)]">
示例 XML:
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<atom:link href="http://calendar.example.edu/" rel="self" type="application/rss+xml"/>
<title>University Calendar - Featured Events</title>
<link>http://calendar.example.edu/</link>
<description>List of featured events on calendar.example.edu</description>
<language>en-us</language>
<pubDate>Tue, 27 Oct 2013 20:47:05 CDT</pubDate>
<item>
<title>Creative Movement Program Student Show</title>
<description/>
<link>http://calendar.example.edu/?&y=2013&m=10&d=30&eventdatetime_id=19721</link>
<guid>calendar.example.edu/?&y=2013&m=10&d=30&eventdatetime_id=19721</guid>
<pubDate>Wed 30 Oct 2013, 17:00:00 CDT</pubDate>
</item>
<item>
<title>Philosophy Career Fair</title>
<description>The Department of Philosophy brings recruiters from around the state to interview seniors and alumni.</description>
<link>http://calendar.example.edu/?&y=2013&m=11&d=04&eventdatetime_id=16427</link>
<guid>calendar.example.edu/?&y=2013&m=11&d=04&eventdatetime_id=16427</guid>
<pubDate>Mon 04 Nov 2013, 07:00:00 CDT</pubDate>
</item>
<item>
<title>Football vs. Caltech</title>
<description/>
<link>http://calendar.example.edu/?&y=2013&m=12&d=07&eventdatetime_id=16521</link>
<guid>calendar.example.edu/?&y=2013&m=12&d=07&eventdatetime_id=16521</guid>
<pubDate>Sat 07 Dec 2013, 00:00:00 CDT</pubDate>
</item>
<item>
<title>Mural Exhibition</title>
<description>The College of Arts presents an overview of wall paintings from the Caves of Lascaux to the Kiev train station.</description>
<link>http://calendar.example.edu/?&y=2014&m=01&d=14&eventdatetime_id=16759</link>
<guid>calendar.example.edu/?&y=2014&m=01&d=14&eventdatetime_id=16759</guid>
<pubDate>Tue 14 Jan 2014, 07:00:00 CDT</pubDate>
</item>
</channel>
</rss>
当前 XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" extension-element-prefixes="date" version="1.0" xmlns:date="http://exslt.org/dates-and-times" >
<xsl:template name="lf">
<xsl:text/>
</xsl:template>
<xsl:template match="rss">
<section id="campusEvents" role="region">
<h2 id="eventsTitle">
<a href="http://calendar.test.edu/">Campus Events</a>
</h2>
<xsl:apply-templates select="channel"/>
<div class="moreLink">
<a href="http://calendar.test.edu/">Full Calendar</a>
</div>
</section>
</xsl:template>
<xsl:template match="channel">
<xsl:variable name="currDay" select="substring(date:date(),9,2)"/>
<xsl:variable name="currMonth">
<xsl:call-template name="format-month">
<xsl:with-param name="date" select="date:date()"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="currYear" select="substring(date:date(),1,4)"/>
<xsl:variable name="current" select="concat($currDay,' ',$currMonth,' ',$currYear )"/>
<xsl:for-each select="item[not(position() > 4)] and substring(item/pubDate,5,11) >= $current">
<div class="eventBlock">
<xsl:call-template name="lf"/>
<div class="dateBlock">
<xsl:call-template name="lf"/>
<div class="eventMonth">
<xsl:value-of select="substring(pubDate,8,3)"/>
</div>
<div class="eventDate">
<xsl:value-of select="substring(pubDate,5,2)"/>
</div>
</div>
<xsl:call-template name="lf"/>
<div class="eventDescription">
<a class="url" href="link">
<xsl:value-of select="title"/>
</a>
<xsl:call-template name="lf"/>
</div>
<xsl:call-template name="lf"/>
</div>
<xsl:call-template name="lf"/>
</xsl:for-each>
</xsl:template>
<xsl:template name="format-month">
<xsl:param name="date"/>
<xsl:variable name="monthName" select="substring(date:date(),6,2)"/>
<xsl:variable name="month">
<xsl:choose>
<xsl:when test="$monthName = '01'">Jan</xsl:when>
<xsl:when test="$monthName = '02'">Feb</xsl:when>
<xsl:when test="$monthName = '03'">Mar</xsl:when>
<xsl:when test="$monthName = '04'">Apr</xsl:when>
<xsl:when test="$monthName = '05'">May</xsl:when>
<xsl:when test="$monthName = '06'">Jun</xsl:when>
<xsl:when test="$monthName = '07'">Jul</xsl:when>
<xsl:when test="$monthName = '08'">Aug</xsl:when>
<xsl:when test="$monthName = '09'">Sep</xsl:when>
<xsl:when test="$monthName = '10'">Oct</xsl:when>
<xsl:when test="$monthName = '11'">Nov</xsl:when>
<xsl:when test="$monthName = '12'">Dec</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:variable>
<xsl:value-of select="$month"/>
</xsl:template>
</xsl:stylesheet>
期望结果(10 月 30 日活动结束后):
<section role="region" id="campusEvents">
<h2 id="eventsTitle">
<a href="http://calendar.test.edu/">Campus Events</a>
</h2>
<div class="eventBlock">
<div class="dateBlock">
<div class="eventMonth">Nov</div>
<div class="eventDate">04</div>
</div>
<div class="eventDescription">
<a href="http://calendar.example.edu/?&y=2013&m=11&d=04&eventdatetime_id=16427" class="url">Philosophy Career Fair</a>
</div>
</div>
<div class="eventBlock">
<div class="dateBlock">
<div class="eventMonth">Dec</div>
<div class="eventDate">07</div>
</div>
<div class="eventDescription">
<a href="http://calendar.example.edu/?&y=2013&m=12&d=07&eventdatetime_id=16521" class="url">Football vs. Caltech</a>
</div>
</div>
<div class="eventBlock">
<div class="dateBlock">
<div class="eventMonth">Jan</div>
<div class="eventDate">14</div>
</div>
<div class="eventDescription">
<a href="http://calendar.example.edu/?&y=2014&m=01&d=14&eventdatetime_id=16759" class="url">Mural Exhibition</a>
</div>
</div>
<div class="moreLink">
<a href="http://calendar.test.edu/">Full Calendar</a>
</div>
</section>
【问题讨论】:
【参考方案1】:如果您想比较日期,那么您必须以某种方式将各种日期表达式转换为全数字 yyyymmdd 格式(例如 20131029),以便时间顺序等同于数字顺序。对于当前日期,这是一个简单的全局变量:
<xsl:variable name="curDateStr" select="date:date()" />
<xsl:variable name="currentDateNum"
select="concat(substring($curDateStr, 1, 4),
substring($curDateStr, 6, 2),
substring($curDateStr, 9, 2))" />
为了解析 pubDate
值,我将使用与当前 format-month
相反的命名模板
<xsl:template name="parse-date">
<xsl:param name="dateStr" />
<xsl:value-of select="substring($dateStr, 12, 4)" /><!-- year -->
<xsl:variable name="month" select="substring($dateStr, 8, 3)" />
<xsl:choose>
<xsl:when test="$month = 'Jan'">01</xsl:when>
<xsl:when test="$month = 'Feb'">02</xsl:when>
<!-- etc. -->
</xsl:choose>
<xsl:value-of select="substring($dateStr, 5, 2)" /><!-- day -->
</xsl:template>
现在可以使用尾递归模板来实现主要逻辑,这是您可以在 XSLT 中获得的最接近“while”循环的模板:
<xsl:template match="item">
<xsl:param name="numItems" select="3" />
<xsl:if test="$numItems > 0"><!-- stop if we hit the threshold -->
<xsl:variable name="itemDate">
<xsl:call-template name="parse-date">
<xsl:with-param name="dateStr" select="pubDate" />
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$itemDate > $currentDateNum">
<!-- do what you need to do to produce output for this item -->
<!-- ..... -->
<xsl:apply-templates select="following-sibling::item[1]">
<!-- we processed this item, so decrement $numItems -->
<xsl:with-param name="numItems" select="$numItems - 1" />
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="following-sibling::item[1]">
<!-- we ignored this item, so don't decrement $numItems -->
<xsl:with-param name="numItems" select="$numItems" />
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
<xsl:if>
</xsl:template>
然后在channel
模板中,您通过仅将模板应用于第一个项来开始这个“循环”
<xsl:template match="channel">
<xsl:apply-templates select="item[1]" />
</xsl:template>
然后项目模板将继续处理同级,直到它完全用完 item
元素,或者它处理了 3 个符合日期条件的项目。
【讨论】:
精彩而创新!一旦我更改了一些变量名称以使它们彼此一致,它就像一个魅力。 @MichaelMcGinnis 感谢编辑,我认为手指比大脑快。以上是关于xslt 通过子节点和位置选择 rss 项目的主要内容,如果未能解决你的问题,请参考以下文章