2009-02-01 22 views
35

Quando uso il serializzatore XML per serializzare un DateTime, è scritto nel seguente formato:formato una data in XML tramite XSLT

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

Quando si passa questo attraverso un foglio di stile XSLT per output HTML, come posso formattare questo? Nella maggior parte dei casi ho solo bisogno della data, e quando ho bisogno del tempo ovviamente non voglio che la "T divertente" sia lì.

+2

E 'molto importante indicare la versione e XSLT piattaforma – AnthonyWJones

+3

E' più probabile XSLT 1.0 e .NET perché la domanda è codificata con C# –

+0

@divo: ben individuato – AnthonyWJones

risposta

65

Qui ci sono un paio di 1.0 modelli che è possibile utilizzare: -

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

Li chiamano con: -

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

e

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

dove XPath è il percorso un elemento o attributo che ha il formato di data e ora standard.

+13

XSLT fa schifo. La tua soluzione è elegante, ma sicuramente non dovremmo preparare manualmente le routine di formattazione delle date. – Ryan

+0

@Ryan: Sono d'accordo e XSLT 2 ha un supporto molto migliore per la gestione della data. Sfortunatamente c'è ancora un supporto molto sottile nella base installata dei browser HTML. – AnthonyWJones

+2

@AnthonyWJones: si tratta di un understatement serio, XSLT 2.0 è molto sottile al di fuori dei linguaggi dinamici. La maggior parte dei quali sono Java e alcuni .NET. Non abbiamo libXSLT per XSLT 2.0, che altrimenti porterebbe XSLT a una manciata di browser. Una volta che esiste una libreria FOSS ed efficiente C/C++ XSLT 2.0, con dipendenze cross-platform ragionevolmente minime, vedremo il supporto del browser. – TechZilla

25

La formattazione della data non è semplice in XSLT 1.0. Probabilmente il modo più elegante è scrivere una breve funzione di estensione XSLT in C# per la formattazione della data. Ecco un esempio:

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

Con questo documento di input

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

otterrete

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

la funzione di formattazione della data assume un valore di data come stringa e di un formato come descritto in DateTime.ToString Method . L'utilizzo della struttura DateTime di .NET consente di analizzare gratuitamente valori datetime XSD arbitrari (compresi gli specificatori del fuso orario), il calcolo del fuso orario e l'output localizzato.

Tuttavia, tenere presente che esiste uno caveat (http://support.microsoft.com/kb/316775) con estensioni di script msxml: ogni volta che si carica l'XSLT, un assembly contenente il codice dello script viene generato dinamicamente e caricato in memoria. A causa della progettazione del runtime .NET, questo assembly non può essere scaricato. Ecco perché devi assicurarti che il tuo XSLT sia caricato una sola volta (e poi memorizzato nella cache per un ulteriore riutilizzo). Questo è particolarmente importante quando si esegue all'interno di IIS.

+1

Sì, è quasi identico al metodo che uso! – Cerebrus

+1

Solo curioso del downvote: c'è una ragione tecnica? O solo antipatia personale dell'approccio? –

+0

Ho downvoted perché msxsl: lo script non è necessario (vedi il post di AnthonyW che è la soluzione più elegante) e ha dei lati negativi: http://www.tkachenko.com/blog/archives/000620.html. Gli oggetti di estensione XSLT sono molto più preferibili per creare funzioni XSLT personalizzate in .NET. Provalo :) –

9

John Workman discute questo problema a lungo e fornisce diverse soluzioni in questo discussion[1] sul suo blog. Fondamentalmente, analizza i singoli componenti della data e ricombina nell'ordine che desideri. Per il vostro caso, una pura versione XSLT 1.0+ sarebbe:

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

Un altro formato (sostituisce la sezione FORMATO EUROPEO):

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

È possibile ricombinare gli elementi in qualsiasi modo si sceglie.

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

+1

Vorrei farvi un bel commento qui. Il tuo codice mi ha appena salvato un mal di testa. – espais

3

correzione al post di Roy: il giorno dalla funzione sempre ottenere il valore del mese.Utilizzare la seguente:

<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

Ho corretto l'errore. Grazie. – rivy

3

Grazie, questo post ha aiutato molto.

Stavo trasformando un feed RSS che utilizza il seguente formato data: Lun, 04 Apr 2011 23:18:00 -0700. Ecco il modello chiamato che ho usato per analizzarlo.

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

Scuse per commentare questo vecchio thread, ma per gli altri trovandolo come me si potrebbe anche usare JavaScript se si utilizza un trasformatore MS:

dichiarare il "msxsl" namespace:

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

dichiarare uno spazio dei nomi per lo script:

xmlns:js="urn:custom-javascript" 

(opzionale) Omettere ° e prefissi dalla uscita:

exclude-result-prefixes="msxsl js" 

Così si finisce con una dichiarazione XSL come questo:

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

Scrivi il codice JavaScript nella msxsl: elemento 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> 

Chiamate il vostro Funzione JavaScript (usando la sintassi XPath '.' Che denota 'questo nodo'):

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

NB: Al momento della scrittura non sembra esserci un modo (xsl) per includere file js esterni (ad es. libreria jquery). Questo potrebbe essere fatto analizzando il lato file server xsl prima della trasformazione e aggiungendo il contenuto del file js come una stringa in una sezione CDATA. Ho iniziato a seguire questa rotta da solo, ma ho concluso che se hai bisogno di questo livello di funzionalità potrebbe essere posizionato in una parte diversa della pipeline.

fonte: http://dev.ektron.com/kb_article.aspx?id=482
ref: http://www.ibm.com/developerworks/xml/library/x-tipxsltjs/index.html