cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Hunsberger, Peter" <>
Subject RE: concatenate two pipelines (was on dev list: Re: Running Schematron validation from flow)
Date Tue, 30 Dec 2003 15:54:31 GMT
Sebastian Klamar <> asks:

> * Hunsberger, Peter [2003-12-29 21:45 +0100] wrote:
> > Ok, figured this out:  don't use copy, use 
> processPipelineTo and use 
> > the xmodule as the target...  So far so good, except I'm not seeing 
> > the result in the request attribute after I've written it.
> > 
> > I might note that if this works we've sort of got the 
> capabliity for 
> > dynamically composing pipelines in flowscript:  run 
> whatever pipeline 
> > you want to write whatever data into memory, later run a regular 
> > pileline to aggregate this in memory data with it's normal 
> output....
> Peter, could you be more verbose how to concatenate several 
> pipelines together with the help of the new xmodule?


I can try.  In the flow you can do something like: 

    var sourceURI = "cocoon:"+target_pipeline;
    var destinationURI = "xmodule:request-attr:tempstorage";
    var resolver = null;
    var destination = null;
        resolver = cocoon.getComponent( );
        destination = resolver.resolveURI( destinationURI );
        output = destination.getOutputStream();
        cocoon.processPipelineTo( sourceURI, {}, output );
    } finally {
        if (destination != null)
            resolver.release( destination );
        cocoon.releaseComponent( resolver );

This will cause Cocoon to run the "target_pipeline" and stash the
contents in the request attribute "tempstorage" (in this case).  Later,
when you want to get at the data you can run a generator that pulls the
data back out of the request attribute.  In particular, the request
generator will do the trick with the "generate-attributes" parameter if
you don't mind getting all of the rest of the request data and having to
parse some pretty long xpath to find the data:

                <map:generate type="request">
                    <map:parameter name="generate-attributes"

You can of course run as many of these arbitrary pipelines as you want,
stashing the contents into as many variables as you want, and then use
map:aggregate to aggregate all the data from all the attributes one by
one or have a generator that just knows what attributes to look at all
at once (or just grab all attributes as per the request generator).

Note, that you can also grab the data back out of the output stream at
the time it is generated and stash it in a flow variable.  This can then
be passed back into a pipeline as variable (though parsing it will
require treating it as a nodeset if using it as XML -- no big deal).

I'm not quite sure what to think of this approach overall, it seems to
push the boundaries of clean Cocoon design.  However, for us it makes
running Schematron as a validator very straight forward, I can basically
write a sendPageAndValidate function that returns a Boolean if the page
is valid, so flow looks like:

        var valid = false;
        while ( !valid )
            valid = _sendPageAndValidate( "run/_page/" + screen );
        cocoon.sendPage( "run/_page/" + nextscreen );

Each sendPage picks up any errors created by the previous validation
pass and most importantly to us we have full access to the Cocoon
pipeline within Schematron so we can cross validate data from one screen
with data (already in our database) produced by another screen.  The
trick here is to have the validating pipeline run a simple transformer
that looks for Schematron assert statements in the output stream and
sets another request variable indicating what it found.  You can then
pick this back up in the flow function I gave at the top of this reply:

        if ( cocoon.request.getAttribute( "validationErrorLevel" ) == 0
            return true;
		return false;

View raw message