Herramientas/Utilidades, Programación, XSLT

XSL – Llamada recursiva

Si necesitas iterar sobre un XML en el que los nodos son genéricos, pero siguiente un orden, como por ejemplo, este XML de entrada:

<?xml version="1.0" encoding="UTF-8"?>
<lista>
    <PARAM1>Favoritos</PARAM1>
    <PARAM2>Antonio</PARAM2>
    <PARAM3>28/03/2017</PARAM3>
    <PARAM4>2</PARAM4>
    <PARAM5>León</PARAM5>
    <PARAM6>Panthera leo</PARAM6>
    <PARAM7>Félidos</PARAM7>
    <PARAM8>Panthera</PARAM8>
    <PARAM9>El rey de la selva</PARAM9>
    <PARAM10>Lemming</PARAM10>
    <PARAM11>Lemmus lemmus</PARAM11>
    <PARAM12>Roedor</PARAM12>
    <PARAM13>Cricetidae</PARAM13>
    <PARAM14>Dicen que se suicidan</PARAM14>
</lista>

Esto puede venir como respuesta de algún WebService, como por ejemplo haría este código en Java:

public static String getAnimalesFavoritos(String username, List<Mamifero> list) {
	SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
	String date = sdf.format(new Date());
	StringBuilder sb = new StringBuilder();
	sb.append("<lista>\n");
	sb.append("\t<PARAM1>Favoritos</PARAM1>\n");
	sb.append("\t<PARAM2>").append(username).append("</PARAM2>\n");
	sb.append("\t<PARAM3>").append(date).append("</PARAM3>\n");
	sb.append("\t<PARAM4>").append(list.size()).append("</PARAM4>\n");
	int i = 5;
	for (Mamifero elem : list) {
		sb.append("\t<PARAM" + i + ">").append(elem.getNombre()).append("</PARAM" + i + ">\n");
		sb.append("\t<PARAM" + (i + 1) + ">").append(elem.getNombreLatin()).append("</PARAM" + (i + 1) + ">\n");
		sb.append("\t<PARAM" + (i + 2) + ">").append(elem.getFamilia()).append("</PARAM" + (i + 2) + ">\n");
		sb.append("\t<PARAM" + (i + 3) + ">").append(elem.getEspecie()).append("</PARAM" + (i + 3) + ">\n");
		sb.append("\t<PARAM" + (i + 4) + ">").append(elem.getDescripcion()).append("</PARAM" + (i + 4) + ">\n");
		i += 5;
	}
	sb.append("</lista>");
	return sb.toString();
}

Para ello, se puede aplicar una plantilla XSL como la siguiente:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:user="urn:my-scripts" version="1.0" exclude-result-prefixes="msxsl user">
    <xsl:template match="/lista">
        <xsl:variable name="lista" select="PARAM1" />
        <xsl:variable name="username" select="PARAM2" />
        <xsl:variable name="dateTime" select="PARAM3" />
        <xsl:variable name="numero" select="PARAM4" />
        <animales>
            <tipoLista>
                <xsl:value-of select="$lista" />
            </tipoLista>
            <userName>
                <xsl:value-of select="$username" />
            </userName>
            <dateTime>
                <xsl:value-of select="$dateTime" />
            </dateTime>
            <mamíferos>
                <xsl:call-template name="animal">
                    <xsl:with-param name="node" select="." />
                    <xsl:with-param name="count">
                        <xsl:value-of select="1" />
                    </xsl:with-param>
                    <xsl:with-param name="cursor">
                        <xsl:value-of select="5" />
                    </xsl:with-param>
                    <xsl:with-param name="max">
                        <xsl:value-of select="$numero" />
                    </xsl:with-param>
                </xsl:call-template>
            </mamíferos>
        </animales>
    </xsl:template>
    <xsl:template name="animal">
        <xsl:param name="node" />
        <xsl:param name="count" />
        <xsl:param name="cursor" />
        <xsl:param name="max" />
        <mamífero>
            <nombre>
                <xsl:value-of select="$node/*[name() = concat('PARAM', $cursor)]" />
            </nombre>
            <nombreLatin>
                <xsl:value-of select="$node/*[name() = concat('PARAM', $cursor + 1)]" />
            </nombreLatin>
            <familia>
                <xsl:value-of select="$node/*[name() = concat('PARAM', $cursor + 2)]" />
            </familia>
            <especie>
                <xsl:value-of select="$node/*[name() = concat('PARAM', $cursor + 3)]" />
            </especie>
            <descripción>
                <xsl:value-of select="$node/*[name() = concat('PARAM', $cursor + 4)]" />
            </descripción>
        </mamífero>
        <xsl:if test="$count &lt; $max">
            <xsl:call-template name="animal">
                <xsl:with-param name="node" select="$node" />
                <xsl:with-param name="count">
                    <xsl:value-of select="$count+1" />
                </xsl:with-param>
                <xsl:with-param name="cursor">
                    <xsl:value-of select="$cursor+5" />
                </xsl:with-param>
                <xsl:with-param name="max">
                    <xsl:value-of select="$max" />
                </xsl:with-param>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

Donde se utiliza una llamada a una función de manera recursiva.
Es importante que se pase el número de “animales” que se van a enviar, ya que es la única forma que tiene la función de saber cuándo parar.

El XML resultante sería el siguiente:

<?xml version="1.0" encoding="UTF-8"?>
<animales>
    <tipoLista>Favoritos</tipoLista>
    <userName>Antonio</userName>
    <dateTime>28/03/2017</dateTime>
    <mamíferos>
        <mamífero>
            <nombre>León</nombre>
            <nombreLatin>Panthera leo</nombreLatin>
            <familia>Félidos</familia>
            <especie>Panthera</especie>
            <descripción>El rey de la selva</descripción>
        </mamífero>
        <mamífero>
            <nombre>Lemming</nombre>
            <nombreLatin>Lemmus lemmus</nombreLatin>
            <familia>Roedor</familia>
            <especie>Cricetidae</especie>
            <descripción>Dicen que se suicidan</descripción>
        </mamífero>
    </mamíferos>
</animales>
Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s