Reputation: 503
I'm new of XSLT and I have troubles with template recursive. My problem is: I have two file xml, the first is:
<EV>
<forma codice="f01">
...
<forma codice="f02">
...
<forma>
...
</forma>
</forma>
</forma>
</EV>
and the second is:
<forme> <!--codice_forma è "fxx"-->
<famiglia tipo="quadrilatero">
<forma codice="f00" figura="quadrato"/>
<forma codice="f01" figura="rettangolo"/>
</famiglia>
<famiglia tipo="triangolo">
<forma codice="f02" figura="triangolo equilatero"/>
<forma codice="f03" figura="triangolo rettangolo"/>
</famiglia>
</forme>
Now I must have this trasform result, with the join on attributes "codice":
<EV>
<forma tipo="quadrilatero" figura="rettangolo">
<forma ...>
<forma ...>
...
</forma>
</forma>
</forma>
</EV>
My XSLT file don't include the tags "forma":
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<evoluzione>
<!-- Ciclo su tutti i possibili snapshot presenti -->
<xsl:for-each select="/evoluzione/snapshot">
<!-- Creo il tag snapshot -->
<snapshot id="{@id}" label="{@label}">
<!-- Creo il tag data -->
<data giorno="{substring(@data,1,2)}" mese="{substring(@data,4,2)}" anno="{substring(@data,7,4)}"/>
<!-- Ciclo su tutti i possibili esseri viventi presenti nello shapshot -->
<xsl:for-each select="./EV">
<!-- Creo il tag EV -->
<EV cod_individuo="{@codice_individuo}" eta="{@eta}" salute="{@salute}" ciclo_di_vita="{@ciclo_di_vita}">
<!-- Invoco template sul file esseri_vienti.xml per ricavare l'aspettativa -->
<xsl:apply-templates select="document('/home/localhero/Scrivania/Progetto/esseri_viventi.xml')//EV">
<!-- Passo il parametro codInd al template -->
<xsl:with-param name="codInd" select="@codice_individuo"/>
</xsl:apply-templates>
<!-- Creo il tag specie -->
<specie>
<!-- Invoco template sul file tipi_esseri_viventi.xml -->
<xsl:apply-templates select="document('/home/localhero/Scrivania/Progetto/tipi_esseri_viventi.xml')//tipo">
<!-- Passo il parametro codTip al template -->
<xsl:with-param name="codTip" select="@codice_tipo"/>
</xsl:apply-templates>
</specie>
<!-- Creo il tag matrice -->
<matrice>
<!-- Qui andranno i tag di <affinità specie>%</affinità> -->
</matrice>
<!--THE TROUBLE IS THERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!-->
<!-- Invoco template sul file forme.xml -->
<xsl:apply-templates select="document('/home/localhero/Scrivania/Progetto/forme.xml')//forma">
<!-- Passo il parametro codForm al template -->
<xsl:with-param name="codForm" select=".//forma/@codice"/>
</xsl:apply-templates>
</EV>
</xsl:for-each>
</snapshot>
</xsl:for-each>
</evoluzione>
</xsl:template>
<!-- Richiamo template su tutti i nodi EV del file esseri_viventi.xml-->
<xsl:template match="EV">
<!-- Parametro codInd ricevuto in input dal template -->
<xsl:param name="codInd"/>
<!-- Se l'attributo Stringa non è NULL -->
<xsl:if test="@Stringa != ''">
<!-- Espressione regolare sull'attributo Stringa -->
<xsl:analyze-string select="@Stringa" regex="(.*),(.*),(.*),(.*),(.*),(.*),(.*)">
<xsl:matching-substring>
<!-- Se il codice individuo coincide allora crea l'attributo aspettativa -->
<xsl:if test="$codInd = regex-group(2)">
<xsl:attribute name="aspettativa">
<xsl:value-of select="regex-group(6)"/>
</xsl:attribute>
</xsl:if>
</xsl:matching-substring>
</xsl:analyze-string>
</xsl:if>
</xsl:template>
<!-- Richiamo template su tutti i nodi tipo del file esseri_viventi.xml-->
<xsl:template match="tipo">
<!-- Parametro codTip ricevuto in input dal template -->
<xsl:param name="codTip"/>
<!-- Se il codice tipo coincide allora crea gli attributi -->
<xsl:if test="$codTip = @codice">
<xsl:attribute name="famiglia">
<xsl:value-of select="../@nome"/>
</xsl:attribute>
<xsl:attribute name="nome_specie">
<xsl:value-of select="@specie"/>
</xsl:attribute>
</xsl:if>
</xsl:template>
<!-- Richiamo template su tutti i nodi forma del file forme.xml-->
<xsl:template match="forma">
<!-- Parametro codForm ricevuto in input dal template -->
<xsl:param name="codForm"/>
<!-- Se il codice forma coincide allora crea gli attributi -->
<xsl:if test="$codForm = @codice">
<!--<xsl:value-of select="$codForm"/><br/>-->
<!-- Creo il tag forma -->
<forma>
<xsl:attribute name="tipo">
<xsl:value-of select="../@tipo"/>
</xsl:attribute>
<xsl:attribute name="figura">
<xsl:value-of select="@figura"/>
</xsl:attribute>
<!-- Ricorsione -->
<xsl:apply-templates select="forma">
<!-- Passo il parametro codForm al template -->
<xsl:with-param name="codForm" select="document('/home/localhero/Scrivania/Progetto/evoluzione.xml')//forma/@codice"/>
</xsl:apply-templates>
</forma>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
My results:
...
<EV>
<forma tipo="quadrilatero" figura="rettangolo"></forma>
<forma tipo="triangolo" figura="triangolo equilatero"></forma>
<forma ...></forma>
<forma ...></forma>
...
<forma ...></forma>
</EV>
Why the recursion don't work? Why don't include in mode recursive the tags "forma" in this way:
<forma>
<forma>
...
</forma>
</forma>
Thanks very much for your patience and help!
Upvotes: 4
Views: 1906
Reputation: 338316
The simplest possible stylesheet to do what you need looks like this:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:variable name="forme" select="document('/path/to/forme.xml')//forma" />
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
<xsl:template match="forma/@codice">
<xsl:variable name="forma" select="$forme[@codice = current()]" />
<xsl:copy-of select="$forma/@figura | $forma/../@tipo" />
</xsl:template>
</xsl:stylesheet>
Notes
<EV>
document, you must (well... should) apply the stylesheet to that document, not to the lookup document.codice
attributes of <forma>
elements, so we only need a template that matches forma/@codice
and outputs different attributes.$forme[@codice = current()]
selects the matching <forma>
from the lookup document.$forma/@figura | $forma/../@tipo
selects the two attribute nodes we need.@codice
numbers are uniqe in the lookup document.The output looks like this, for your sample:
<EV>
<forma tipo="quadrilatero" figura="rettangolo">
<!-- ... -->
<forma tipo="triangolo" figura="triangolo equilatero">
<!-- ... -->
<forma>
<!-- ... -->
</forma>
</forma>
</forma>
</EV>
Upvotes: 3