At first glance, these macros may seem a bit complex, but I think you'll find the attached is actually quite a bit simpler than WoodyTemplateTransformer. The additional benefit is that you also have the full power of JXTemplate's in your Woody form templates (expression substitution, flow control, etc).
To use these macros, in your sitemap replace
<generate src="blah.xml"> <transform type="woody">
with <generate type="jx" src="blah.xml">
and modify your form template to import the jx template containing the macros, e.g:
<page xmlns:wt="http://apache.org/cocoon/woody/template/1.0" xmlns:wi="http://apache.org/cocoon/woody/instance/1.0" xmlns:jx="http://apache.org/cocoon/templates/jx/1.0">
<jx:import uri="forms/woody.jx"/>
<title>Sample form</title>
<content>
<wt:form-template action="#{$continuation/id}.continue" method="POST">
...Let me know what you think.
Regards,
Chris
<jx:template xmlns:jx="http://apache.org/cocoon/templates/jx/1.0">
<jx:set var="woodyStack" value="${java.util.Stack()}"/>
<jx:macro name="form-template"
targetNamespace="http://apache.org/cocoon/woody/template/1.0">
<jx:parameter name="action"/>
<jx:parameter name="method"/>
<wi:form-template xmlns:wi="http://apache.org/cocoon/woody/instance/1.0"
action="${action}" method="${method}">
<jx:set var="ignored" value="${woodyStack.push(this['woody-form'])}"/>
<jx:evalBody/>
<jx:set var="ignored" value="${woodyStack.pop()}"/>
</wi:form-template>
</jx:macro>
<jx:macro name="widget" targetNamespace="http://apache.org/cocoon/woody/template/1.0">
<jx:parameter name="id"/>
<jx:set var="contextWidget" value="${woodyStack.peek()}"/>
<jx:set var="widget" value="${contextWidget.getWidget(id)}"/>
<jx:choose>
<jx:when test="${widget.getSize() != null}"> <!-- repeater -->
<jx:set var="lastRow" value="${widget.getSize() - 1}"/>
<jx:forEach varStatus="loop" begin="0" end="${lastRow}">
<jx:set var="row" value="${widget.getRow(loop.index)}"/>
<jx:set var="ignored" value="${woodyStack.push(row)}"/>
${row.generateSaxFragment(cocoon.consumer, locale)}
<jx:evalBody/>
<jx:set var="ignored" value="${woodyStack.pop()}"/>
</jx:forEach>
</jx:when>
<jx:otherwise>
${widget.generateSaxFragment(cocoon.consumer, locale)}
<jx:evalBody/>
</jx:otherwise>
</jx:choose>
</jx:macro>
<jx:macro name="repeater-widget-label"
targetNamespace="http://apache.org/cocoon/woody/template/1.0">
<jx:parameter name="id"/>
<jx:parameter name="widget-id"/>
<jx:set var="contextWidget" value="${woodyStack.peek()}"/>
<jx:set var="repeater" value="contextWidget.getWidget(id)}"/>
${repeater.generateWidgetLabel(this['widget-id'], cocoon.consumer)}
</jx:macro>
<jx:macro name="widget-label"
targetNamespace="http://apache.org/cocoon/woody/template/1.0">
<jx:parameter name="id"/>
<jx:set var="contextWidget" value="${woodyStack.peek()}"/>
<jx:set var="widget" value="${contextWidget.getWidget(widget_id)}"/>
${widget.generateLabel(cocoon.consumer)}
</jx:macro>
<jx:macro name="repeater-size"
targetNamespace="http://apache.org/cocoon/woody/template/1.0">
<jx:parameter name="id"/>
<jx:set var="contextWidget" value="${woodyStack.peek()}"/>
<jx:set var="widget" value="${contextWidget.getWidget(id)}"/>
${widget.generateSize(cocoon.consumer)}
</jx:macro>
<jx:macro name="repeater-widget"
targetNamespace="http://apache.org/cocoon/woody/template/1.0"
xmlns:wt="http://apache.org/cocoon/woody/template/1.0">
<jx:parameter name="id"/>
<jx:set var="contextWidget" value="${woodyStack.peek()}"/>
<jx:set var="widget" value="${contextWidget.getWidget(id)}"/>
<jx:set var="lastRow" value="${widget.getSize() - 1}"/>
<jx:forEach varStatus="loop" begin="0" end="${lastRow}">
<jx:set var="row" value="${widget.getRow(loop.index)}"/>
<jx:set var="ignored" value="${woodyStack.push(row)}"/>
<jx:evalBody/>
<jx:set var="ignored" value="${woodyStack.pop()}"/>
</jx:forEach>
</jx:macro>
</jx:template>
