On Feb 9, 2004, at 9:49 AM, Alan wrote:
* Mark Lundquist <[EMAIL PROTECTED]> [2004-02-05 07:19]:
OK, I am just learning Woody for the first time. The wiki docs are
most helpful.
I am going through the same experience. I am recording my
impressions and discoveries in my web log:
http://engrm.com/
Thanks!
We should chatter about our experiences on list. Our back and forth
might produce some documentation.
Good idea.
My pipelines look like this:
<map:match pattern="hello-world-display-pipeline">
<map:generate src="forms/view/hello-world.xml"/>
<map:transform type="woody"/>
<map:transform type="xslt" src="stylesheets/application/web.xslt">
<map:parameter name="base-link" value="."/>
</map:transform>
<map:serialize type="html"/>
</map:match>
I know nothing of a WoodyGenerator.
"This XSLT only has to handle individual widgets, and not the page
as a whole, and is thus not specific for one form but can be
reused across forms." Well yes, but then the template was
form-specific in the first place, and arguably it was more
laborious to have to call out each widget than it would be to
match them in using <xsl:apply-templates>, isn't it?
I am building my own widget stylesheet. I include it in my page
stylesheets. The templates match using apply-templates. You do
not need to call them explicitly.
Right... but by that time, you've already had to "declare" your widgets twice, right? It takes two pipelines to make a Woody form happen: a "Controller pipeline", and a "View pipeline". Your excerpt above shows the "View pipeline". But you also have another pipeline that invokes a flowscript to (a) create the form instance, and (b) display it by calling its showForm() method (with your "view pipeline" as a parameter). So then — the Form constructor named a definition file, full of elements from the "wd" namespace. Compare that with your "forms/view/hello-world.xml" — that's the "form template", full of stuff from the "wt" namespace. In your case, maybe you have a form template that actually brings something to the table, but if you looked at my form definition file and my form template file side-by-side, you'd probably say, "wow man, that's... kinda redundant."
It should be OK to use Woody forms without a template. I can easily envision applications where being able to plug into a template is a nice convenience. In my project, the template approach gets in the way.
The woody stylesheets seem to be a little bit in limbo right now. The Wiki pages talk about them as though they already were what they want to be: first-class, reusable generic templates for generating HTML controls from Woody widgets. It seems like maybe the Wiki is ahead of the game here — see http://wiki.cocoondev.org/Wiki.jsp?page=WoodyXSLT, where what is described is similar to what's in the 2.1.3 distro, but not quite (I just see the first three of the five stylesheets mentioned, with the calendar stuff included in woody-field-styling.xsl). Arguably, if these are to be "standard" parts of Cocoon Forms, they don't belong in the "samples" directory. I guess we'll see when 2.1.4 comes out.
I think you have the right idea, making your own widget stylesheet. The sample woody-field-styling.xsl IMHO doesn't provide for very good separation of concerns, because it tries to lay out the whole form and style the labels and everything. I took woody-field-styling.xsl, and ripped out all that stuff, so that I ended up with templates that just generate the HTML controls — that's it. So this stylesheet is 100% reusable. The parts that are specific to the look-and-feel of my project — the form layout, label styling, dealing with validation messages — are done with separate stylesheets.
I make a lot of use of the mode attribute to template and
apply-tempaltes. Have you started playing around with this?
Using include and the mode attribute I'm getting some pretty
impressive resuse and modularization in my stylesheets.
I have played with moded templates a little bit, but it's not obvious to me how you're using them for form styling, so I'd be really interested if to see some more details about what you're doing that way!
(I use modes to control multiple phases of processing within a single stylesheet, with the node-set() XSLT extension function).
http://wiki.cocoondev.org/Wiki.jsp?page=WoodyTemplateTransformer has
this to say: "If you prefer to do everything with XSLT, you have also
the option of using the WoodyGenerator. In general we recommend to use
the woody transformer though." Why is the transformer approach
recommended over the generator approach? I don't get it.
Nor do I. Documentation for WoodyGenerator is thin.
Right. It's kind of like it's a secret or something.
Here's what it looks like happened...
I'm guessing that the WoodyGenerator came first. At that time, the controller aspects of woody were implemented using actions (and you can still see how that's done in some of the Woody samples). Somebody developed the WoodyTemplateTransformer because this "pull-model" template approach was going to make their life easier. I think maybe it's more natural when you have plenty of static content. Then it would make sense to think of that as the "bottommost" layer of content, and it might feel wrong to start with the form and then write the static content into the XSLT stylesheets to build it up around the form... because if that's really the "content", then you want to think of it as the "source document", not the "styling"! So you want to start with the fixed content, and then interpolate or "plug in" the form elements to that, which is what the template transformer approach is all about. But in my application its more natural to think of the form itself as the most primitive content on the page, and everything else really is built up around that in the stylesheets. But anyway, the template generator approach seemed so wonderful and obviously better, that it seemed to someone like it really pretty much superseded the generator approach, and they figured (I'm just guessing here), that occasions to use the generator approach would be few and far-between, or maybe a matter of quirky individual taste, so this bias got written in to the documentation.
Then flow came along, and the WoodyTemplateTransformer was made flow-friendly: first and foremost, it knows about the continuation ID! But the WoodyGenerator fell behind the curve, probably because it was a second-class citizen already. It is not flow-happy! (Compare the source for the generator and transformer to see).
This is where I got stuck — I could create and display a form using flow and display it using the generator (and my stylesheet), but then for flow you have to encode that continuation ID into the <form action="..."> somehow, and there's no way to do it!
Then I Googled up this post from Marc Portier at Outerthought, one of the Woody developers... check it out: http://archives.real-time.com/pipermail/cocoon-devel/2003-December/025453.html
So anyway... I'm back to using the WoodyTemplateTransformer for now. >sigh<.
It looks to me
like a WoodyGenerator is a way to stream an object of type
org.apache.cocoon.woody.formmodel.Form. How you get your hands
on one of those in your pipeline is a mystery to me.
Well, you have to do the same thing when you use the transformer, so I guess it's so mysterious that you don't even realize it's there! :-) Check it out, so you have this flowscript, right, and it says something like this for your example:
form = new Form ("hello-world.wd"); // whatever
form.showForm ("hello-world-display-pipeline");
Then the hello-world-display-pipeline takes that form, and... hey, wait a minute, how did you get that form "into your pipeline"? The source stream for this pipeline is not the form, it's the form template (forms/view/hello-world.xml). You transform that with the WoodyTemplateTransformer like this:
<map:transform type="woody"/>
and that transformer "plugs in" the widgets into your template... but where does it get the widgets to plug in? It''s magic! The transformer gets the form instance from the request attribute context, either (a) by default from the key "woody-form", attached to the bizdata object passed in to showForm() in the flow; (b) as given by a JXPath expression in the <wt:form-template location="..."> attribute, or (c) from a request attribute named in:
<map:transform type="woody" attribute-name="...">
...and if it's (c), then you have to do something in your flow (see below) to set it up first...
With WoodyGenerator, you're kinda roughing it a little bit because it only supports the (c) way, and it's undocumented how to do it from flow (and arguably, that's OK for now, since WoodyGenerator can't make a form that you can handle with flow!). But to get an idea what it would be like if this worked, try this:
1)
<map:match pattern="hello-world-display-pipeline">
<map:generate type="woody" src="forms/view/hello-world.xml">
<map:parameter name="attribute-name" value="hello-form"
<map:serialize type="xml"/>
</map:match>
2) Then, add the super-secret ingredient in your flowscript, right before the call to showForm():
cocoon.request.setAttribute ('hello-form', form.form);
Invoke your controller pipeline, and you'll get the XML from your view pipeline.
All the best,
~ml
