xslt - attribute - Profundidad de salida del nodo actual en la jerarquía
xpath selenium (3)
Usando XSLT / XPATH 1.0, quiero crear HTML donde el atributo de class
de un elemento span
indica la profundidad en la jerarquía XML original.
Por ejemplo, con este fragmento XML:
<text>
<div type="Book" n="3">
<div type="Chapter" n="6">
<div type="Verse" n="12">
</div>
</div>
</div>
</text>
Quiero este HTML:
<span class="level1">Book 3</span>
<span class="level2">Chapter 6</span>
<span class="level3">Verse 12</span>
No se sabe a priori qué tan profundo podrían ir estos elementos div
. Los div
s podrían ser Libro -> Capítulo. Podrían ser Volumen -> Libro -> Capítulo -> Párrafo -> Línea.
No puedo confiar en los valores de @type. Algunos o todos podrían ser NULL.
Como usualmente con XSL, usa recursión.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/text">
<html>
<xsl:apply-templates>
<xsl:with-param name="level" select="1"/>
</xsl:apply-templates>
</html>
</xsl:template>
<xsl:template match="div">
<xsl:param name="level"/>
<span class="{concat(''level'',$level)}"><xsl:value-of select="@type"/> <xsl:value-of select="@n"/></span>
<xsl:apply-templates>
<xsl:with-param name="level" select="$level+1"/>
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>
O sin usar recursión, pero la respuesta de Dimitre es mejor que la mía
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/text">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="//div">
<xsl:variable name="depth" select="count(ancestor::*)"/>
<xsl:if test="$depth > 0">
<xsl:element name="span">
<xsl:attribute name="class">
<xsl:value-of select="concat(''level'',$depth)"/>
</xsl:attribute>
<xsl:value-of select="concat(@type, '' '' , @n)"/>
</xsl:element>
</xsl:if>
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
Esto tiene una solución muy simple y corta: sin recurrencia, sin parámetros, sin xsl:element
, sin xsl:attribute
:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="div">
<span class="level{count(ancestor::*)}">
<xsl:value-of select="concat(@type, '' '', @n)"/>
</span>
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
cuando esta transformación se aplica en el documento XML proporcionado :
<text>
<div type="Book" n="3">
<div type="Chapter" n="6">
<div type="Verse" n="12"></div></div></div>
</text>
el resultado deseado y correcto se produce :
<span class="level1">Book 3</span>
<span class="level2">Chapter 6</span>
<span class="level3">Verse 12</span>
Explicación : uso adecuado de plantillas, AVT y la función count()
.