XSLT - 递归模板

时间:2013-11-07 13:05:31

标签: xml templates xslt recursion

我是XSLT的新手,我在模板递归方面遇到了麻烦。 我的问题是:我有两个文件xml,第一个是:

    <EV>
        <forma codice="f01">
            ...
            <forma codice="f02">
                ...
                <forma>
                    ...
                </forma>
            </forma>
        </forma>
    </EV>

,第二个是:

<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>

现在我必须有这个trasform结果,加上属性“codice”:

<EV>
        <forma tipo="quadrilatero" figura="rettangolo">
           <forma ...>
               <forma ...>
                   ...
               </forma>
           </forma>
        </forma>
</EV>

我的XSLT文件不包含标签“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>

我的结果:

   ...
   <EV>
        <forma tipo="quadrilatero" figura="rettangolo"></forma>
        <forma tipo="triangolo" figura="triangolo equilatero"></forma>
        <forma ...></forma>
        <forma ...></forma>
        ...
        <forma ...></forma>
    </EV>

为什么递归不起作用?为什么不以模式递归标签“forma”以这种方式递归:

<forma>
  <forma>
     ...
  </forma>
</forma>

非常感谢您的耐心和帮助!

1 个答案:

答案 0 :(得分:3)

执行所需操作的最简单的样式表如下所示:

<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>

注释

  • 由于您希望输出与<EV>文档相同的结构,因此您必须(以及)将样式表应用于 文档,不要查阅文件。
  • “保持相同的结构”始终意味着从身份模板开始并根据需要覆盖它。
  • 在这种情况下,我们需要替换codice元素的所有<forma>属性,因此我们只需要一个匹配forma/@codice的模板并输出不同的属性。
  • $forme[@codice = current()]从查找文档中选择匹配的<forma>
  • $forma/@figura | $forma/../@tipo选择我们需要的两个属性节点。
  • 解决方案假定查找文档中的@codice个数字是唯一的。

对于您的样本,输出如下所示:

<EV>
    <forma tipo="quadrilatero" figura="rettangolo">
        <!-- ... -->
        <forma tipo="triangolo" figura="triangolo equilatero">
            <!-- ... -->
            <forma>
                <!-- ... -->
            </forma>
        </forma>
    </forma>
</EV>
相关问题