2009-02-01 16 views
35

Kiedy używam serializatora XML serializować DateTime, jest napisane w następującym formacie:Format data w formacie XML za pomocą XSLT

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

Po przejściu tego za pośrednictwem arkusza stylów XSLT do wyjścia HTML, jak mogę sformatować to? W większości przypadków potrzebuję tylko daty, a kiedy potrzebuję czasu, nie chcę oczywiście "zabawnego T".

+2

Jest bardzo ważne, aby podać swoją wersję i XSLT platformę – AnthonyWJones

+3

To najprawdopodobniej XSLT 1.0 i .NET bo pytanie jest oznaczona C# –

+0

@divo: dobrze zauważony – AnthonyWJones

Odpowiedz

65

Oto kilka 1,0 szablonów, które można użyć: -

<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> 

Zadzwoń im: -

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

i

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

gdzie XPath jest ścieżka do element lub atrybut, który ma standardowy format daty.

+13

XSLT jest do bani. Twoje rozwiązanie jest eleganckie, ale z pewnością nie powinniśmy ręcznie opracowywać procedur formatowania daty. – Ryan

+0

@Ryan: Zgadzam się, a XSLT 2 ma znacznie lepsze wsparcie dla obsługi dat. Niestety, nawet w tej chwili jest ona bardzo cienka w zainstalowanej bazie HTML Browsers. – AnthonyWJones

+2

@AnthonyWJones: To poważne niedopowiedzenie, XSLT 2.0 jest bardzo cienki poza dynamicznymi językami. Większość z nich to Java, a niektóre .NET. Nie mamy biblioteki libXSLT dla XSLT 2.0, która w przeciwnym razie przyniosłaby XSLT do garstki przeglądarek. Po utworzeniu biblioteki FOSS i wydajnej biblioteki C/C++ XSLT 2.0, przy rozsądnie minimalnych zależnościach między platformami, zobaczymy obsługę przeglądarki. – TechZilla

25

Formatowanie dat nie jest łatwe w XSLT 1.0. Prawdopodobnie najbardziej eleganckim sposobem jest napisanie krótkiej funkcji rozszerzenia XSLT w języku C# do formatowania daty. Oto przykład:

<?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> 

Z tego dokumentu wejściowego

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

dostaniesz

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

funkcji formatowania datę przyjmuje wartość datę jako ciąg i format, jak to opisano w DateTime.ToString Method . Przy użyciu struktury DateTime systemu .NET można analizować dowolne wartości datetime XSD (w tym specyfikatory strefy czasowej), obliczanie strefy czasowej i zlokalizowane dane wyjściowe za darmo.

Należy jednak pamiętać, że istnieje jeden kod caveat (http://support.microsoft.com/kb/316775) z rozszerzeniami skryptów msxml: Za każdym razem, gdy ładujesz XSLT, zestaw zawierający kod skryptu jest generowany dynamicznie i ładowany do pamięci. Ze względu na konstrukcję środowiska wykonawczego .NET ten zespół nie może zostać rozładowany. Dlatego musisz upewnić się, że Twój XSLT jest załadowany tylko raz (a następnie buforowany do dalszego ponownego wykorzystania). Jest to szczególnie ważne podczas działania w IIS.

+1

Tak, to prawie identyczne z metodą, której używam! – Cerebrus

+1

Po prostu ciekawa sprawa: czy istnieje jakiś techniczny powód? Czy po prostu niechęć do podejścia? –

+0

I przegłosowałem ponieważ msxsl: skrypt nie jest potrzebny (patrz post AnthonyW, który jest najbardziej eleganckim rozwiązaniem) i ma poważne wady: http://www.tkachenko.com/blog/archives/000620.html. Przedłużenia XSLT są o wiele bardziej preferowane, aby stworzyć niestandardowe funkcje XSLT w .NET wypróbować :) –

9

John Workman szczegółowo omawia tę kwestię i podaje kilka rozwiązań w tym discussion[1] na swoim blogu. Zasadniczo przeanalizuj poszczególne komponenty daty i połącz je w dowolnej kolejności. W Twoim przypadku, to czysta XSLT 1.0+ wersja będzie:

<?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> 

innym formacie (zastępuje Europejski Sekcja format):

<!-- 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 --> 

Można rekombinacji elementy w dowolny sposób.

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

+1

Chciałbym rzucić ci miły komentarz tutaj. Twój kod właśnie uratował mi helluva ból głowy. – espais

3

korekta na stanowisku Roya: dzień z funkcji zawsze będzie uzyskać wartość miesiąca.Użyj następujących:

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

+0

Naprawiłem błąd. Dzięki. – rivy

3

Dzięki, ten post pomogło.

Transformowałem kanał RSS, który korzysta z następującego formatu daty: Pon., 04 kwietnia 2011 23:18:00 -0700. Oto nazwany szablon, którego użyłem do jego analizy.

<!--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> 
4

Przepraszamy za komentowanie tego starego wątku ale dla innych znalezienie go jak ja można też użyć JavaScript, jeśli używasz transformatora MS:

zadeklarować „msxsl” nazw:

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

Zadeklaruj nazw dla skryptu:

xmlns:js="urn:custom-javascript" 

(opcjonalnie) pominąć th e prefiksy z wyjścia:

exclude-result-prefixes="msxsl js" 

więc skończyć z deklaracją xsl jak ten:

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

pisać JavaScript w msxsl: Element scenariusz:

<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> 

zadzwonić do Funkcja JavaScript (przy użyciu składni XPath "." Oznaczającej "ten węzeł"):

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

NB: Od czasu pisania nie istnieje sposób (xsl) na dołączenie zewnętrznych plików js (np. biblioteka jquery). Można to zrobić, parsując stronę serwera plików xsl przed transformacją i dodając zawartość pliku js jako ciąg do sekcji CDATA. Zacząłem samodzielnie tę trasę, ale doszedłem do wniosku, że jeśli potrzebujesz tego poziomu funkcjonalności, lepiej będzie umieścić go w innej części rurociągu.

źródło: http://dev.ektron.com/kb_article.aspx?id=482
ref: http://www.ibm.com/developerworks/xml/library/x-tipxsltjs/index.html