2012-02-04 10 views
7

Utilizzando XSLT/XPATH 1.0, voglio creare HTML dove l'attributo class di un elemento span indica la profondità nella gerarchia XML originale.Output della profondità del nodo corrente nella gerarchia

Ad esempio, con questo frammento XML:

<text> 
    <div type="Book" n="3"> 
     <div type="Chapter" n="6"> 
      <div type="Verse" n="12"> 
      </div> 
     </div> 
    </div> 
</text> 

voglio che questo HTML:

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

Come profondo questi div elementi potrebbero andare non è noto a priori. Il numero div potrebbe essere Book -> Chapter. Potrebbero essere Volume -> Libro -> Capitolo -> Paragrafo -> Linea.

Non posso fare affidamento sui valori di @type. Alcuni o tutti potrebbero essere NULL.

risposta

16

Questo ha una soluzione molto semplice e breve - non ricorsione, senza parametri, senza xsl:element, no 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> 

quando questa trasformazione è applicato sul documento XML fornito:

<text> 
    <div type="Book" n="3"> 
     <div type="Chapter" n="6"> 
      <div type="Verse" n="12"></div></div></div> 
</text> 

The Wanted, risultato corretto è prodotto:

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

Spiegazione: L'uso corretto di modelli, AVT e la funzione count().

0

Come di consueto con XSL, utilizzare la ricorsione.

<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 senza usare la ricorsione - ma la risposta di Dimitre è meglio che il mio unico

<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> 
Problemi correlati