1

変更するためのアクセス権がないXMLフィードに基づいてプレゼンテーションのスケジュールを公開するWebページに取り組んでいます。

フィードは次のようになります。

  <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

セッション3:プレゼンテーション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>
4

2 に答える 2

1

まず、XSLTでfor-eachを避け、代わりにノードをテンプレートに適用します。

call-templateこれを試してみてください(要約されており、そのビットを投稿しなかったため、への呼び出しはありません)。これは、この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

出力:(日付フォーマットテンプレートにアクセスせずに)

<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>
于 2012-07-03T18:10:33.167 に答える
1

Muenchianメソッドを使用してグループ化します。これをスタイルシートのルート要素のすぐ内側に追加します。

<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>
于 2012-07-03T18:17:15.040 に答える