2010-04-19 207 views
7

I tiene un grupo de cadenas es decir, g: Líneas = '9,1,306, LUCY, G, 38,12'XSLT Ordenar alfabéticamente y numéricamente Problema

necesito la salida para estar en XSLT 1.0:

1,9,12,38,306, G, LUCY

Este es mi código actual:

<xsl:for-each select="$all_alerts[g:problem!='normal_service'][g:service='bus']"> 
    <xsl:sort select="g:line"/> 
    <xsl:sort select="number(g:line)" data-type="number"/> 
    <xsl:value-of select="normalize-space(g:line)" /><xsl:text/> 
    <xsl:if test="position()!=last()"><xsl:text>,&#160;</xsl:text></xsl:if> 
</xsl:for-each> 

puedo conseguir que únicamente la imagen del '1, 12, 306, 38, 9, G, LUCY 'porque el segundo tipo no se está recogiendo.

¿Alguien me puede ayudar?

+0

Tiene elementos no numéricos en su lista, ¿cómo se supone que están ordenados numéricamente? – Oded

+0

Sé que los artículos son números y letras, solo necesito números ordenados numéricamente seguidos de las letras ordenadas alfabéticamente. ¿Qué tengo que hacer para que esto suceda – Bryan

Respuesta

11

Para lograr esto usando sólo un XSL: instrucción foreach, intente lo siguiente:

<xsl:for-each select="$all_alerts[g:problem!='normal_service'][g:service='bus']"> 
    <xsl:sort select="not(number(g:line))"/> 
    <xsl:sort select="number(g:line)" data-type="number"/> 
    <xsl:sort select="g:line"/> 
    <xsl:value-of select="normalize-space(g:line)" /><xsl:text/> 
    <xsl:if test="position()!=last()"><xsl:text>,&#160;</xsl:text></xsl:if> 
</xsl:for-each> 

La primera xsl: sort tipo de si la línea es un número o no. El no() devuelve falso si la línea es un número y verdadero si no lo es. falso se ordena antes que verdadero, y los números salen primero. Si omite este tipo, las letras aparecerán primero.

La siguiente xsl: tipo ordena numéricamente, por lo que ordenará los números correctamente, pero no afectará a las letras (que devuelven NaN cuando se aplica number()).

La final xsl: sort ordenará las letras alfabéticamente.

0
<xsl:template match="/"> 
    <xsl:for-each select="(9,1,306,'LUCY','G',89)" > 
    <xsl:sort select="if (number()) then() else ."/> 
    <xsl:sort select="number(.)" data-type="number" /> 
    <xsl:value-of select="."/> 
    <xsl:value-of select="', '" /> 
    </xsl:for-each> 
</xsl:template> 

me da

1, 9, 89, 306, G, LUCY,

supongo que es lo que necesita, ¿verdad?

+0

he recibido un error, probablemente debido a que el código es de 2.0 y 1.0 utilizando im javax.xml.transform.TransformerConfigurationException: javax.xml.transform.TransformerException: javax.xml .transformar.TransformerException: No se pudo encontrar la función: si – Bryan

+0

me atrevo a decir que nunca deberías acostumbrarte a XSLT 1.0. Está muy por detrás 2.0. Perdón por no poder ayudarlo, pero tiene un deseo bastante avanzado y si quiere apegarse a XSLT 1.0, puede que no tenga suerte. Has visto el truco en la respuesta: solo usa el valor del texto si el elemento no es un número. Si es así, devuelve "nada". Entonces, si usted (u otra persona) puede mapear esto a XSLT 1.0, debe hacerlo. Voy a renunciar a esta pregunta ya que no quiero volver a entrar en el modo XSLT 1.0. Lo siento de nuevo. – topskip

+0

No, lo entiendo, mi compañía está usando un CMS de código abierto llamado Alfresco y no me permitirá usar XSLT 2.0. Gracias por tu ayuda. – Bryan

0

En XSLT 1.0 Creo que se necesita algo como esto:

<xsl:for-each select="$all_alerts[g:problem!='normal_service'][g:service='bus']"> 
    <xsl:sort select="g:line[number(g:line) != number(g:line)]"/> 
    <xsl:sort select="g:line[number(g:line) = number(g:line)]" data-type="number"/> 
    <xsl:value-of select="normalize-space(g:line)" /><xsl:text/> 
    <xsl:if test="position()!=last()"><xsl:text>,&#160;</xsl:text></xsl:if> 
</xsl:for-each> 

número ($ foo) = número ($ foo) es XSLT 1.0 modismo para la prueba si un valor no es un número.

Otra solución (más clara, supongo) sería seleccionar/ordenar los primeros números, y luego otros.

+0

El código anterior me dio esta salida: 1, 12, 306, 38, 9, G, LUCY – Bryan

0

Creo que esto logra lo que desea.

Divido primero la evaluación/tipo de números y luego los valores del nodo de texto.

<xsl:for-each select="$all_alerts[g:problem!='normal_service'][g:service='bus'][number(g:line)=number(g:line)]"> 
     <xsl:sort select="g:line" data-type="number" order="ascending"/> 
     <xsl:value-of select="normalize-space(g:line)" /> 
     <xsl:text/> 
     <xsl:if test="position()!=last() or $all_alerts[g:problem!='normal_service'][g:service='bus'][number(g:line)!=number(g:line)]"> 
      <xsl:text>,&#160;</xsl:text> 
     </xsl:if> 
    </xsl:for-each> 

    <xsl:for-each select="$all_alerts[g:problem!='normal_service'][g:service='bus'][number(g:line)!=number(g:line)]"> 
     <xsl:sort select="g:line[number(g:line) != number(g:line)]"/> 
     <xsl:value-of select="normalize-space(g:line)" /> 
     <xsl:text/> 
     <xsl:if test="position()!=last()"> 
      <xsl:text>,&#160;</xsl:text> 
     </xsl:if> 
    </xsl:for-each> 
Cuestiones relacionadas