Подтвердить что ты не робот

Форматировать дату в XML через XSLT

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

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

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

4b9b3361

Ответ 1

Вот несколько шаблонов 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 - это путь к элементу или атрибуту, который имеет стандартный формат даты.

Ответ 2

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

<?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 Method. Использование структуры .NET DateTime позволяет анализировать произвольные значения даты и времени XSD (включая спецификаторы часовых поясов), вычисление часового пояса и локализованный вывод бесплатно.

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

Ответ 3

Джон Работник подробно обсуждает этот вопрос и предлагает несколько решений в этом обсуждение [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

Ответ 4

Извинения за комментарий к этому старому потоку, но для других, нашедших это как я, вы также можете использовать javascript, если используете MS-трансформер:

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

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

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

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). 'обозначая' этот node '):

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

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

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

Ответ 5

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

  

<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)" />

Ответ 6

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

Я преобразовал 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>