2009-01-28 20 views
5

Estoy tratando de transformar un formato de fecha aaaa-MM-dd, porque estoy usando la herramienta xsd.exe los tipos de datos xs: date se cambian automáticamente a un tipo de datos datetime, porque no hay ningún tipo en .NET Framework que coincida con el tipo xs: date completamente.Transformación XSLT formato datetime to date

Pero no puedo conseguir que funcione

<articles> 
     <article> 
      <articleid>48992</articleid> 
      <deliverydateasked>2009-01-29T00:00:00+01:00</deliverydateasked> 
     </article> 
     <article> 
      <articleid>48993</articleid> 
      <deliverydateasked>2009-01-30T00:00:00+01:00</deliverydateasked> 
     </article> 
</articles> 

tratar de convertir el xml a

<articles> 
     <article> 
      <articleid>48992</articleid> 
      <deliverydateasked>2009-01-29</deliverydateasked> 
     </article> 
     <article> 
      <articleid>48993</articleid> 
      <deliverydateasked>2009-01-30</deliverydateasked> 
     </article> 
</articles> 

Actualmente estoy usando este XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
<xsl:template match="/"> 
    <articles> 
     <xsl:apply-templates select="article"> 
     </xsl:apply-templates> 
      </articles> 
</xsl:template> 

<xsl:template name="FormatDate"> 

    <xsl:param name="DateTime" /> 
    <xsl:variable name="date"> 
     <xsl:value-of select="substring-before($DateTime,'T')" /> 
    </xsl:variable> 

    <xsl:if test="string-length($date) != 10"> 
     <xsl:value-of select="$DateTime"/> 
    </xsl:if> 
    <xsl:if test="string-length($date) = 10"> 
     <xsl:value-of select="$date"/> 
    </xsl:if> 
</xsl:template> 

<xsl:template match="article"> 
     <xsl:call-template name="FormatDate"> 
      <xsl:with-param name="DateTime" select="deliverydateasked"/> 
     </xsl:call-template>  
</xsl:template>  

¿Alguien sabe un buen xsl t transformación.

Gracias de antemano

El resultado de la salida de mi código es

<articles /> 

Respuesta

1

Gracias a Stesoc y annakata lo he descubierto Este es el código que estoy usando ahora y funciona perfecto

<xsl:template match="*"> 
    <xsl:param name="parentElm"> 
     <xsl:value-of select="name(..)" /> 
    </xsl:param> 
    <xsl:choose> 
     <xsl:when test="local-name() = 'deliverydateasked'"> 
      <xsl:element name="deliverydateasked"> 
       <xsl:call-template name="FormatDate"> 
        <xsl:with-param name="DateTime" select="."/> 
       </xsl:call-template> 
      </xsl:element> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:element name="{local-name()}"> 
       <xsl:copy-of select="@*" /> 
       <xsl:apply-templates select="@* | node()" /> 
      </xsl:element> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

<xsl:template name="FormatDate"> 
    <xsl:param name="DateTime" /> 
    <xsl:variable name="date"> 
     <xsl:value-of select="substring-before($DateTime,'T')" /> 
    </xsl:variable> 

    <xsl:if test="string-length($date) != 10"> 
     <xsl:value-of select="$DateTime"/> 
    </xsl:if> 
    <xsl:if test="string-length($date) = 10"> 
     <xsl:value-of select="$date"/> 
    </xsl:if> 
</xsl:template>  

+0

¿Por qué haces las complicadas "local-name()" cosas? – Tomalak

+0

lo Tomalak dijo - apalancamiento XSL: copiar – annakata

+0

Annakata He intentado su primera sugerencia con el resultado: 2009-01 -292009-01-30 ¿O hice algo mal? pero es local-name() que una función para evitar? el tiempo de duración ahora es de 15-30 ms – freggel

7

Francamente, esto se ve bastante bien para mí - a veces una subcadena simple es lo suficientemente bueno.

Sin embargo, si estás en la tierra .NET y que está realmente necesidad extra de funcionalidad .NET tiene XSLT Extension Objects


edición: oico, usted tiene una básicas apply-templates problema conceptual. Prueba esto (nota de la copia y el partido plantilla de raíz):

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 

<xsl:template match="*"> 
    <xsl:copy><xsl:apply-templates /></xsl:copy> 
</xsl:template> 

<xsl:template match="deliverydateasked"> 
    <xsl:copy> 
     <xsl:call-template name="FormatDate"> 
      <xsl:with-param name="DateTime" select="."/> 
     </xsl:call-template>  
    </xsl:copy> 
</xsl:template> 

<xsl:template name="FormatDate"> 

     <xsl:param name="DateTime" /> 
     <xsl:variable name="date"> 
       <xsl:value-of select="substring-before($DateTime,'T')" /> 
     </xsl:variable> 

     <xsl:if test="string-length($date) != 10"> 
       <xsl:value-of select="$DateTime"/> 
     </xsl:if> 
     <xsl:if test="string-length($date) = 10"> 
       <xsl:value-of select="$date"/> 
     </xsl:if> 
</xsl:template> 

</xsl:stylesheet> 

plantillas es un concepto difícil de aprender, que puede ser mejor empezando por el más sencillo for-each, y/o que parece que podría hacer con algunos Tutoriales/libros de XSLT.

+1

En "usar el más sencillo para cada uno": http://gregbeech.com/blogs/tech/archive/2006/08/17/using-xsl-for-each-is-almost-always-wrong.aspx .Voto por hacerlo bien desde el principio. :) – Tomalak

+0

De la experiencia personal de enseñar XSLT a novatos, estoy totalmente en desacuerdo con eso, porque cada uno es un concepto traducible y fácil de comprender, y si algo es un trampolín útil para explicar el concepto de plantilla "ahora lo tienes, mira qué esto puede hacer! " – annakata

+1

El enlace que Tomalak dio al artículo de Greg Beech ha cambiado; ahora es http://gregbeech.com/blog/using-xsl-for-each-is-almost-always-wrong – Val

6

Formateo obtendrá mucho más fácil en XPath 2.0, que Microsoft se ha negado a admitir durante los últimos 8 años. Dado que el problema de formato es realmente sólo la persistencia de XSLT en .Net me gusta utilizar una función personalizada, lo que es más limpio & fácil:

XSLT con el formato Función:

xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
    xmlns:user="http://www.tempuri.org/User"> 

    <msxsl:script implements-prefix="user" language="C#"> 
     <![CDATA[ 
      public string FormatCurrency(string amount) 
      { 
      return decimal.Parse(amount).ToString("C0"); 
      } 

      public string FormatDate(string dateValue) 
      { 
      return DateTime.Parse(dateValue).ToString("MM/dd/yyyy hh:mm"); 
      } 
      ]]> 
     </msxsl:script> 

Uso:

<xsl:value-of select="user:FormatDate(@transactionDate)"/> 
<xsl:value-of select="user:FormatCurrency(@amount)"/> 

Cuando ejecute su XSLT en .Net, asegúrese de decirle que es confiable (para que se ejecute el bloque de script msxsl:

XslCompiledTransform.Load(reader, XsltSettings.TrustedXslt, null);