2011-06-15 10 views
6

Tengo un pedazo de XML que tiene este aspecto:XSLT XSL: Con fines de cada selección condicional

<root> 
    <tag1>tractor</tag1> 
    <tag2> 
    <subtag1 att="apple" /> 
    <subtag2> 
     <subsubtag1>red</subsubtag1>   
     <subsubtag2>lunch</subsubtag2> 
    </subtag2> 
    </tag2>  
    <tag1>forklift</tag1> 
    <tag2> 
    <subtag1 att="pear" /> 
    <subtag2> 
     <subsubtag1>green</subsubtag1>   
     <subsubtag2>breakfast</subsubtag2> 
    </subtag2> 
    </tag2>  
    <tag2> 
    <subtag1 att="apple" /> 
    <subtag2> 
     <subsubtag1>green</subsubtag1>   
     <subsubtag2>dinner</subsubtag2> 
    </subtag2> 
    </tag2> 
    <tag1>combine harvester</tag1> 
</root> 

Lo que necesito para obtener transformarlo para que consigo etiquetas secundarias 2 y 3 de cada nodo tag2, pero solo los nodos tag2 donde subtag1 es apple. También necesito un número de secuencia para cada uno.

Mi código actual es como la siguiente:

<xsl:for-each select="//tag2"> 
    <apple> 
    <seq_num><xsl:value-of select="position()" /></seq_num> 
    <colour><xsl:value_of select="subtag2" /></colour> 
    <meal><xsl:value_of select="subtag3" /></meal> 
    </apple> 
</xsl:for-each> 

Esto estaría bien, excepto que necesito para-cada uno sólo para devolver el tag2 que son las manzanas (es decir subtag1 = manzana). No puedo usar un xsl: if o un xsl: cuando porque entonces el número de secuencia sería inexacto para la segunda manzana.

¿Alguna idea?

Gracias, Rik

Respuesta

13

para quedarse con su código, debe ser tan simple como:

<xsl:for-each select="//tag2[subtag1/@att='apple']"> 
    <apple> 
    <seq_num><xsl:value-of select="position()" /></seq_num> 
    <colour><xsl:value-of select="subtag2/subsubtag1" /></colour> 
    <meal><xsl:value-of select="subtag2/subsubtag2" /></meal> 
    </apple> 
</xsl:for-each> 

De acuerdo con los comentarios a continuación, como se sugiere, es mejor evitar //. Deberías poder cuando estés en el contexto correcto. Por ejemplo:

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

    <xsl:output method="xml" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="/root"> 
     <xsl:for-each select="tag2[subtag1/@att='apple']"> 
      <apple> 
       <seq_num><xsl:value-of select="position()" /></seq_num> 
       <colour><xsl:value-of select="subtag2/subsubtag1" /></colour> 
       <meal><xsl:value-of select="subtag2/subsubtag2" /></meal> 
      </apple> 
     </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 

Aplicado en su entrada, produce el mismo resultado. O aún mejor, evite el xsl:for-each también:

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

    <xsl:output method="xml" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="/root"> 
     <xsl:apply-templates select="tag2[subtag1/@att='apple']"/> 
    </xsl:template> 

    <xsl:template match="tag2"> 
     <apple> 
      <seq_num><xsl:value-of select="position()" /></seq_num> 
      <colour><xsl:value-of select="subtag2/subsubtag1" /></colour> 
      <meal><xsl:value-of select="subtag2/subsubtag2" /></meal> 
     </apple> 
    </xsl:template> 

</xsl:stylesheet> 
+0

Eso funciona? Prefiero escribir 'subtag1/text()' –

+0

Sí, recién editado. –

+3

Por lo general, trato de evitar el operador perezoso '//' XPath: es una gran sobrecarga de rendimiento en el procesamiento de archivos XML grandes y puede causar problemas extraños en documentos XML complejos. Si conoce la ruta absoluta/relativa, úselo. – Mikaveli

Cuestiones relacionadas