2

操作したい日付のイベントの XML フィードがあります。

ソース XML:

<?xml version="1.0" encoding="UTF-8"?>
<events>
  <event>
    <!-- various elements -->
    <start_datetime value="2012-02-09 10:00:00"/>
    <end_datetime value="2012-02-09 11:00:00"/>
    <!-- various elements -->
  </event>
  <event>
    <!-- various elements -->
    <start_datetime value="2012-02-09 10:00:00"/>
    <end_datetime value="2012-02-10 15:00:00"/>
    <!-- various elements -->
  </event>
  <!-- other events -->
</events>

/events/event[1]これは、同じ日に開始および終了するイベントであることに注意してください。/events/event[2]、一方、2 日間にまたがります。これが私が達成したいことです:

  1. 同じ日のイベントの場合は、日時をそのままにして、それらの属性を子要素に変換するだけです。
  2. <event>複数日にまたがるイベントの場合、(a) 全体の期間に一致し、(b) 必要に応じて 1 日分の時間にまたがる複数の要素を作成したいと考えています。

したがって、私の理想的な XSLT は次のようになります。

必要な XML:

<?xml version="1.0" encoding="UTF-8"?>
<events>
  <event>
    <!-- various elements -->
    <start_datetime>2012-02-09 10:00:00</start_datetime>
    <end_datetime>2012-02-09 11:00:00</end_datetime>
    <!-- various elements -->
  </event>
  <event>
    <!-- various elements -->
    <start_datetime>2012-02-09 10:00:00</start_datetime>
    <end_datetime>2012-02-09 23:59:59</end_datetime>
    <!-- various elements -->
  </event>
  <event>
    <!-- various elements -->
    <start_datetime>2012-02-10 00:00:00</start_datetime>
    <end_datetime>2012-02-10 15:00:00</end_datetime>
    <!-- various elements -->
  </event>
  <!-- other events -->
</events>

私のルールがどのように満たされているかに注意してください。

  • 同じ日に発生するため/events/event[1]、そのままにしておきます (属性値を子要素に変更するという簡単な作業以外は)。
  • /events/event[2]つまり、2 つのブロックが必要<event>です (1 つは開始日時からその日の午後 11:59:59 まで、もう 1 つは終了日の 00:00:00 から終了日時まで)。

最終的な考慮事項:

  • これは、XSLT 1.0 で実現する必要があります。

  • 私は EXSLT の日付関数を使用することに反対しているわけではありません。

泥のように透明?いつもお世話になっております。:)

4

1 に答える 1

4

これは、EXSLT 日付関数を使用しない XSLT 1.0 ソリューションですが、名前付きテンプレートを使用して特定の日付に追加し、文字列操作関数を使用して日付文字列から年、月、日を追加します。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="@*|node()">
      <xsl:copy>
         <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="event" name="event">
      <xsl:param name="start_datetime" select="start_datetime/@value"/>
      <xsl:variable name="end_datetime" select="end_datetime/@value"/>
      <event>
         <xsl:apply-templates select="start_datetime/preceding-sibling::node()"/>
         <start_datetime>
            <xsl:value-of select="$start_datetime"/>
         </start_datetime>
         <end_datetime>
            <xsl:choose>
               <xsl:when test="substring($start_datetime, 1, 10) = substring($end_datetime ,1, 10)">
                  <xsl:value-of select="$end_datetime"/>
               </xsl:when>
               <xsl:otherwise>
                  <xsl:value-of select="concat(substring($start_datetime, 1, 10), ' 23:59:59')"/>
               </xsl:otherwise>
            </xsl:choose>
         </end_datetime>
         <xsl:apply-templates select="end_datetime/following-sibling::node()"/>
      </event>
      <xsl:if test="substring($start_datetime, 1, 10) != substring($end_datetime ,1, 10)">
         <xsl:call-template name="event">
            <xsl:with-param name="start_datetime">
               <xsl:call-template name="addOneToDate">
                  <xsl:with-param name="date" select="$start_datetime"/>
               </xsl:call-template>
            </xsl:with-param>
         </xsl:call-template>
      </xsl:if>
   </xsl:template>

   <xsl:template name="addOneToDate">
      <xsl:param name="date"/>
      <xsl:variable name="year" select="number(substring($date, 1, 4))"/>
      <xsl:variable name="month" select="number(substring($date, 6, 2))"/>
      <xsl:variable name="day" select="number(substring($date, 9, 2))"/>
      <xsl:variable name="daysInMonth">
         <xsl:choose>
            <xsl:when test="$month = 2">
               <xsl:choose>
                  <xsl:when test="($year div 4 = 0 and $year div 100 != 0) or ($year div 400 = 0)">29</xsl:when>
                  <xsl:otherwise>28</xsl:otherwise>
               </xsl:choose>
            </xsl:when>
            <xsl:when test="$month = 4 or $month = 6 or $month = 9 or $month = 11">30</xsl:when>
            <xsl:otherwise>31</xsl:otherwise>
         </xsl:choose>
      </xsl:variable>
      <xsl:choose>
         <xsl:when test="$day != $daysInMonth">
            <xsl:value-of select="concat($year, '-', format-number($month, '00'), '-', format-number($day + 1, '00'), ' 00:00:00')"/>
         </xsl:when>
         <xsl:when test="$month = 12">
            <xsl:value-of select="concat($year + 1, '-01-01 00:00:00')"/>
         </xsl:when>
         <xsl:otherwise>
            <xsl:value-of select="concat($year, '-', format-number($month + 1, '00'), '-01 00:00:00')"/>
         </xsl:otherwise>
      </xsl:choose>
   </xsl:template>
</xsl:stylesheet>

サンプル XML に適用すると、次のように出力されます。

<events>
   <event>
      <!-- various elements -->
      <start_datetime>2012-02-09 10:00:00</start_datetime>
      <end_datetime>2012-02-09 11:00:00</end_datetime>
      <!-- various elements -->
   </event>
   <event>
      <!-- various elements -->
      <start_datetime>2012-02-09 10:00:00</start_datetime>
      <end_datetime>2012-02-09 23:59:59</end_datetime>
      <!-- various elements -->
   </event>
   <event>
      <!-- various elements -->
      <start_datetime>2012-02-10 00:00:00</start_datetime>
      <end_datetime>2012-02-10 15:00:00</end_datetime>
      <!-- various elements -->
   </event>
   <!-- other events -->
</events>

EXSLTを使用する方が簡単になることに同意していただけると思います....

于 2012-05-21T22:02:40.920 に答える