[XSL-LIST Mailing List Archive Home]
Re: [xsl] running a 'pipeline' as a loop?
Subject: Re: [xsl] running a 'pipeline' as a loop?|
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Mon, 27 Oct 2008 18:27:15 -0400
Like any "loop" in XSLT, this can be done using a recursive template
that calls itself with parameters. In this case, the first pass
accepts the set of updates as a parameter, along with the source,
processes the source with the first update, and then calls itself
with its result sent in to be the source, and the update just used
removed from the update set. This continues until the update set is
empty, at which point you have your final result.
Unfortunately, my time at the moment is short so I can't sketch this
out in detail. If this hint isn't enough, maybe another intrepid
XSLTer could help you work it out. :-)
Note that this can be processor and memory-intensive, but depending
on the processor used there may also be ways around these issues.
BTW, this technique will work only in XSLT 2.0 or extended 1.0 (but
you seem to be using 2.0), since unextended XSLT 1.0 can't process
its own results.
At 05:59 PM 10/27/2008, you wrote:
I'd like to apply (essentially) the same transformation to an input
doc several times. In my case, I've got an 'base' doc and several
'update' docs. The update docs contain elements that should replace
their corresponding elements in the base doc. There can be a
variable number of update docs.
The key point is that the output of one update is to become the
input to the next update.
It seems like the cleanest way to do this would be to initialize a
variable '$source' with the base doc, and then loop through the
update docs, copying the $source to a new variable, '$output',
making the appropriate substitutions along the way. Before the loop
iterates to the next update doc, copy $output to $source, so the
output of one update becomes the input to the next update.
Conceptually, the algorithm might look like:
$source = base_doc
for each update_doc
$output = apply-update($source, update_doc)
<xsl:apply-templates mode="begin" />
<xsl:template match="service-manual" mode="begin">
<!-- load all update files for the current doc -->
select="collection($filedir)//service-manual[@update = 'true']"/>
<!-- initialize $source with the base document -->
<xsl:variable name="source"><xsl:copy-of select="."/></xsl:variable>
<!-- now loop through the update docs, in update order, and
create an new, updated version in the $output doc -->
<xsl:sort select="article/meta/@update" order="ascending"/>
<!-- now perform the update by operating on $source -->
<xsl:with-param name="updates" select="$updates"/>
<!-- copy this output to source, in preparation for
applying the next update on top of this one -->
<!-- tried copy-of instead of
apply-templates...mode="copy", but it did no better... -->
After the loop completes, $output should contain the final version
of the updated doc, but after the loop is exited, $output goes out
of scope (I'm getting an 'undefined variable' error on the last
copy-of select="$output", which would be where the final doc is
Anyone have any ideas about how I might be able to create this kind
of transform, where the input comes from the output?
Thanks in advance for any help.
Wendell Piez mailto:wapiez@xxxxxxxxxxxxxxxx
Mulberry Technologies, Inc. http://www.mulberrytech.com
17 West Jefferson Street Direct Phone: 301/315-9635
Suite 207 Phone: 301/315-9631
Rockville, MD 20850 Fax: 301/315-8285
Mulberry Technologies: A Consultancy Specializing in SGML and XML