2009-10-25 12 views
6

Sé que me falta algo aquí. En la transformación XSLT a continuación, el resultado real no coincide con el resultado deseado.¿Cómo aplico plantillas a cada nodo seleccionado en un for-each?

Dentro del for-each, deseo aplicar la plantilla match="track" a cada elemento track seleccionado. Si entendí XSLT correctamente, con la configuración actual, solo los nodos secundarios de cada elemento track seleccionado se comparan con las plantillas, no con los elementos track.

¿Cómo puedo hacer que los elementos track pasen por la plantilla como lo desee? ¿Debo reconsiderar mi enfoque completo?

Nota: La transformación se ejecuta con PHP. Las declaraciones XML se han omitido por brevedad. Documento

XML:

<album> 
    <title>Grave Dancers Union</title> 
    <track id="shove">Somebody To Shove</track> 
    <track id="gold">Black Gold</track> 
    <track id="train">Runaway Train</track> 
    <producer>Michael Beinhorn</producer> 
</album> 

hoja de estilo XSL:

<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="/album"> 
     <ol> 
      <xsl:for-each select="track"> 
       <li><xsl:apply-templates/></li> 
      </xsl:for-each> 
     </ol> 
    </xsl:template> 

    <xsl:template match="track"> 
     <a href="{@id}"><xsl:apply-templates/></a> 
    </xsl:template> 
</xsl:stylesheet> 

Resultado:

<ol> 
    <li>Somebody To Shove</li> 
    <li>Black Gold</li> 
    <li>Runaway Train</li> 
</ol> 

Resultado deseado:

<ol> 
    <li><a href="shove">Somebody To Shove</a></li> 
    <li><a href="gold">Black Gold</a></li> 
    <li><a href="train">Runaway Train</a></li> 
</ol> 

Respuesta

9

Estoy de acuerdo con 'ndim' que probablemente deba reestructurar su XSLT para eliminar el bucle xsl: for-each.

Como alternativa, puede modificar el XSL: apply-templates para seleccionar el nodo pista actual dentro del xsl: for-each

<xsl:for-each select="track"> 
    <li> 
     <xsl:apply-templates select="." /> 
    </li> 
</xsl:for-each> 

Mantener el XSL: Con fines de cada uno de ellos, al menos, le permitirá ordenar las pistas en otro orden, si lo desea.

+0

Buena captura en la clasificación. Supongo que esta es la mejor solución, debido a la clasificación. – ndim

+0

Podría haber jurado que ya probé esto, pero supongo que no. ¡Esto es exactamente lo que estaba buscando, sin embargo! – Jakob

4

me gustaría reestructurar un poco (si es que no es necesario la clasificación del enfoque for-each hace que sea posible):

<xsl:template match="/album"> 
    <ol> 
    <xsl:apply-templates select="track"/> 
    </ol> 
</xsl:template> 

<xsl:template match="track"> 
    <li><a href="{@id}"><xsl:apply-templates/></a></li> 
<xsl:template> 

Esto se ve más corto y más al punto , EN MI HUMILDE OPINIÓN.

pienso que su

<xsl:for-each select="track"> 
     <li><xsl:apply-templates/></li> 
    </xsl:for-each> 

paseos a través de todos los elementos de la vía con el for-each, y luego aplica las reglas predeterminadas a sus descendientes. Por lo tanto, el contenido de for-each tiene el mismo nodo de contexto que la plantilla match="track" y, por lo tanto, la plantilla match="track" nunca coincide.

Si realmente desea utilizar el for-each de esa manera, tendrá que cambiar ninguna de las dos cosas siguientes en su enfoque:

  1. Añadir un atributo name="track" a la plantilla match="track", y luego usar <xsl:call-template/> desde dentro de for-each (mi idea, y peor que Tim C)
  2. Use la solución Tim C usando <xsl:apply-templates select="."/>. Esto tiene la ventaja de evitar nombrar y mantener la posibilidad de ordenar las pistas.
+0

La solución de reestructuración parece menos modular de lo que me gustaría (no me permite incluir pistas en un '

' o '' en otro lugar de la página/sitio, al menos no usando la misma hoja de estilo), pero probablemente tengas razón en que es la solución más suave para este ejemplo. – Jakob

+0

@Jakob Soy consciente de que esto es antiguo, pero solo quiero señalar que puede usar el atributo 'modo' para seleccionar otra plantilla para los mismos nodos. Al igual que '' and ' ...'. – janek37

0

creo que el uso de apply-templates y plantillas modos es la solución más limpia:

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

    <xsl:template match="/"> 
    <body> 
     <xsl:apply-templates select="album" mode="ol" /> 
    </body> 
    </xsl:template> 

    <xsl:template match="album" mode="ol"> 
    <ol> 
     <xsl:apply-templates select="track" mode="li" /> 
    </ol> 
    </xsl:template> 

    <xsl:template match="track" mode="li"> 
    <li> 
     <xsl:apply-templates select="." /> 
    </li> 
    </xsl:template> 

    <xsl:template match="track"> 
    <a href="{@id}"> 
     <xsl:value-of select="." /> 
    </a> 
    </xsl:template> 


</xsl:stylesheet> 

resultados en:

<body> 
    <ol> 
    <li> 
     <a href="shove">Somebody To Shove</a> 
    </li> 
    <li> 
     <a href="gold">Black Gold</a> 
    </li> 
    <li> 
     <a href="train">Runaway Train</a> 
    </li> 
    </ol> 
</body> 
0

El para-cada declaración cambia el nodo de contexto de álbum a rastrear. La llamada a apply-templates aplica de forma predeterminada plantillas a los nodos secundarios del nodo de contexto que en su caso son los nodos secundarios del elemento de pista. Por lo tanto, tu plantilla que coincida con 'track' nunca será golpeada.

Cuestiones relacionadas