2011-01-06 17 views
5

Digamos que tengo una lista de nodos que contienen un atributo datetime, y quiero seleccionar solo los registros que ocurren después de $ compare-datetime.XSLT1.0/XPath 1.0 Selección de nodos por rango de fechas. ¿Esto es posible?

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

En xquery para seleccionar elementos dentro de un intervalo de fechas que haría

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

mucho Sin embargo, en XSLT 1.0 He tratado de diferentes enfoques y un montón de búsqueda de respuestas, sin ninguna suerte en conseguir este trabajar.

Estoy empezando a pensar que si no se analiza el dateTime real en un valor entero, esta no es una tarea sencilla en xslt.

Espero que alguien me pueda dar una respuesta definitiva sobre eso para que al menos sepa a qué me opongo.

Saludos,

Casey

Respuesta

6

Si las fechas siempre estarán en la misma zona horaria y tienen campos de ancho fijo (número constante de dígitos en cada campo), creo que podría tomar this approach: eliminar la puntuación, dejar los números y comparar los números .

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

A continuación, utilice

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

+1. También pensé en eso. Puede ser más eficiente por cierto. – Flack

+0

@Flack, sí, quise decir que este es un método más rápido y sucio, que funcionará dadas las limitaciones anteriores, y no requiere un análisis completo de los datos de fecha y hora. No nos dará cosas buenas como la diferencia entre dos fechas, pero parece que el OP no necesita eso. – LarsH

+0

+1 para los dos, muchachos. –

1

Me temo que XSLT 1.0 no tiene soporte incorporado para datetimes. Es posible que descubra que alguien ha escrito una biblioteca: eche un vistazo a las preguntas más frecuentes de XSLT

Consulte el http://www.dpawson.co.uk/xsl/rev2/dates.html#d14938e16 para conocer lo que XSLT 2.0 puede ofrecer.

5

Puede ser que no es la mejor solución, pero tengo esto:

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

Resultado:

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

Negativo la diferencia significaría que la primera fecha ocurre después de la segunda fecha.

+0

buena solución. +1 – LarsH

+0

+1 para los dos, muchachos. –

+0

+1 Buen recurso. Esta conversión de zona de cobertura, pero el uso de una plantilla con nombre (para estándar estricto) haría que ** seleccionar nodos ** fuera un trabajo difícil. –

0

tuve el mismo problema que tú. Construí un método C# (por lo que este sólo funciona con .Net XSLT):

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

con espacios de nombres

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

y uso (fragmento de mi documento XSLT)

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

Sí, las funciones de extensiones siempre pueden "resolver" lo que el lenguaje (XPath 1.0) no cubrió. ** Pero las definiciones de lenguaje extranjero en línea no son parte del mecanismo de extensión estándar **. El registro de una implementación en el contexto del procesador XSLT es el enfoque estándar. –

+0

Para cualquiera que use [tag: .net]/[tag: C#], no pierda demasiado tiempo intentando que las importaciones EXSLT funcionen con los transformadores .NET XSLT estándar: use [MVP.XML] (http: // mvpxml .codeplex.com /) de inmediato. Tiene [soporte integrado para ESXLT] (http://mvpxml.codeplex.com/wikipage?title=EXSLT.NET). –

Cuestiones relacionadas