You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cocoon.apache.org by Guido Casper <gc...@s-und-n.de> on 2003/12/07 14:24:59 UTC

extending FOM? (was on cocoon-users: Re: Parsing Source into DOM in Flow)

Did anyone else also feel the need to have something like
processPipelineTo but getting a DOM or just an InputStream instead of
just streaming it directly to another OutputStream?

Guido


Geoff Howard wrote:
> Upayavira wrote:
>> Maybe my last question was too specific.
>>
>> I'm trying to parse the contents of a source into a DOM in
>> Flowscript, but am getting all sorts of errors. Can anyone provide a
>> better way than this (which doesn't work)?
>>
>> var resolver =
>>
cocoon.getComponent(Packages.org.apache.excalibur.source.SourceResolver.
ROLE);
>>
>> var source = resolver.resolveURI("blah.xml");
>> var builder =
>>
Packages.javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocum
entBuilder();
>
> I think I have observed that you cannot use the returned result of a
> java method call ( newInstance() ) as a java object in flow (
> .newDocumentBuilder() ).
>
> The workaround I have found is to separate the calls:
>
> var builderFactory =
> Packages.javax.xml.parsers.DocumentBuilderFactory.newInstance();
>
> var builder = builderFactory.newDocumentBuilder();
>
> I don't know if this is a bug or not, don't know if it's only when
> calling with Packages or not.  I also have not carefully confirmed
> this.
>
> Finally, don't we have a convenience component to do this?
>
> Geoff
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@cocoon.apache.org
> For additional commands, e-mail: users-help@cocoon.apache.org


Re: extending FOM? (was on cocoon-users: Re: Parsing Source into DOM in Flow)

Posted by Guido Casper <gc...@s-und-n.de>.
Sylvain Wallez wrote:
> Guido Casper wrote:
>
>> Did anyone else also feel the need to have something like
>> processPipelineTo but getting a DOM or just an InputStream instead
>> of just streaming it directly to another OutputStream?
>>
>>
>
> Rather than extending the FOM, what we need is a helper JS library
> that
> is a simple wrapper around the SourceResolver and the
> SourceUtil.toDOM() method. I have this on my projects in a
> "flow-utils.js" file.

Yes but passing parameters to the pipeline that way is a hassle and
misses the elegance of JXTemplate.

Guido

>
> I'll add it in the CVS (needs a little polishing). In the meantime,
> here are the DOM-related functions:
>
> ========================================================
>
> // Create a new document, given the name of its root element
> function newDocument(root) {
>     var result =
>
Packages.javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocum
entBuilder().newDocument();
>     result.appendChild(result.createElement("News"));
>     return result;
> }
>
> // Load a document from an URI, absolute or relative to the current
> sitemap function loadDocument(uri) {
>     var resolver =
> cocoon.getComponent("org.apache.excalibur.source.SourceResolver");
>     var source = resolver.resolveURI(uri);
>     try {
>         var document =
> Packages.org.apache.cocoon.components.source.SourceUtil.toDOM(source);
>     } finally {
>         resolver.release(source);
>         cocoon.releaseComponent(resolver);
>     }
>     return document;
> }
>
> // Save a document to an URI (which should be writeable)
> function saveDocument(document, uri) {
>     var resolver =
>
cocoon.getComponent(Packages.org.apache.cocoon.environment.SourceResolve
r.ROLE);
>     var source = resolver.resolveURI(uri);
>     var output = null;
>
>     try {
>         output = source.getOutputStream();
>
>         var transformer =
>
Packages.javax.xml.transform.TransformerFactory.newInstance().newTransfo
rmer();
>
>
>
transformer.setOutputProperty(Packages.javax.xml.transform.OutputKeys.IN
DENT,
> "true");
>
>
transformer.setOutputProperty(Packages.javax.xml.transform.OutputKeys.ME
THOD,
> "xml");
>
>
transformer.setOutputProperty(Packages.javax.xml.transform.OutputKeys.EN
CODING,
> "ISO-8859-1");
>         transformer.transform(
>             new Packages.javax.xml.transform.dom.DOMSource(document),
>             new
>         Packages.javax.xml.transform.stream.StreamResult(output) );
>
>     } finally {
>         if (output != null) output.close();
>         resolver.release(source);
>         cocoon.releaseComponent(resolver);
>     }
> }
>
> ========================================================
>
> Note that processPipelineTo is nothing more than copying the result
> of a "cocoon:/" uri to an outputstream after having called
> FlowHelper.setContextObject(objectModel, viewdata);
>
> Sylvain


Re: extending FOM? (was on cocoon-users: Re: Parsing Source into DOM in Flow)

Posted by Sylvain Wallez <sy...@apache.org>.
Guido Casper wrote:

>Did anyone else also feel the need to have something like processPipelineTo but getting a DOM or just an InputStream instead of just streaming it directly to another OutputStream?
>  
>

Rather than extending the FOM, what we need is a helper JS library that 
is a simple wrapper around the SourceResolver and the SourceUtil.toDOM() 
method. I have this on my projects in a "flow-utils.js" file.

I'll add it in the CVS (needs a little polishing). In the meantime, here 
are the DOM-related functions:

========================================================

// Create a new document, given the name of its root element
function newDocument(root) {
    var result = 
Packages.javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
    result.appendChild(result.createElement("News"));
    return result;
}

// Load a document from an URI, absolute or relative to the current sitemap
function loadDocument(uri) {
    var resolver = 
cocoon.getComponent("org.apache.excalibur.source.SourceResolver");
    var source = resolver.resolveURI(uri);
    try {
        var document = 
Packages.org.apache.cocoon.components.source.SourceUtil.toDOM(source);
    } finally {
        resolver.release(source);
        cocoon.releaseComponent(resolver);
    }
    return document;
}

// Save a document to an URI (which should be writeable)
function saveDocument(document, uri) {
    var resolver = 
cocoon.getComponent(Packages.org.apache.cocoon.environment.SourceResolver.ROLE);
    var source = resolver.resolveURI(uri);
    var output = null;
   
    try {
        output = source.getOutputStream();
   
        var transformer = 
Packages.javax.xml.transform.TransformerFactory.newInstance().newTransformer();
   
        
transformer.setOutputProperty(Packages.javax.xml.transform.OutputKeys.INDENT, 
"true");
        
transformer.setOutputProperty(Packages.javax.xml.transform.OutputKeys.METHOD, 
"xml");
        
transformer.setOutputProperty(Packages.javax.xml.transform.OutputKeys.ENCODING, 
"ISO-8859-1");
        transformer.transform(
            new Packages.javax.xml.transform.dom.DOMSource(document),
            new Packages.javax.xml.transform.stream.StreamResult(output)
        );
       
    } finally {
        if (output != null) output.close();
        resolver.release(source);
        cocoon.releaseComponent(resolver);
    }
}

========================================================

Note that processPipelineTo is nothing more than copying the result of a 
"cocoon:/" uri to an outputstream after having called 
FlowHelper.setContextObject(objectModel, viewdata);

Sylvain

-- 
Sylvain Wallez                                  Anyware Technologies
http://www.apache.org/~sylvain           http://www.anyware-tech.com
{ XML, Java, Cocoon, OpenSource }*{ Training, Consulting, Projects }
Orixo, the opensource XML business alliance  -  http://www.orixo.com



Re: extending FOM? (was on cocoon-users: Re: Parsing Source intoDOM in Flow)

Posted by da...@nada.kth.se.
Guido Casper wrote:
> Did anyone else also feel the need to have something like
> processPipelineTo but getting a DOM

Yes, I use that quite often, so it would be good if FOM could provide 
some easier to use functionality for this.

We could have a processPipelineToDOM(uri, map) that returns a DOM. I 
would also like a processPipelineToSource(uri, map, modifiableSourceURI) 
which would simlify writing pipeline content to e.g. files and
repositorys. It could also be used together with the xmodule source 
(http://nagoya.apache.org/bugzilla/show_bug.cgi?id=25210) to put DOM  with
the pipeline content in whatether object that can be accessable  from an
output module.

Implementation details
----------------------

In the processPipelineToDOM we can the avoid the serialize to output 
stream reparse to SAX steps by using the same mechanism as in the 
o.a.c.components.source.impl.SitemapSource. I.e. instead of using the 
process(String uri, Object bizData, OutputStream out, Environment env) 
from o.a.c.components.flow.AbstractInterpreter, we could write a
process(String uri, Object bizData, ContentHandler out, Environment  env),
that process the pipeline directly to a ContentHandler, that in  turn
could write the DOM, se the toSAX method in the SitemapSource for 
details.

Something similar could be used for the processPipelineToSource, but  here
we would need some convention for knowing when a ModifiableSource  can
accept SAX input, before migrating to the Excalibur sources there  was an
interface o.a.c.environment.WritableSource that had a method that 
returned a ContentHandler for that purpose. One could of course let the 
ModifiableSource implement XMLConsumer, but that is a litle bit
unconvinient as there are so many methods in that interface, I would 
prefer to ihave an interface that just returns a ContentHandler e.g.

public interface SAXWritable {
     ContentHandler getContentHandler();
}

WDYT?

> or just an InputStream instead of
> just streaming it directly to another OutputStream?

Have not found any use of that yet.

>
> Guido
>
>
> Geoff Howard wrote:
>
>>Upayavira wrote:
>>>Maybe my last question was too specific.
>>>I'm trying to parse the contents of a source into a DOM in
>>>Flowscript, but am getting all sorts of errors. Can anyone provide a
better way than this (which doesn't work)?

I have not access to my code ATM but take a look at the loadDocument and 
saveDocument function in
http://cvs.apache.org/viewcvs.cgi/cocoon-2.1/src/blocks/woody/samples/flow/binding_example.js

That code can in turn be simplified to a few lines by using the toDOM  and
getSource methods is o.a.c.components.source.SourceUtil

/Daniel





Re: extending FOM?

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Guido Casper wrote:
> Christopher Oliver wrote:
>>Why not have processPipelineTo take a javax.xml.transform.Result
>>instead of an OutputStream?
> 
> Yes, that might be a good solution (although back incompatible IIUC).
> Buffering in a byte array might also work. I'm just (overly?) worried
> about the performance penalty of serialization/parsing which does not
> take place with Sylvain's approach. I think I'm seeking for the best of
> both, which might only be possible with an extra FOM method?.
> 
> Guido

While javax.xml.transform.Result is convenient for connecting to 
parsers, XSLT-transformers and serializing to SAX and DOM, it is not 
used as an external API in Cocoon. In Cocoon XMLConsumer and XMLProducer 
are the main API:s for transporting XML data. Furthermore it would be 
unpractical to use Result within Cocoon as DOMResult, SAXResult and 
StreamResult are classes instead of being interfaces.

I think that we need a

   processPipelineToSAX(String uri, Object bizData, XMLConsumer out)

that would solve the serialization/parsing performance penalty that 
worry me as well. It would not introduce any new concepts in Cocoon 
either, when you use the cocoon protocol in e.g. an aggregator, you get 
SAX output from a pipeline.

As I said in an earlier post I would like to have the convenience 
functions: processPipelineToDOM and processPipelineToSource as well.

Concerning the question where to put these things, they should IMO be 
part of the FOM. XML in form of SAX and DOM, and sources are core 
concepts in Cocoon and should therefore be supported in the FOM.

/Daniel

Re: extending FOM?

Posted by Guido Casper <gc...@s-und-n.de>.
Christopher Oliver wrote:
> Why not have processPipelineTo take a javax.xml.transform.Result
> instead of an OutputStream?

Yes, that might be a good solution (although back incompatible IIUC).
Buffering in a byte array might also work. I'm just (overly?) worried
about the performance penalty of serialization/parsing which does not
take place with Sylvain's approach. I think I'm seeking for the best of
both, which might only be possible with an extra FOM method?.

Guido

>
> Guido Casper wrote:
>
>> Did anyone else also feel the need to have something like
>> processPipelineTo but getting a DOM or just an InputStream instead of
>> just streaming it directly to another OutputStream?
>>
>> Guido
>>
>>
>> Geoff Howard wrote:
>>
>>
>>> Upayavira wrote:
>>>
>>>
>>>> Maybe my last question was too specific.
>>>>
>>>> I'm trying to parse the contents of a source into a DOM in
>>>> Flowscript, but am getting all sorts of errors. Can anyone provide
>>>> a better way than this (which doesn't work)?
>>>>
>>>> var resolver =
>>>>
>>>>
>>>>
>>
cocoon.getComponent(Packages.org.apache.excalibur.source.SourceResolver.
>> ROLE);
>>
>>
>>>> var source = resolver.resolveURI("blah.xml");
>>>> var builder =
>>>>
>>>>
>>>>
>>
Packages.javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocum
>> entBuilder();
>>
>>
>>> I think I have observed that you cannot use the returned result of a
>>> java method call ( newInstance() ) as a java object in flow (
>>> .newDocumentBuilder() ).
>>>
>>> The workaround I have found is to separate the calls:
>>>
>>> var builderFactory =
>>> Packages.javax.xml.parsers.DocumentBuilderFactory.newInstance();
>>>
>>> var builder = builderFactory.newDocumentBuilder();
>>>
>>> I don't know if this is a bug or not, don't know if it's only when
>>> calling with Packages or not.  I also have not carefully confirmed
>>> this.
>>>
>>> Finally, don't we have a convenience component to do this?
>>>
>>> Geoff
>>>
>>>
>>> --------------------------------------------------------------------
-
>>> To unsubscribe, e-mail: users-unsubscribe@cocoon.apache.org
>>> For additional commands, e-mail: users-help@cocoon.apache.org


Re: extending FOM? (was on cocoon-users: Re: Parsing Source into DOM in Flow)

Posted by Christopher Oliver <re...@verizon.net>.
Why not have processPipelineTo take a javax.xml.transform.Result instead 
of an OutputStream?

Guido Casper wrote:

>Did anyone else also feel the need to have something like
>processPipelineTo but getting a DOM or just an InputStream instead of
>just streaming it directly to another OutputStream?
>
>Guido
>
>
>Geoff Howard wrote:
>  
>
>>Upayavira wrote:
>>    
>>
>>>Maybe my last question was too specific.
>>>
>>>I'm trying to parse the contents of a source into a DOM in
>>>Flowscript, but am getting all sorts of errors. Can anyone provide a
>>>better way than this (which doesn't work)?
>>>
>>>var resolver =
>>>
>>>      
>>>
>cocoon.getComponent(Packages.org.apache.excalibur.source.SourceResolver.
>ROLE);
>  
>
>>>var source = resolver.resolveURI("blah.xml");
>>>var builder =
>>>
>>>      
>>>
>Packages.javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocum
>entBuilder();
>  
>
>>I think I have observed that you cannot use the returned result of a
>>java method call ( newInstance() ) as a java object in flow (
>>.newDocumentBuilder() ).
>>
>>The workaround I have found is to separate the calls:
>>
>>var builderFactory =
>>Packages.javax.xml.parsers.DocumentBuilderFactory.newInstance();
>>
>>var builder = builderFactory.newDocumentBuilder();
>>
>>I don't know if this is a bug or not, don't know if it's only when
>>calling with Packages or not.  I also have not carefully confirmed
>>this.
>>
>>Finally, don't we have a convenience component to do this?
>>
>>Geoff
>>
>>
>>---------------------------------------------------------------------
>>To unsubscribe, e-mail: users-unsubscribe@cocoon.apache.org
>>For additional commands, e-mail: users-help@cocoon.apache.org
>>    
>>
>
>
>  
>