2010-04-29 14 views
5

bien tengo este xmlXSL por nodo

<roots> 
<root> 
    <name>first</name> 
    <item type='test'><something>A</something></item> 
    <item type='test'><something>B</something></item> 
    <item type='test'><something>C</something></item> 
    <item type='test'><something>A</something></item> 
    <item type='other'><something>A</something></item> 
    <item type='test'><something>B</something></item> 
    <item type='other'><something>D</something></item> 

</root> 
<root> 
<name>second</name> 
    <item type='test'><something>E</something></item> 
    <item type='test'><something>B</something></item> 
    <item type='test'><something>F</something></item> 
    <item type='test'><something>A</something></item> 
    <item type='other'><something>A</something></item> 
    <item type='test'><something>B</something></item> 
    <item type='other'><something>D</something></item> 

</root> 

</roots> 

Ahora necesito para obtener los valores singulares de cada nodo raíz hasta ahora he

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:output indent="yes" method="text"/> 
    <xsl:key name="item-by-value" match="something" use="."/> 
    <xsl:key name="rootkey" match="root" use="name"/> 

    <xsl:template match="/"> 
    <xsl:for-each select="key('rootkey','second')"> 
     <xsl:for-each select="item/something"> 
     <xsl:if test="generate-id() = generate-id(key('item-by-value', normalize-space(.)))"> 
      <xsl:value-of select="."/> 
     </xsl:if> 
     </xsl:for-each> 
    </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 

si uso como "primera" la clave para obtener sólo la primera raíz i obtener un buen resultado ABCD

cómo cada vez si yo uso "segundo" solo me dan EF pero necesito que el resultado sea ABDFE

+0

buena pregunta (1). Vea mi respuesta para una solución completa y correcta. :) –

Respuesta

2

Obtengo EBFAD con una ligera modificación de su xsl. La clave es que si está utilizando la clave para encontrar el primer nodo con este contenido bajo el elemento raíz dado, la clave debe ser específica del elemento raíz. He cambiado la xsl:key a:

<xsl:key name="item-by-value" match="something" 
use="concat(normalize-space(.), ' ', generate-id(./ancestor::root))"/> 

A continuación, la prueba se convierte en xsl:if:

<xsl:if test="generate-id() = generate-id(key('item-by-value', 
        concat(normalize-space(.), ' ', generate-id(./ancestor::root))))"> 
0

Creo que eres muy cercano. Pero sólo desea que el primer valor de la tecla de partida por valor que tiene la raíz correcta como padre:

<xsl:for-each select="key('rootkey','second')"> 
    <xsl:variable name="root" select="generate-id()" /> 
    <xsl:for-each select="item/something"> 
     <xsl:sort order="ascending" select="." data-type="text"/> 
     <xsl:if test="generate-id() = generate-id(key('item-by-value', .)[generate-id(ancestor::root)=$root][1])"> 
      <xsl:value-of select="."/> 
     </xsl:if> 
    </xsl:for-each> 
</xsl:for-each> 
+0

Sí, he estado cerca desde hace bastante tiempo jaja, e incluso con el [1] aún obtengo los mismos resultados – Nathan

+0

No hay necesidad de ser grosero cuando alguien intenta ayudar. Al principio no entendí la parte "única" de la pregunta. Hice un pequeño cambio en mi código para reflejar el resultado deseado. – Lucero

2

Este es un caso en el que debe utilizar una clave compuesta.

Esta transformación:

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

<xsl:key name="kSomethingByNameAndVal" match="something" 
    use="concat(../../name, '+', .)"/> 

<xsl:template match="/"> 
    <xsl:for-each select="*/*"> 
    <xsl:for-each select= 
     "item/something 
      [generate-id() 
      = 
       generate-id(key('kSomethingByNameAndVal', 
           concat(../../name, '+', .) 
          ) 
         ) 
      ] 
     "> 

     <xsl:value-of select="."/> 
    </xsl:for-each> 
    <xsl:text>&#xA;</xsl:text> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

cuando se aplica en el documento XML proporcionado produce correctamente el resultado deseado:

ABCD

EBFAD

Cuestiones relacionadas