2013-11-01 2 views
1

Используя XSLT 1.0 с лентой календаря RSS, я хочу исключить истекшие элементы - те, у которых есть pubDates до текущей даты, - затем включать только три текущих элемента. Результатом должны стать следующие три будущих события. Я использовал http://exslt.org/date/index.html для создания переменной для текущей системной даты. Проблема заключается в том, что когда я выбираю = "item [not (position() > 4)] и substring (item/pubDate, 5,11) & gt = $ current", я получаю менее трех элементов, если какой-либо из первые из них истекли. По-видимому, мой код выбирает три элемента, а затем удаляет истекшие, что не то, что я хочу. Можно ли сохранить копию неистекших предметов, а затем выбрать три из них?xslt select rss item как дочерним узлом, так и позицией

С XSLT 1.0 doesn't provide inequality string comparison operators, возможно, я не могу увидеть, больше ли значение, например «30 октября 2013», больше, чем «29 октября 2013 года», я могу форматировать значения как 30102013 и 29102013, но все же кажется, что я Я пытаюсь объединить канал/item/pubDate, прежде чем я его выберу. Поэтому было бы полезно знать, как обрабатывать XML/RSS в два этапа, если это возможно.

Я попробовал несколько методов, с аналогичными результатами:

<xsl:for-each select="substring(item/pubDate,5,11) &gt;= $current and item[not(position() &gt; 4)]"> 

    <xsl:template match="item[not(position() &gt; 4)]"> 
     <xsl:apply-templates select="item"/> 

    <xsl:for-each select="substring(item/pubDate,5,11) &gt;= $current"> 
     <xsl:if test=" item[not(position() &gt; 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/?&amp;y=2013&amp;m=10&amp;d=30&amp;eventdatetime_id=19721</link> 
     <guid>calendar.example.edu/?&amp;y=2013&amp;m=10&amp;d=30&amp;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/?&amp;y=2013&amp;m=11&amp;d=04&amp;eventdatetime_id=16427</link> 
     <guid>calendar.example.edu/?&amp;y=2013&amp;m=11&amp;d=04&amp;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/?&amp;y=2013&amp;m=12&amp;d=07&amp;eventdatetime_id=16521</link> 
     <guid>calendar.example.edu/?&amp;y=2013&amp;m=12&amp;d=07&amp;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/?&amp;y=2014&amp;m=01&amp;d=14&amp;eventdatetime_id=16759</link> 
     <guid>calendar.example.edu/?&amp;y=2014&amp;m=01&amp;d=14&amp;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() &gt; 4)] and substring(item/pubDate,5,11) &gt;= $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> 

желаемого результата (после того, как 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/?&amp;y=2013&amp;m=11&amp;d=04&amp;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/?&amp;y=2013&amp;m=12&amp;d=07&amp;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/?&amp;y=2014&amp;m=01&amp;d=14&amp;eventdatetime_id=16759" class="url">Mural Exhibition</a> 
    </div> 
    </div> 
    <div class="moreLink"> 
    <a href="http://calendar.test.edu/">Full Calendar</a> 
    </div> 
</section> 

ответ

2

Если вы хотите сравнить даты, то вам придется как-то массировать различные выражения даты на всезначные 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 к «а» петле:

<xsl:template match="item"> 
    <xsl:param name="numItems" select="3" /> 
    <xsl:if test="$numItems &gt; 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 &gt; $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 вещи, которые соответствуют критериям даты.

+0

Замечательный и инновационный! Как только я изменил несколько имен переменных, чтобы они были согласованы друг с другом, он работал как шарм. –

+0

@MichaelMcGinnis спасибо за редактирование, пальцы были быстрее, чем мозг, я думаю. –

Смежные вопросы