Iterating elements multiple times.

Here should go questions about transforming XML with XSLT and FOP.
William
Posts: 42
Joined: Sun Jul 15, 2012 12:26 pm
Location: London

Iterating elements multiple times.

Post by William »

Hello again!

In my transformer I need to iterate my XML x times, and apply various date changes and calculations on the extracted results.

Using :

Code: Select all

<xsl:for-each select="for $offset in (0 to ($loopCount -1)) return $offset">
<xsl:call-template name="stuff">
<xsl:with-param name="offset" select="."/>
</xsl:call-template>
</xsl:for-each>
results in :

Code: Select all

 Required item type of first operand of '/' is node(); supplied value has item type xs:integer


When calling the template like this:

Code: Select all


<xsl:template name="stuff">
<xsl:param name="offset"/>
<nodeName>
<xsl:for-each select="./xxxx">
...
</xsl:template>
And of course the same error occurs if I move the <xsl:for-each> into the template.

I know I'm not doing it right but I really can't see another way, can anyone show me how this should be done please?

--
William
William
Posts: 42
Joined: Sun Jul 15, 2012 12:26 pm
Location: London

Re: Iterating elements multiple times.

Post by William »

Does the lack of response on this topic mean that the solution is so obvious that only an idiot (me) would miss it. If this is the case I would still like to know what it is. :oops:

Or maybe does it mean that it is indeed a lot harder to actually put in to practice.

Or, there's not enough information in the original post to elicit an answer.

I really would appreciate some help with this.

--
William
adrian
Posts: 2855
Joined: Tue May 17, 2005 4:01 pm

Re: Iterating elements multiple times.

Post by adrian »

Hi,

It is a little obvious what you're doing wrong. What's not very clear to me is what you want to achieve.

Let me explain:

Code: Select all

<xsl:for-each select="for $offset in (0 to ($loopCount -1)) return $offset">
This xsl:for-each iterates on a sequence of integers (0, 1, 2, ... $loopCount-1). My first observation is that you could have very well written this as:

Code: Select all

<xsl:for-each select="0 to $loopCount - 1">
Since you iterate on a sequence of integers, the context(.) is the current integer. This context is also inherited by the called template. That's why the stylesheet fails in the xsl:for-each from the "stuff" template (<xsl:for-each select="./xxxx">).

I'm not sure what you want to do in this last xsl:for-each.
If you just want to iterate on the entire document every time, make sure you pass the document node as an argument. You will have to keep this in a variable before any xsl:for-each, especially the one over the sequence of integers.
e.g.

Code: Select all


<xsl:variable name="doc" select="/"/>
<xsl:for-each select="0 to ($loopCount - 1)">
<xsl:call-template name="stuff">
<xsl:with-param name="offset" select="."/>
<xsl:with-param name="node" select="$doc"/>
</xsl:call-template>
</xsl:for-each>
and the template:

Code: Select all

<xsl:template name="stuff">
<xsl:param name="offset"/>
<xsl:param name="node"/>
<nodeName>
<xsl:for-each select="$node/xxxx">
...
</xsl:template>
Although, I have to mention that whatever it is you're trying to do, there's probably a simpler way to do it than this.
Why do you want to process the entire document multiple times? What is the goal? Have you considered a solution where this could be achieved in a single step?

Regards,
Adrian
Adrian Buza
<oXygen/> XML Editor, Schema Editor and XSLT Editor/Debugger
http://www.oxygenxml.com
William
Posts: 42
Joined: Sun Jul 15, 2012 12:26 pm
Location: London

Re: Iterating elements multiple times.

Post by William »

:D Thank you Adrian, very much appreciated and for a bit of background:

The XML file contains data I feed in to a mathematical model so I need to extract data from it that meets my current criterion and create various data sets for putting into the model.

However, each set of data I feed in needs 'adjusting' depending on various factors (parameter values to be set by the Java application)

So on the first iteration I would look for data that was within my range parameters (fromDateX, toDateY) I would then apply my BlockCalculator to it and if the result of this passed my sanity check include it in the set.

Then, on the next iteration(s) I would then add X Hours to the fromDateX value, and then re-calculate the block values for it. Although I will iterate some of the data many times, these calculated values change due to other factors.

I hope this makes sense to you and you can see why I'm doing multiple iterations.

--
William
Post Reply