2012-07-03 140 views
1

我正在研究一個基於XML Feed的發佈時間表的網頁,該XML Feed是我無權更改的。使用XSLT根據屬性對XML元素進行分組

飼料看起來是這樣的:

<track name="Track 1"> 
    <session name="Session 1" starttime="2012-06-06 10:45" endtime="2012-06-06 12:45"> 
     <presentation name="Presentation 1"> 
     ...presentation info 
     </presentation> 
     <presentation name="Presentation 2"> 
     ...presentation info 
     </presentation> 
    </session> 
    <session name="Session 2" starttime="2012-06-06 10:45" endtime="2012-06-06 12:45"> 
     <presentation name="Presentation 3"> 
     ...presentation info 
     </presentation> 
     <presentation name="Presentation 4"> 
     ...presentation info 
     </presentation> 
    </session> 
    <session name="Session 3" starttime="2012-06-07 08:45" endtime="2012-06-07 10:45"> 
     <presentation name="Presentation 5"> 
     ...presentation info 
     </presentation> 
     <presentation name="Presentation 6"> 
     ...presentation info 
     </presentation> 
    </session> 
    </track> 

目前,我正在做一個<xsl:for-each select="session">環拉出信息,但是與我輸出重複日期和時間結束。

我沒有問題做實際的日期和時間解析,所以我目前正在輸出2012年6月6日; 10:45沒有問題,但它正在每次複製因的for-each,具體如下:

2012年6月6日

10:45-12:45

會話1:演示1,演示2

2012年6月6日

10:45-12:45

會話2:演示3,介紹4

2012年6月7日:

8:45-10:45

第3場:演示5演示6

我想什麼是莫名其妙地拉出所有常見的日期時間,例如,獲取輸出,如:

2012年6月6日:

10:45-12:45

會議1:演示1,演示2

會話2:演示3,介紹4

2012年6月7日:

8:45-10:45

第三節:演示5,演示6

作爲參考,這裏是我目前的實施:

<xsl:for-each select="session"> 
    <h4> 
    <!-- output to Month, DD, YYYY --> 
    <xsl:call-template name="formatDate"> 
     <xsl:with-param name="dateTime" select="@starttime" /> 
    </xsl:call-template> 
    </h4> 

    <h5> 
    <!-- output time --> 
    <xsl:call-template name="formatTime"> 
     <xsl:with-param name="dateTime" select="@starttime" /> 
    </xsl:call-template> - 
    <xsl:call-template name="formatTime"> 
     <xsl:with-param name="dateTime" select="@endtime" /> 
    </xsl:call-template> 
    </h5> 

    <!-- session title --> 
    <h5><xsl:value-of select="@name"/></h5> 

    <!-- presentation title -->   
    <xsl:for-each select="presentation"> 
    <xsl:value-of select="@name"/><xsl:element name="br"/> 
    </xsl:for-each> 

</xsl:for-each> 

和日期時間格式:

<!-- formatting dateTime --> 
<xsl:template name="formatDate"> 
    <xsl:param name="dateTime" /> 
    <xsl:variable name="date" select="substring-before($dateTime, ' ')" /> 
    <xsl:variable name="year" select="substring-before($date, '-')" /> 
    <xsl:variable name="month" select="number(substring-before(substring-after($date, '-'), '-'))" /> 
    <xsl:variable name="day" select="number(substring-after(substring-after($date, '-'), '-'))" /> 

    <!-- output --> 
    <xsl:choose> 
    <xsl:when test="$month = '1'">January</xsl:when> 
    <xsl:when test="$month = '2'">February</xsl:when> 
    <xsl:when test="$month = '3'">March</xsl:when> 
    <xsl:when test="$month = '4'">April</xsl:when> 
    <xsl:when test="$month = '5'">May</xsl:when> 
    <xsl:when test="$month = '6'">June</xsl:when> 
    <xsl:when test="$month = '7'">July</xsl:when> 
    <xsl:when test="$month = '8'">August</xsl:when> 
    <xsl:when test="$month = '9'">September</xsl:when> 
    <xsl:when test="$month = '10'">October</xsl:when> 
    <xsl:when test="$month = '11'">November</xsl:when> 
    <xsl:when test="$month = '12'">December</xsl:when> 
    </xsl:choose> 
    <xsl:value-of select="' '" /> 
    <xsl:value-of select="$day" /> 
    <xsl:value-of select="', '" /> 
    <xsl:value-of select="$year" /> 
</xsl:template> 

<!-- formatting dateTime --> 
<xsl:template name="formatTime"> 
    <xsl:param name="dateTime" /> 
    <xsl:value-of select="substring-after($dateTime, ' ')" /> 
</xsl:template> 

回答

1

您使用Muenchian method要組。立即加入這個樣式表的根元素裏面:

<xsl:key name="sessions-by-track-name-starttime-and-endtime" match="/track/session" use="concat(parent::track/@name, ' ', @starttime, ' ', @endtime)"/> 

然後更新您的XSLT,如下所示:

<xsl:for-each select="session[generate-id() = generate-id(key('sessions-by-track-name-starttime-and-endtime', concat(parent::track/@name, ' ', @starttime, ' ', @endtime))[1])]"> 
    <h4> 
    <!-- output to Month, DD, YYYY --> 
    <xsl:call-template name="formatDate"> 
     <xsl:with-param name="dateTime" select="@starttime" /> 
    </xsl:call-template> 
    </h4> 

    <h5> 
    <!-- output time --> 
    <xsl:call-template name="formatTime"> 
     <xsl:with-param name="dateTime" select="@starttime" /> 
    </xsl:call-template> - 
    <xsl:call-template name="formatTime"> 
     <xsl:with-param name="dateTime" select="@endtime" /> 
    </xsl:call-template> 
    </h5> 

    <xsl:for-each select="key('sessions-by-track-name-starttime-and-endtime', concat(parent::track/@name, ' ', @starttime, ' ', @endtime))"> 

    <!-- session title --> 
    <h5><xsl:value-of select="@name"/></h5> 

    <!-- presentation title -->   
    <xsl:for-each select="presentation"> 
     <xsl:value-of select="@name"/><xsl:element name="br"/> 
    </xsl:for-each> 

    </xsl:for-each> 

</xsl:for-each> 
+0

開箱即用,謝謝你親切的先生 – espais

1

首先,避免-每個XSLT並應用節點模板代替。

試試這個(濃縮,沒有call-template的調用,因爲你沒有發佈那個位),你可以運行在this XMLPlayground

<!-- sessions --> 
<xsl:template match='track/session'> 
    <xsl:if test='not(preceding-sibling::session[@starttime = current()/@starttime])'> 
     <h4><xsl:value-of select="@starttime" /></h4> 
     <h5><xsl:value-of select="concat(@starttime,' - ',@endtime)" /></h5> 
     <p><xsl:apply-templates select="presentation" /></p> 
     <xsl:variable name='other_pres' select="following-sibling::session[@starttime = current()/@starttime]/presentation" /> 
     <xsl:if test='count($other_pres)'> 
      <p><xsl:apply-templates select="$other_pres" /></p> 
     </xsl:if> 
    </xsl:if> 
</xsl:template> 

<!-- presentations --> 
<xsl:template match='presentation'> 
    <xsl:if test='position() = 1'> 
     <strong><xsl:value-of select='../@name' />: </strong> 
    </xsl:if> 
    <xsl:value-of select="@name"/> 
    <xsl:if test='position() != last()'>, </xsl:if> 
</xsl:template> 

的概念在這裏,在session模板中,對於每一個環節,我們先看看我們之前已經處理與會話相同@starttime(因爲我認爲這是你的意思屬性負責重複)。如果是這樣,我們跳過它。

然後,在輸出會話的演示文稿(由他們自己的模板處理時,您會注意到),我們還處理當前session的兄弟節點的任何演示。

Output(無訪問您的日期格式模板)

<h4>2012-06-06 10:45</h4> 
<h5>2012-06-06 10:45 - 2012-06-06 12:45</h5> 
<p><strong>Session 1: </strong>Presentation 1, Presentation 2</p><p><strong>Session 2: </strong>Presentation 3, Presentation 4</p> 

<h4>2012-06-07 08:45</h4> 
<h5>2012-06-07 08:45 - 2012-06-07 10:45</h5> 
<p><strong>Session 3: </strong>Presentation 5, Presentation 6</p> 
+0

我看到你在做什麼都有,但另一種方法涉及更少的代碼重構從我結束... upvote你的方式爲你的時間:) – espais

+0

是的Muenchian方法是這樣做的另一個明顯的方式。我去了一個沒有使用鍵:)塔無論如何投票,很高興你得到它以任何方式排序。 – Utkanos

+0

抱歉疏浚舊的答案,但我要去與你的。一個接受......說我已經創建了一個變量來替換你的if-test($ cdate)中的@starttime ...有沒有辦法進一步應用呢?基本上,試圖從我擁有的日期時間字段中去除dd/mm/yy,然後排序。 – espais

相關問題