2011-08-30 19 views
7

Soy bastante nuevo en xslt y necesito ayuda con un tipo de transformación. Necesito agrupar todos los nodos de cierto tipo por uno de sus atributos y enumerar los padres de todo tipo de atributo. Es un tipo de resumen del uso de ciertas cosas en el documento. El presentaré un ejemplo simplificado.
de entrada:Agrupación de nodos XML por valor de atributo en XSLT

<root> 
<node name="node1"> 
    <somechild child-id="1"> 
</node> 
<node name="node2"> 
    <somechild child-id="2"> 
</node> 
<node name="node3"> 
    <somechild child-id="1"> 
</node> 
<node name="node4"> 
    <somechild child-id="2"> 
</node> 
<node name="node5"> 
    <somechild child-id="3"> 
</node> 
</root> 

salida deseada:

<root> 
<somechild child-id="1"> 
    <is-child-of> 
     <node name="node1" /> 
     <node name="node3" /> 
    </is-child-of> 
</somechild> 
<somechild child-id="2"> 
    <is-child-of> 
     <node name="node2" /> 
     <node name="node4" /> 
    </is-child-of> 
</somechild> 
<somechild child-id="3"> 
    <is-child-of> 
     <node name="node5" /> 
    </is-child-of> 
</somechild> 
</root> 

idea es que si es el mismo elemento en muchos nodos que tienen un mismo niño-id. Necesito encontrar todo usado por todos. Encontré esta pregunta XSLT transformation to xml, grouping by key que es similar pero hay una declaración de todos los autores al principio y no la tengo, siempre es solo un hijo de.

Respuesta

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

    <xsl:key name="k" match="somechild" use="@child-id"/> 
    <xsl:key name="n" match="node" use="somechild/@child-id"/> 

    <xsl:template match="root"> 
     <xsl:copy> 
      <xsl:apply-templates 
       select="//somechild[generate-id(.) = generate-id(key('k', @child-id))]"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="somechild"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*"/> 

      <is-child-of> 
       <xsl:apply-templates select="key('n', @child-id)"/> 
      </is-child-of> 
     </xsl:copy> 

    </xsl:template> 

    <xsl:template match="node"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="@*"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*"/> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

Salida:

<root> 
    <somechild child-id="1"> 
    <is-child-of> 
     <node name="node1" /> 
     <node name="node3" /> 
    </is-child-of> 
    </somechild> 
    <somechild child-id="2"> 
    <is-child-of> 
     <node name="node2" /> 
     <node name="node4" /> 
    </is-child-of> 
    </somechild> 
    <somechild child-id="3"> 
    <is-child-of> 
     <node name="node5" /> 
    </is-child-of> 
    </somechild> 
</root> 
+0

Muchas gracias! Usando este ejemplo, ¡pude hacer una transformación para el problema de la mina! – Pax0r

+0

@ Pax0r, ¡De nada! –

1

Puedes probar el siguiente acercamiento?

<!-- select the current child id to filter by --> 
<xsl:variable name="id" select="somechild/@child-id"/> 
<!-- select the nodes which have a somechild element with the child-id to look for --> 
<xsl:for-each select="/root//some-child[@child-id = $id]/.."> 
    <!-- for each such node, do something --> 
</xsl:for-each> 
Cuestiones relacionadas