Форматировать дату в XML через XSLT - PullRequest
36 голосов
/ 01 февраля 2009

Когда я использую сериализатор XML для сериализации DateTime, он записывается в следующем формате:

<Date>2007-11-14T12:01:00</Date>

При передаче этого через таблицу стилей XSLT для вывода HTML, как я могу отформатировать это? В большинстве случаев мне просто нужна дата, а когда мне нужно время, я, конечно, не хочу, чтобы там был «забавный Т».

Ответы [ 6 ]

65 голосов
/ 01 февраля 2009

Вот пара шаблонов 1.0, которые вы можете использовать: -

<xsl:template name="formatDate">
    <xsl:param name="dateTime" />
    <xsl:variable name="date" select="substring-before($dateTime, 'T')" />
    <xsl:variable name="year" select="substring-before($date, '-')" />
    <xsl:variable name="month" select="substring-before(substring-after($date, '-'), '-')" />
    <xsl:variable name="day" select="substring-after(substring-after($date, '-'), '-')" />
    <xsl:value-of select="concat($day, ' ', $month, ' ', $year)" />
</xsl:template>

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

Позвоните им по номеру: -

    <xsl:call-template name="formatDate">
        <xsl:with-param name="dateTime" select="xpath" />
    </xsl:call-template>

и

    <xsl:call-template name="formatTime">
        <xsl:with-param name="dateTime" select="xpath" />
    </xsl:call-template>

где xpath - это путь к элементу или атрибуту, который имеет стандартный формат даты и времени.

25 голосов
/ 01 февраля 2009

Форматирование даты нелегко в XSLT 1.0. Вероятно, самый элегантный способ - написать короткую функцию расширения XSLT на C # для форматирования даты. Вот пример:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                xmlns:myExtension="urn:myExtension"
                exclude-result-prefixes="msxsl myExtension">
  <xsl:output method="xml" indent="yes"/>

  <msxsl:script implements-prefix="myExtension" language="C#">
    <![CDATA[
      public string FormatDateTime(string xsdDateTime, string format)
      {
          DateTime date = DateTime.Parse(xsdDateTime);
          return date.ToString(format); 
      }

    ]]>
  </msxsl:script>

  <xsl:template match="date">
    <formattedDate>
      <xsl:value-of select="myExtension:FormatDateTime(self::node(), 'd')"/>
    </formattedDate>
  </xsl:template>
</xsl:stylesheet>

С этим входным документом

<?xml version="1.0" encoding="utf-8"?>
<date>2007-11-14T12:01:00</date>

вы получите

<?xml version="1.0" encoding="utf-8"?>
<formattedDate>14.11.2007</formattedDate> 

Функция форматирования даты принимает значение даты в виде строки и формат, описанный в Метод DateTime.ToString . Использование структуры DateTime в .NET позволяет бесплатно анализировать произвольные значения даты и времени XSD (включая спецификаторы часового пояса), вычисление часового пояса и локализованный вывод.

Однако имейте в виду, что существует одно предупреждение (http://support.microsoft.com/kb/316775) с расширениями сценариев msxml: каждый раз, когда вы загружаете XSLT, сборка, содержащая код сценария, динамически генерируется и загружается в память. Среда выполнения .NET, эта сборка не может быть выгружена, поэтому вы должны убедиться, что ваш XSLT загружается только один раз (а затем кэшируется для дальнейшего повторного использования). Это особенно важно при работе внутри IIS.

9 голосов
/ 01 февраля 2009

Джон Воркман подробно обсуждает эту проблему и дает несколько решений в этом обсуждении [1] в своем блоге. По сути, анализируйте отдельные компоненты даты и рекомбинируйте в любом порядке. Для вашего случая чистой версией XSLT 1.0+ будет:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="date">
<!-- converts FROM <date>2001-12-31T12:00:00</date> TO some new format (DEFINED below) -->
<xsl:template name="FormatDate">
<xsl:param name="DateTime" />

<xsl:variable name="year" select="substring($DateTime,1,4)" />
<xsl:variable name="month-temp" select="substring-after($DateTime,'-')" />
<xsl:variable name="month" select="substring-before($month-temp,'-')" />
<xsl:variable name="day-temp" select="substring-after($month-temp,'-')" />
<xsl:variable name="day" select="substring($day-temp,1,2)" />
<xsl:variable name="time" select="substring-after($DateTime,'T')" />
<xsl:variable name="hh" select="substring($time,1,2)" />
<xsl:variable name="mm" select="substring($time,4,2)" />
<xsl:variable name="ss" select="substring($time,7,2)" />

<!-- EUROPEAN FORMAT -->
<xsl:value-of select="$day"/>
<xsl:value-of select="'.'"/> <!--18.-->
<xsl:value-of select="$month"/>
<xsl:value-of select="'.'"/> <!--18.03.-->
<xsl:value-of select="$year"/>
<xsl:value-of select="' '"/> <!--18.03.1976 -->
<xsl:value-of select="$hh"/>
<xsl:value-of select="':'"/> <!--18.03.1976 13: -->
<xsl:value-of select="$mm"/>
<xsl:value-of select="':'"/> <!--18.03.1976 13:24 -->
<xsl:value-of select="$ss"/> <!--18.03.1976 13:24:55 -->
<!-- END: EUROPEAN FORMAT -->

</xsl:template>

Другой формат (ЗАМЕНИТЕ раздел ЕВРОПЕЙСКИЙ ФОРМАТ):

<!-- Long DATE FORMAT -->
<xsl:choose>
<xsl:when test="$month = '1' or $month= '01'">January</xsl:when>
<xsl:when test="$month = '2' or $month= '02'">February</xsl:when>
<xsl:when test="$month= '3' or $month= '03'">March</xsl:when>
<xsl:when test="$month= '4' or $month= '04'">April</xsl:when>
<xsl:when test="$month= '5' or $month= '05'">May</xsl:when>
<xsl:when test="$month= '6' or $month= '06'">June</xsl:when>
<xsl:when test="$month= '7' or $month= '07'">July</xsl:when>
<xsl:when test="$month= '8' or $month= '08'">August</xsl:when>
<xsl:when test="$month= '9' or $month= '09'">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="' '"/> <!--January -->
<xsl:value-of select="$day"/> <!--January 12 -->
<xsl:value-of select="','"/> <!--January 12,-->
<xsl:value-of select="' '"/> <!--January 12, -->
<xsl:value-of select="$year"/> <!--January 12, 2001-->
<!-- END: Long DATE FORMAT -->

Вы можете рекомбинировать элементы любым способом по вашему выбору.

[1] http://geekswithblogs.net/workdog/archive/2007/02/08/105858.aspx @@ http://archive.is/4Hjep

5 голосов
/ 09 марта 2012

Извиняюсь за комментирование этого старого потока, но для других, находящих это как я, Вы могли бы также использовать javascript, если вы используете преобразователь MS:

Объявить пространство имен "msxsl":

xmlns:msxsl="urn:schemas-microsoft-com:xslt" 

Объявите пространство имен для вашего скрипта:

xmlns:js="urn:custom-javascript" 

(Необязательно) Опустить префиксы с выхода:

exclude-result-prefixes="msxsl js" 

Таким образом, вы получите объявление xsl, подобное этому:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
  xmlns:msxsl="urn:schemas-microsoft-com:xslt"
  xmlns:js="urn:custom-javascript"
  exclude-result-prefixes="msxsl js">

Запишите JavaScript в элементе msxsl: script:

<msxsl:script language="JavaScript" implements-prefix="js"> 
<![CDATA[ 
function javascriptFunction(dateValue){
  var date = new Date(dateValue);
  if(!isNaN(date)) return date.toLocaleString();
  return dateValue;
}
]]>
</msxsl:script>

Вызовите функцию JavaScript (используя синтаксис XPath '.', Обозначающий 'этот узел'):

<xsl:value-of select="js:javascriptFunction(string(.))"/>

NB. На момент написания статьи не существует (xsl) способа включения внешних js-файлов (например, библиотеки jquery). Это можно сделать, проанализировав сторону файлового сервера xsl перед преобразованием и добавив содержимое файла js в виде строки в раздел CDATA. Я сам начал идти по этому пути, но пришел к выводу, что если вам нужен такой уровень функциональности, его лучше разместить в другой части конвейера.

источник: http://dev.ektron.com/kb_article.aspx?id=482
ref: http://www.ibm.com/developerworks/xml/library/x-tipxsltjs/index.html

3 голосов
/ 06 апреля 2011

Спасибо, этот пост очень помог.

Я преобразовывал ленту RSS, которая использует следующий формат даты: Пн, 04 апреля 2011 23:18:00 -0700 . Вот названный шаблон, который я использовал для его анализа.

<!--Parse date format: Mon, 04 Apr 2011 23:18:00 -0700-->
<xsl:template name="formatDate">

    <xsl:param name="dateIn" />

    <xsl:variable name="day" select="substring($dateIn, 0, 3)" />
    <xsl:variable name="date" select="substring($dateIn, 6, 2)" />
    <xsl:variable name="month" select="substring($dateIn, 9, 3)" />
    <xsl:variable name="year" select="substring($dateIn, 13, 4)" />

    <xsl:variable name="hour" select="substring($dateIn, 18, 2)" />
    <xsl:variable name="min" select="substring($dateIn, 21, 2)" />
    <xsl:variable name="sec" select="substring($dateIn, 24, 2)" />

    <xsl:value-of select="concat($date, ' ', $month, ' ', $year, ' ', $hour, ':', $min, ':', $sec)" />

</xsl:template>
3 голосов
/ 24 ноября 2010

поправка к сообщению Роя: день от функции всегда будет иметь значение месяца. Используйте следующее:

<xsl:variable name="year" select="substring($dateTime,1,4)" />
<xsl:variable name="month-temp" select="substring-after($dateTime,'-')" />
<xsl:variable name="month" select="substring-before($month-temp,'-')" />
<xsl:variable name="day-temp" select="substring-after($month-temp,'-')" />
<xsl:variable name="day" select="substring($day-temp,1,2)" />
<xsl:variable name="time" select="substring-after($dateTime,'T')" />
<xsl:variable name="hh" select="substring($time,1,2)" />
<xsl:variable name="mm" select="substring($time,4,2)" />
<xsl:variable name="ss" select="substring($time,7,2)" />

<xsl:value-of select="concat($month,'/',$day,'/',$year,' ',$hh,':',$mm,':',$ss)" />

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...