2012-02-04 11 views
7

Usando XSLT/XPATH 1.0, quiero crear HTML donde el atributo class de un elemento span indica la profundidad en la jerarquía XML original.Profundidad de salida del nodo actual en la jerarquía

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 código HTML:

<span class="level1">Book 3</span> 
<span class="level2">Chapter 6</span> 
<span class="level3">Verse 12</span> 

¿A qué profundidad estos elementos podrían ir div no se conoce a priori. El div s puede 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.

Respuesta

16

Esto tiene una solución muy simple y corto - sin recursividad, no hay 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 se aplica esta transformación 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, se produce correcta:

<span class="level1">Book 3</span> 
<span class="level2">Chapter 6</span> 
<span class="level3">Verse 12</span> 

Explicación: El uso adecuado de las plantillas, AVT y la función count().

0

Como suele ser con XSL, utilice recursividad.

<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> 
5

o sin el uso de la recursividad - pero la respuesta de Dimitre es mejor que mi uno

<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> 
Cuestiones relacionadas