2011-01-06 12 views
5

Diciamo che ho un elenco di nodi che contengono un attributo datetime e voglio selezionare solo i record che si verificano dopo $ compare-datetime.XSLT1.0/XPath 1.0 Selezione dei nodi per intervallo di date. È possibile?

<records> 
    <record @datetime="2010-01-04T16:48:15.501-05:00"/> 
    <record @datetime="2010-01-03T16:48:15.501-05:00"/> 
    ...etc... 
</records> 

in XQuery per selezionare le voci all'interno di un intervallo di date che avrei fatto

/records/record[xs:dateTime(@datetime) > xs:dateTime($compare-datetime)] 

sacco Tuttavia in XSLT 1.0 Ho cercato di diversi approcci e un sacco di ricerca di risposte, senza alcuna fortuna ad ottenere questo lavorare.

Sto iniziando a pensare che, a parte l'analisi della data effettiva. Tempo su un valore intero, questo non è un compito semplice in xslt.

Spero che qualcuno possa darmi una risposta definitiva su questo, così posso almeno sapere a cosa mi trovo di fronte.

Cheers,

Casey

risposta

6

Se le date saranno sempre nello stesso fuso orario e avranno campi a larghezza fissa (numero costante di cifre in ogni campo), credo che si possa prendere this approach: rimuovere la punteggiatura, lasciare i numeri e confrontare i numeri .

<xsl:variable name="datetime-punctuation" select="'-.:T'" /> 
<xsl:variable name="stripped-compare-datetime" 
    select="number(translate($compare-datetime, $datetime-punctuation, ''))" /> 

Quindi utilizzare

/records/record[number(translate(@datetime, $datetime-punctuation, '')) 
       > $stripped-compare-datetime)] 
+0

+1. Anche pensato a questo. Potrebbe essere più efficiente a proposito. – Flack

+0

@Flack, sì, intendevo dire che questo è un metodo più veloce e sporco, che funzionerà in base ai vincoli di cui sopra e non richiede il parsing completo dei dati datetime. Non ci darà cose belle come la differenza tra due periodi di tempo, ma sembra che l'OP non ne abbia bisogno. – LarsH

+0

+1 per entrambi, ragazzi. –

1

temo che XSLT 1.0 non ha il supporto integrato per datetimes. È possibile che qualcuno possa aver scritto una biblioteca - dare un'occhiata alle domande frequenti XSLT

Vedere http://www.dpawson.co.uk/xsl/rev2/dates.html#d14938e16 per ciò che XSLT 2.0 può offrire.

5

Può essere non è la soluzione migliore, ma ho questa:

input XML:

<?xml version="1.0" encoding="UTF-8"?> 
<?xml-stylesheet type="text/xsl" href="dates.xsl"?> 
<records> 
    <record datetime="2010-01-04T16:48:15.501-05:00"/> 
    <record datetime="2011-01-04T16:48:15.501-05:00"/> 
</records> 

XSLT:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:date="http://exslt.org/dates-and-times" 
    extension-element-prefixes="date"> 
    <xsl:import href="date.difference.template.xsl"/> 
    <!-- http://exslt.org/date/functions/difference/date.difference.template.xsl --> 
    <xsl:output method="xml" indent="yes"/>   

    <xsl:template match="/*"> 
     <xsl:copy> 
      <result1> 
       <xsl:call-template name="date:difference"> 
        <xsl:with-param name="start" select="record[1]/@datetime"/> 
        <xsl:with-param name="end" select="'2010-04-04T16:48:15.501-05:00'"/> 
       </xsl:call-template> 
      </result1> 
      <result2> 
       <xsl:call-template name="date:difference"> 
        <xsl:with-param name="start" select="record[2]/@datetime"/> 
        <xsl:with-param name="end" select="'2010-04-04T16:48:15.501-05:00'"/> 
       </xsl:call-template> 
      </result2> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

Risultato:

<records> 
    <result1>P90D</result1> 
    <result2>-P275D</result2> 
</records> 

Negative differenza significherebbe questo la prima data si verifica dopo la seconda data.

+0

buona soluzione. +1 – LarsH

+0

+1 per entrambi, ragazzi. –

+0

+1 buona risorsa. Questa conversione della zona di copertura ma l'uso del modello con nome (per standard rigorosi) renderebbe ** la selezione dei nodi ** un lavoro difficile. –

0

Ho avuto lo stesso problema come voi. Ho costruito un metodo C# (per cui questo funziona solo con .Net XSLT):

<msxsl:script language="C#" implements-prefix="user"> 
    <![CDATA[ 
    public bool largerThan(DateTime dt0, DateTime dt1) { 
    return dt0 > dt1; 
    } 
    ]]> 
</msxsl:script> 

con i namespace

xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
xmlns:user="urn:my-scripts" 

e di utilizzo (Snippet dal mio XSLT doc)

<xsl:for-each select="../b:post[user:largerThan(@created,$created)]"> 
+0

Sì, le funzioni di estensione possono sempre "risolvere" ciò che la lingua (XPath 1.0) non copriva. ** Tuttavia, le definizioni delle lingue in linea non fanno parte del meccanismo di estensione standard **. La registrazione di un'implementazione nel contesto del processore XSLT è l'approccio standard. –

+0

Per chiunque utilizzi [tag: .net]/[tag: C#], non passare troppo tempo a cercare di importare le importazioni EXSLT con i trasformatori .NET XSLT standard. Utilizza [MVP.XML] (http: // mvpxml .codeplex.com /) subito. Ha [supporto integrato per ESXLT] (http://mvpxml.codeplex.com/wikipage?title=EXSLT.NET). –

Problemi correlati