Re: [xsl] variable outside a for-each loop

Subject: Re: [xsl] variable outside a for-each loop
From: Abel Braaksma <abel.online@xxxxxxxxx>
Date: Thu, 20 Sep 2007 15:39:01 +0200
Hi Matthieu,

Maybe I am missing something obvious, but on a quick review of your problem I notice three things:

1. You use an xsl:for-each on a simple selected node set. This is usually best replaced (refactored) with a xsl:template match.
2. You use a complex variable for every situation (but you figured out yourself that this is not the best way, which is why you posted the q. in the first place).
3. The snippet you showed does not produce the output you showed on the input you showed.


This is how I would do it:

<!-- this goes on the root level of the stylesheet -->
<xsl:template match="row">
<entry
one="{(entry[1]/para[. != ''] | preceding-sibling::row[entry[1]/para != ''][1])[1]}"
two="{(entry[2]/para[. != ''] | preceding-sibling::row[entry[2]/para != ''][1])[1]}" />
</xsl:template>


<!-- this goes on wherever you currently have for-each -->
<xsl:apply-templates select="row" />


If you want something like one/two/three etc for each entry that is available, I'd choose another solution, something along the following lines:


<xsl:template match="entry">
  <xs:attribute name="{format-number(position(), '[Nn]')}" select="." />
</

not sure whether the format is correct though.

HTH,
Cheers,
-- Abel Braaksma

Mathieu Malaterre wrote:
Hello,

  this is clearly a question that has been asked many times on this
mailing list. But I simply cannot find anything smart to do for my
issue:

I have the following XML (docbook):

<informaltable>
  <row>
    <entry>
      <para>ABC</para>
    </entry>
    <entry>
      <para>DEF</para>
    </entry>
  </row>
  <row>
    <entry>
      <para/>
    </entry>
    <entry>
      <para>DEF 2</para>
    </entry>
  </row>
</informaltable>

My goal is to produce:

  <table>
    <entry one="ABC" two="DEF"/>
    <entry one="ABC" two="DEF 2"/>
  </table>


In C/C++ this is trivial at each step whenever row/entry is empty I would use some local variable instead. But in XSL I am stuck with:

                <xsl:for-each select="row">
                  <xsl:variable name="one"
select="normalize-space(string-join(entry[1]/para,' '))"/>
                  <xsl:variable name="two"
select="normalize-space(string-join(entry[2]/para,' '))"/>
                  <entry one="{$one}" two="{$two}"/>
                </xsl:for-each>

Could someone please let me know what the correct solution is when using XSL ?

Thanks so much;

Current Thread