2012-02-28 30 views
5

Una pregunta inicial bastante staright, o eso creía ...Xpath ¿cómo obtengo la longitud total de la cadena de todos los atributos en los hijos de los padres?

select="../Store" devuelve un conjunto de nodos que contiene todos los nodos que necesito. Entonces necesito calcular la longitud de la cadena del atributo de nombre adjunto al nodo Store.

Hubiera pensado que sería esto: select="string-length(../Store/@name)" pero esto solo devuelve la longitud de la cadena del primer nodo.

¿Alguna idea?

+0

XML de muestra por favor ... –

+1

No tenemos idea de qué elemento 'Store' contiene y cuántos atributos contiene ... !! –

+0

Solo estoy interesado en la longitud de cadena del atributo @name. –

Respuesta

8
<xsl:variable name="StoreNames"> 
    <xsl:for-each select="../Store"> 
    <xsl:value-of select="@name"/> 
    </xsl:for-each> 
</xsl:variable> 

<xsl:value-of select="string-length($StoreNames)" /> 

¡Agradable y fácil!

3
sum(../Store/@name/string-length()) 
+0

Esto no parece funcionar? "Token esperado ')' encontrado ..." –

+0

Debería. ¿Cómo lo utilizas? – flyx

+0

@flyx, supongo que OP está teniendo XSLT 1.0 :) –

3

que asumen el código XML de entrada:

<?xml version="1.0" encoding="utf-8"?> 
<root> 
    <Store name="data1"/> 
    <Store name="data2"/> 
    <Store name="data3"/> 
    <Store name="data4"/> 
    <Store name="data55"/> 
</root> 

Este es el código XSLT:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" 
> 
    <xsl:output method="text" indent="yes"/> 
    <xsl:template match="/"> 
    <xsl:apply-templates select="node()"/> 
    </xsl:template> 

    <xsl:template match="Store[1]"> 
     <xsl:call-template name="calclength"/> 
    </xsl:template> 
    <xsl:template name="calclength"> 
    <xsl:param name="lengthsum" select="'0'"/> 
    <xsl:variable name="newlengthsum" select="string-length(@name/.) + $lengthsum"/> 
    <xsl:for-each select="following-sibling::Store[1]"> 
     <xsl:call-template name="calclength"> 
     <xsl:with-param name="lengthsum" select="$newlengthsum"/> 
     </xsl:call-template> 
    </xsl:for-each> 
    <xsl:if test="not(following-sibling::Store[1])"> 
     LengthOfNameAttrs: 
     <xsl:value-of select="$newlengthsum"/> 

     Averagelength: 
     <xsl:variable name="count" select="count(../Store)"/> 
     <xsl:value-of select="$newlengthsum div $count"/> 
    </xsl:if> 
    </xsl:template> 
</xsl:stylesheet> 

de salida es:

LengthOfNameAttrs: 
    26 

    Averagelength: 
    5.2 

es necesario llamar a la plantilla calclength solamente para el primer Store nodo ... es decir, Store[1] calculará y devolverá la suma de todos sibling-nodes .. solo use estos archivos XML y XSLT y ejecútelos. Avíseme si necesita ayuda en la parte calling the template. Se puede editar de acuerdo.

8

En XPath 2.0 usar una sola expresión como este:

sum(../Store/@name/string-length(.)) 

Esto no se puede hacer con una sola XPath 1.0 expresión (una función como un paso de localización no está permitido), por lo tanto alguna se necesita ayuda con el lenguaje de alojamiento.

Por ejemplo, si el idioma de alojamiento es XSLT:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text"/> 

<xsl:template match="/*"> 
    <xsl:apply-templates select="Store[@name][1]"/> 
</xsl:template> 

<xsl:template match="Store[@name]"> 
    <xsl:param name="vAccum" select="0"/> 

    <xsl:value-of select="$vAccum + string-length(@name)"/> 
</xsl:template> 

<xsl:template match="Store[@name and following-sibling::Store/@name]"> 
    <xsl:param name="vAccum" select="0"/> 

    <xsl:apply-templates select="following-sibling::Store[@name][1]"> 
    <xsl:with-param name="vAccum" select="$vAccum + string-length(@name)"/> 
    </xsl:apply-templates> 
</xsl:template> 
</xsl:stylesheet> 

cuando se aplica esta transformación en el siguiente documento XML:

<root> 
    <Store name="ab"/> 
    <Store name="cde"/> 
    <Store name="fgh"/> 
    <Store name="ijklmn"/> 
    <Store name="opr"/> 
</root> 

el resultado deseado, correcta es producido:

+0

increíble !! .. (Solución xslt 1.0) –

+0

El código de flyx no funcionó para OP, así que supongo que está trabajando con el procesador XSLT 1.0 .. –

+0

@ infantprogrammer'Aravind ': Si esto te parece increíble, debes echarle un vistazo a FXSL: http://fxsl.sf.net :) –

Cuestiones relacionadas