ivelin 02/04/24 05:22:51
Modified: src/scratchpad/src/org/apache/cocoon/samples/xmlform
UserBean.java
src/scratchpad/src/org/apache/cocoon/transformation
XMLFormTransformer.java
src/scratchpad/src/org/apache/cocoon/xmlform Form.java
src/scratchpad/webapp/mount/xmlform/stylesheets
wizard2html.xsl
src/scratchpad/webapp/mount/xmlform/wizard confirm.xml
deployment.xml system.xml
Log:
Implemented XMLForm <group/> and <repeat/> tags.
Syntax and semantics borrowed from XForms.
Revision Changes Path
1.2 +25 -0
xml-cocoon2/src/scratchpad/src/org/apache/cocoon/samples/xmlform/UserBean.java
Index: UserBean.java
===================================================================
RCS file:
/home/cvs/xml-cocoon2/src/scratchpad/src/org/apache/cocoon/samples/xmlform/UserBean.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- UserBean.java 17 Apr 2002 17:59:15 -0000 1.1
+++ UserBean.java 24 Apr 2002 12:22:51 -0000 1.2
@@ -2,6 +2,8 @@
import java.util.Set;
import java.util.HashSet;
+import java.util.List;
+import java.util.ArrayList;
import org.w3c.dom.*;
import javax.xml.parsers.*;
@@ -28,6 +30,7 @@
private String liveUrl = "http://";
private boolean publish = true;
private Set roles = new HashSet();
+ private List favorites = new ArrayList();
private Node system;
@@ -35,6 +38,7 @@
{
initDomNode();
initRoleSet();
+ initFavorites();
}
public String getFirstName() {
@@ -181,6 +185,17 @@
roles = newRoles;
}
+
+ public List getFavorite()
+ {
+ return favorites;
+ }
+
+ public void setFavorite( List newFavorites )
+ {
+ favorites = newFavorites;
+ }
+
public void initRoleSet()
{
roles.add( "Geek" );
@@ -192,6 +207,16 @@
roles.add( "Development Manager" );
roles.add( "Executive" );
roles.add( "Heir of the Apache" );
+ }
+
+
+ public void initFavorites()
+ {
+ favorites.add( "http://xml.apache.org/cocoon" );
+ favorites.add( "http://jakarta.apache.org" );
+ favorites.add( "http://www.google.com" );
+ favorites.add( "http://www.slashdot.org" );
+ favorites.add( "http://www.yahoo.com" );
}
}
1.5 +389 -173
xml-cocoon2/src/scratchpad/src/org/apache/cocoon/transformation/XMLFormTransformer.java
Index: XMLFormTransformer.java
===================================================================
RCS file:
/home/cvs/xml-cocoon2/src/scratchpad/src/org/apache/cocoon/transformation/XMLFormTransformer.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- XMLFormTransformer.java 21 Apr 2002 18:59:38 -0000 1.4
+++ XMLFormTransformer.java 24 Apr 2002 12:22:51 -0000 1.5
@@ -63,6 +63,8 @@
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
+import org.w3c.dom.DocumentFragment;
+
import org.apache.log.Logger;
import org.apache.avalon.framework.parameters.Parameters;
@@ -75,6 +77,8 @@
import org.apache.cocoon.environment.Session;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.cocoon.transformation.AbstractTransformer;
+import org.apache.cocoon.transformation.AbstractSAXTransformer;
+import org.apache.cocoon.xml.dom.DOMStreamer;
import org.apache.cocoon.validation.Violation;
import org.apache.cocoon.xmlform.Form;
@@ -91,7 +95,10 @@
* @author: Torsten Curdt <[EMAIL PROTECTED]>
* @author: Ivelin Ivanov <[EMAIL PROTECTED]>
*/
-public class XMLFormTransformer extends AbstractTransformer {
+
+public class XMLFormTransformer extends AbstractSAXTransformer
+{
+
//implements Cacheable {
@@ -186,7 +193,6 @@
* </group>
* </pre>
*
- * @todo implement
*
*/
public final static String TAG_GROUP = "group";
@@ -198,24 +204,52 @@
* <input ref="." .../><html:br/>
* </repeat>
*
- * @todo implement
*
*/
public final static String TAG_REPEAT = "repeat";
+ /**
+ * this attribute is used within the
+ * <code>repeat</code> tag
+ * to represent an XPath node set selector from
+ * the underlying xmlform model.
+ */
+ public final static String TAG_REPEAT_ATTR_NODESET = "nodeset";
+
/**
- * Stack of nested references.
- * Used to track nested group and repeat tags.
+ * The current fully expanded reference
+ * in the form model.
*
*/
- private Stack nestedRefStack_ = null;
+ private String cannonicalRef = null;
+ /**
+ * Tracks the current repeat tag depth,
+ * when there is one in scope
+ */
+ private int repeatTagDepth = -1;
+
+ /**
+ * The nodeset selector string of the
+ * currently processed repeat tag (if any)
+ */
+ private String nodeset = null;
+
+
+ /**
+ * The flag annotating if the transformer is
+ * working on a repeat tag
+ */
+ private boolean isRecording = false;
- // the ref value of the current field
- // used by the violations tag
- private Stack refStack_ = null;
+
+ /**
+ * the ref value of the current field
+ * used by the violations tag
+ */
+ private Stack refStack = null;
/**
* Tracks the current depth of the XML tree
@@ -231,134 +265,217 @@
public final static String TAG_COMMON_ATTR_REF = "ref";
- private Map objectModel_;
- private Request request_;
- private Session session_;
-
// the current Form being processed
- private Form currentForm_;
+ private Form currentForm;
private Object value_;
- private boolean isRootElement_ = true;
- public void setup(SourceResolver resolver, Map objectModel, String source,
Parameters parameters) throws ProcessingException, SAXException, IOException
- {
- objectModel_ = objectModel;
- request_ = ObjectModelHelper.getRequest(objectModel);
- if (request_ == null)
+
+ /**
+ * Setup the next round.
+ * The instance variables are initialised.
+ * @param resolver The current SourceResolver
+ * @param objectModel The objectModel of the environment.
+ * @param src The value of the src attribute in the sitemap.
+ * @param par The parameters from the sitemap.
+ */
+ public void setup(
+ SourceResolver resolver,
+ Map objectModel,
+ String src,
+ Parameters par)
+ throws ProcessingException,
+ SAXException,
+ IOException
+ {
+ super.setup( resolver, objectModel, src, par );
+ if (request == null)
{
- getLogger().debug("no request object");
- throw new ProcessingException("no request object");
+ getLogger().debug("no request object");
+ throw new ProcessingException("no request object");
}
- session_ = request_.getSession(false);
-
- // init tracking parameters
- currentForm_ = null;
- nestedRefStack_ = new Stack();
- refStack_ = new Stack();
- currentTagDepth = 0;
+
+ // set the XMLForm namespace as the one
+ // this transformer is interested to work on
+ namespaceURI = NS;
+
+ // init tracking parameters
+ currentForm = null;
+ cannonicalRef = "";
+ refStack = new Stack();
+ currentTagDepth = 0;
+ repeatTagDepth = -1;
+ isRecording = false;
+ nodeset = null;
}
-
- public void startElement(String uri, String name, String raw, Attributes
attributes) throws SAXException
- {
- // track the tree depth
- ++currentTagDepth;
-
- if (isRootElement_)
+
+ /**
+ * Start processing elements of our namespace.
+ * This hook is invoked for each sax event with our namespace.
+ * @param uri The namespace of the element.
+ * @param name The local name of the element.
+ * @param raw The qualified name of the element.
+ * @param attr The attributes of the element.
+ */
+ public void startTransformingElement(String uri,
+ String name,
+ String raw,
+ Attributes attributes )
+ throws ProcessingException, IOException, SAXException
{
- AttributesImpl atts;
- if (attributes == null || attributes.getLength() == 0) {
- atts = new AttributesImpl();
- } else {
- atts = new AttributesImpl(attributes);
+ try
+ {
+ // avoid endless loop for elements in our namespace
+ // when outputting the elements themselves
+ this.ignoreHooksCount = 1;
+
+ if (this.getLogger().isDebugEnabled() == true)
+ {
+ this.getLogger().debug("BEGIN startTransformingElement uri=" + uri + ",
name=" + name + ", raw=" + raw + ", attr=" + attributes + ")");
+ }
+
+ // top level element in our namespace
+ // set an xmlns:xf="XMLForm namespace..." attribute
+ // to explicitely define the prefix to namespace binding
+ if (currentTagDepth == 0)
+ {
+ AttributesImpl atts;
+ if (attributes == null || attributes.getLength() == 0) {
+ atts = new AttributesImpl();
+ } else {
+ atts = new AttributesImpl(attributes);
+ }
+ atts.addAttribute( null, NS_PREFIX, XMLNS_PREFIX + ":" + NS_PREFIX,
"CDATA", NS);
+ attributes = atts;
}
- atts.addAttribute( NS, NS_PREFIX, XMLNS_PREFIX + ":" + NS_PREFIX, "CDATA",
NS);
- attributes = atts;
- isRootElement_ = false;
- }
-
- // if the element is not in the XMLForm namespace,
- // ignore it (forward the SAX event and return)
- if (!NS.equals(uri))
- {
- super.startElement(uri, name, raw, attributes);
- return;
- }
- // if this tag has a "ref" attribute, then
- // add its value to the refStack_
- String aref = attributes.getValue( TAG_COMMON_ATTR_REF );
- if ( aref != null )
- {
- Entry entry = new Entry( new Integer(currentTagDepth), aref);
- refStack_.push( entry );
- }
-
- // match tag name and apply transformation logic
- if (TAG_FORM.equals(name))
- {
- startElementForm( uri, name, raw, attributes );
- return;
- }
- else if ( TAG_OUTPUT.equals(name) )
- {
- startElementOutput( uri, name, raw, attributes );
- return;
- } // end if TAG_OUTPUT
- else if ( TAG_CAPTION.equals( name ) )
- {
- super.startElement(uri, name, raw, attributes);
- return;
- }
+ // track the tree depth
+ ++currentTagDepth;
+
+ // if within a repeat tag, keep recording
+ // when recording, nothing is actively processed
+ if (isRecording)
+ {
+ // just record the SAX event
+ super.startElement( uri, name, raw, attributes);
+ }
+ // when a new repeat tag is discovered
+ // start recording
+ // the repeat will be unrolled after the repeat tag ends
+ else if (TAG_REPEAT.equals( name) )
+ {
+ repeatTagDepth = currentTagDepth;
+ isRecording = true;
- // if the currentForm_ is still not available
- // then we can't process nested form tags
- if (currentForm_ == null) return;
+ // get the nodeset selector string
+ nodeset = attributes.getValue(TAG_REPEAT_ATTR_NODESET);
- if (TAG_INSERTVIOLATIONS.equals(name))
- {
- startElementViolations( uri, name, raw, attributes );
- } // end if TAG_INSERTVIOLATIONS
+ if (nodeset == null)
+ {
+ throw new SAXException( name + " element should provide a '" +
TAG_REPEAT_ATTR_NODESET + "' attribute" );
+ }
+
+ // open the repeat tag in the output document
+ super.startElement( uri, name, raw, attributes);
+ // and start recording its content
+ startRecording();
+ }
+ else // if not a repeat tag
+ {
+ // if this tag has a "ref" attribute, then
+ // add its value to the refStack
+ String aref = attributes.getValue( TAG_COMMON_ATTR_REF );
+ if ( aref != null )
+ {
+ // put on top of the ref stack the full ref
+ // append the new ref to the last stack top if not referencing the root
+ cannonicalRef = aref.startsWith ("/") ? aref : ( ((Entry)
refStack.peek()).getValue() + "/" + aref );
+ Entry entry = new Entry( new Integer(currentTagDepth), cannonicalRef);
+ refStack.push( entry );
+
+ // replace the ref attribute's value(path) with its full cannonical form
+ AttributesImpl atts = new AttributesImpl( attributes );
+ int refIdx = atts.getIndex ( TAG_COMMON_ATTR_REF );
+ atts.setValue ( refIdx, cannonicalRef );
+ attributes = atts;
+ }
- else if (
- TAG_TEXTBOX.equals(name) ||
- TAG_TEXTAREA.equals(name) ||
- TAG_PASSWORD.equals(name) ||
- TAG_SELECTBOOLEAN.equals(name) ||
- TAG_SELECTONE.equals(name))
- {
- startElementSimpleField( uri, name, raw, attributes, currentForm_ );
- }
- else if (TAG_SELECTMANY.equals(name))
- {
- //NYI - Not Yet Implemented
- throw new SAXException("tag selectMany Not Yet Implemented");
+ // match tag name and apply transformation logic
+ if (TAG_FORM.equals(name))
+ {
+ startElementForm( uri, name, raw, attributes );
+ }
+ else if ( TAG_OUTPUT.equals(name) )
+ {
+ startElementOutput( uri, name, raw, attributes );
+ } // end if TAG_OUTPUT
+ else if ( TAG_CAPTION.equals( name ) )
+ {
+ super.startElement( uri, name, raw, attributes);
+ this.ignoreHooksCount = 0;
+ }
+ // if the currentForm is still not available
+ // then we can't process nested form tags
+ else if (currentForm != null)
+ {
+ if (TAG_INSERTVIOLATIONS.equals(name))
+ {
+ startElementViolations( uri, name, raw, attributes );
+ } // end if TAG_INSERTVIOLATIONS
+
+ else if (
+ TAG_TEXTBOX.equals(name) ||
+ TAG_TEXTAREA.equals(name) ||
+ TAG_PASSWORD.equals(name) ||
+ TAG_SELECTBOOLEAN.equals(name) ||
+ TAG_SELECTONE.equals(name))
+ {
+ startElementSimpleField( uri, name, raw, attributes, currentForm );
+ }
+ else if (TAG_SELECTMANY.equals(name))
+ {
+ //NYI - Not Yet Implemented
+ throw new SAXException("tag selectMany Not Yet Implemented");
+ }
+ else if (
+ TAG_SUBMIT.equals(name) ||
+ TAG_CANCEL.equals(name) ||
+ TAG_RESET.equals(name) )
+ {
+ //NYI
+ super.startElement(uri, name, raw, attributes);
+ }
+ else
+ {
+ getLogger().error("unknown element [" + String.valueOf(name) + "]");
+ super.startElement(uri, name, raw, attributes);
+ }
+ }
+ } // end else (not a repeat tag)
}
- else if (
- TAG_SUBMIT.equals(name) ||
- TAG_CANCEL.equals(name) ||
- TAG_RESET.equals(name) )
+ finally
{
- //NYI
- super.startElement(uri, name, raw, attributes);
+ // reset ignore counter
+ this.ignoreHooksCount = 0;
}
- else
+
+
+ if (this.getLogger().isDebugEnabled() == true)
{
- getLogger().error("unknown element [" + String.valueOf(name) + "]");
- super.startElement(uri, name, raw, attributes);
+ this.getLogger().debug("END startTransformingElement");
}
-} // end of startElement
+ } // end of startTransformingElement
protected void startElementForm(String uri, String name, String raw, Attributes
attributes) throws SAXException
{
String id = attributes.getValue(TAG_FORM_ATTR_ID);
- if ( currentForm_ != null )
+ if ( currentForm != null )
{
- String error = "Form nodes should not be nested ! Current form [id=" +
currentForm_.getId() + "], nested form [id=" + String.valueOf(id) + "]";
+ String error = "Form nodes should not be nested ! Current form [id=" +
currentForm.getId() + "], nested form [id=" + String.valueOf(id) + "]";
getLogger().error( error );
throw new SAXException( error );
}
@@ -366,10 +483,10 @@
super.startElement(uri, name, raw, attributes);
// load up the referenced form
- currentForm_ = Form.lookup( objectModel_, id );
+ currentForm = Form.lookup( objectModel, id );
// if the form wasn't found, we're in trouble
- if (currentForm_ == null)
+ if (currentForm == null)
{
getLogger().error("could not find form [id=" + String.valueOf(id) + "]");
}
@@ -379,14 +496,14 @@
protected void startElementViolations(String uri, String name, String raw,
Attributes attributes) throws SAXException
{
- SortedSet violations = currentForm_.getViolations();
+ SortedSet violations = currentForm.getViolations();
// if there are no violations, there is nothing to show
if (violations == null) return;
// if we're immediately under the form tag
// and parent "ref" attribute is not available
- if ( refStack_.isEmpty () )
+ if ( refStack.isEmpty () )
{
for (Iterator it = violations.iterator(); it.hasNext();)
{
@@ -416,7 +533,7 @@
} // end if (currentRef_ == null)
else
{
- Entry entry = (Entry) refStack_.peek ();
+ Entry entry = (Entry) refStack.peek ();
String currentRef = (String) entry.getValue ();
Violation v = new Violation();
v.setPath( currentRef );
@@ -456,15 +573,15 @@
String formAttr = attributes.getValue( TAG_OUTPUT_ATTR_FORM );
if (formAttr == null)
{
- if (currentForm_ == null)
+ if (currentForm == null)
{
throw new SAXException( "When used outside of a form tag, the output
tag requires an '" + TAG_OUTPUT_ATTR_FORM + "' attribute" );
}
- form = currentForm_;
+ form = currentForm;
}
else
{
- form = Form.lookup( objectModel_, formAttr );
+ form = Form.lookup( objectModel, formAttr );
}
startElementSimpleField( uri, name, raw, attributes, form );
@@ -490,7 +607,7 @@
getLogger().debug("[" + String.valueOf( name ) + "] getting value from form
[id=" + form.getId() + ", ref=" + String.valueOf(ref) + "]");
- value_ = form.getValue(ref);
+ value_ = form.getValue( ref );
// we will only forward the SAX event once we know
// that the value of the tag is available
@@ -505,85 +622,184 @@
String v = String.valueOf( value_ );
super.characters(v.toCharArray(),0,v.length());
}
- super.endElement(uri, "value", NS_PREFIX + ":" + "value");
+ super.endElement( uri, "value", NS_PREFIX + ":" + "value" );
} // end of startElementSimpleField
- public void endElement(String uri, String name, String raw) throws SAXException
+ /**
+ * Start processing elements of our namespace.
+ * This hook is invoked for each sax event with our namespace.
+ * @param uri The namespace of the element.
+ * @param name The local name of the element.
+ * @param raw The qualified name of the element.
+ */
+ public void endTransformingElement(
+ String uri,
+ String name,
+ String raw)
+ throws ProcessingException, IOException, SAXException
{
- // track the tree depth
- --currentTagDepth;
-
- // keep the ref stack in synch with the tree navigation
- if ( !refStack_.isEmpty () )
- {
- Entry entry = (Entry) refStack_.peek();
- Integer refDepth = (Integer) entry.getKey ();
- if ( refDepth.intValue () > currentTagDepth )
- {
- refStack_.pop();
- }
- }
-
-
- // if the element is not in the XMLForm namespace,
- // forward the SAX event and return
- if (!NS.equals(uri))
+ if (this.getLogger().isDebugEnabled() == true)
{
- super.endElement(uri, name, raw);
- return;
+ this.getLogger().debug("BEGIN endTransformingElement uri=" + uri + ",
name=" + name + ", raw=" + raw + ")");
}
+
- if (TAG_INSERTVIOLATIONS.equals(name))
+ try
{
- // all violations were rendered completely in the startElement method
- }
- else if (TAG_FORM.equals(name))
- {
- // nullify currentForm_ since we'return getting out of its scope
- currentForm_ = null;
- super.endElement(uri, name, raw);
- }
- else if (TAG_OUTPUT.equals(name) ||
- TAG_TEXTBOX.equals(name) ||
- TAG_PASSWORD.equals(name) ||
- TAG_SELECTBOOLEAN.equals(name) ||
- TAG_SELECTONE.equals(name) )
+ // avoid endless loop for elements in our namespace
+ this.ignoreHooksCount = 1;
+
+
+ // when the end of an active repeat tag is reached
+ // stop recording, unroll the repeat tag content
+ // for each node in the node set,
+ // then close the repeat tag
+ if (TAG_REPEAT.equals( name) && (repeatTagDepth == currentTagDepth))
+ {
+ isRecording = false;
+ DocumentFragment docFragment = endRecording();
+ unrollRepeatTag( docFragment );
+ nodeset = null;
+ // close the repeat tag
+ super.endElement(uri, name, raw);
+ }
+ // if within a repeat tag, keep recording
+ // when recording, nothing is actively processed
+ else if (isRecording)
+ {
+ // just record the SAX event
+ super.endElement(uri, name, raw);
+ }
+ else // if not a repeat tag
{
- super.endElement(uri, name, raw);
+
+ // keep the ref stack in synch with the tree navigation
+ if ( !refStack.isEmpty () )
+ {
+ Entry entry = (Entry) refStack.peek();
+ Integer refDepth = (Integer) entry.getKey ();
+ if ( currentTagDepth <= refDepth.intValue () )
+ {
+ refStack.pop();
+ cannonicalRef = refStack.isEmpty () ? "" : (String)( (Entry)
(refStack.peek ()) ).getValue();
+ }
+ }
+
+
+ if (TAG_INSERTVIOLATIONS.equals(name))
+ {
+ // all violations were rendered completely in the startElement method
+ }
+ else if (TAG_FORM.equals(name))
+ {
+ // nullify currentForm since we're getting out of its scope
+ currentForm = null;
+ super.endElement(uri, name, raw);
+ }
+ else if (TAG_OUTPUT.equals(name) ||
+ TAG_TEXTBOX.equals(name) ||
+ TAG_PASSWORD.equals(name) ||
+ TAG_SELECTBOOLEAN.equals(name) ||
+ TAG_SELECTONE.equals(name) )
+ {
+ super.endElement(uri, name, raw);
+ }
+ else if (TAG_SELECTMANY.equals(name))
+ {
+ // NYI
+ }
+ else if (TAG_SUBMIT.equals(name))
+ {
+ super.endElement(uri, name, raw);
+ }
+ else if ( TAG_CAPTION.equals( name ) )
+ {
+ super.endElement(uri, name, raw);
+ }
+ else
+ {
+ getLogger().error("unknown element [" + String.valueOf(name) + "]");
+ super.endElement(uri, name, raw);
+ }
+ } // else (not in a recording tag)
}
- else if (TAG_SELECTMANY.equals(name))
+ finally
{
- // NYI
+ // reset ignore hooks counter
+ this.ignoreHooksCount = 0;
+
+ // track the tree depth
+ --currentTagDepth;
}
- else if (TAG_SUBMIT.equals(name))
+
+ if (this.getLogger().isDebugEnabled() == true)
{
- super.endElement(uri, name, raw);
- }
- else if ( TAG_CAPTION.equals( name ) )
- {
- super.endElement(uri, name, raw);
+ this.getLogger().debug("END endTransformingElement");
}
- else
+
+ } // end of endTransformingElement
+
+
+ /**
+ * Unroll the repeat tag.
+ * For each node in the repeat tag's nodeset selector result,
+ * render a <code>group</code> tag with a <code>ref</code>
+ * attribute which points to the location of the current node
+ * in the nodeset. Within each <code>group</code> tag,
+ * output the content of the repeat tag,
+ * by resolving all form model references within nested xmlform tags,
+ * relative to the <code>ref</code> attribute of the <code>group</code> element.
+ *
+ * @param docFragment the content of the repeat tag
+ * @param nodeset the nodeset selector string
+ */
+ protected void unrollRepeatTag( DocumentFragment docFragment )
+ throws SAXException
+ {
+ int oldIgnoreHooksCount = ignoreHooksCount;
+ try
{
- getLogger().error("unknown element [" + String.valueOf(name) + "]");
- super.endElement(uri, name, raw);
- }
- } // end of endElement
+ // reset ignore hooks counter
+ this.ignoreHooksCount = 0;
+ Collection locations = currentForm.locate( nodeset );
+ Iterator iter = locations.iterator();
+ // iterate over each node in the nodeset
+ while ( iter.hasNext() )
+ {
+ String nextNodeLocation = (String) iter.next ();
+ // set the ref attribute to point to the current node
+ AttributesImpl atts = new AttributesImpl();
+ atts.addAttribute( null, TAG_COMMON_ATTR_REF, TAG_COMMON_ATTR_REF, "CDATA",
nextNodeLocation);
- public void characters(char[] chars, int start, int len) throws SAXException {
+ super.startElement(NS, TAG_GROUP, NS_PREFIX + ":" + TAG_GROUP, atts);
+ if (value_ != null)
+ {
+ // stream back the recorder repeat content
+ DOMStreamer streamer = new DOMStreamer( this, this);
+ streamer.stream( docFragment );
+ }
- super.characters(chars, start, len);
+ super.endElement( NS, TAG_GROUP, NS_PREFIX + ":" + TAG_GROUP );
- }
+ }
+ }
+ finally
+ {
+ ignoreHooksCount = oldIgnoreHooksCount;
+ }
+ } // unrollRepeatTag
+
+
+
/**
- * refStack_ entry.
+ * refStack entry.
*/
private static class Entry implements Map.Entry {
Object key;
1.3 +30 -5
xml-cocoon2/src/scratchpad/src/org/apache/cocoon/xmlform/Form.java
Index: Form.java
===================================================================
RCS file:
/home/cvs/xml-cocoon2/src/scratchpad/src/org/apache/cocoon/xmlform/Form.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- Form.java 17 Apr 2002 17:59:15 -0000 1.2
+++ Form.java 24 Apr 2002 12:22:51 -0000 1.3
@@ -1,7 +1,7 @@
/*
- * $Header:
/home/cvs/xml-cocoon2/src/scratchpad/src/org/apache/cocoon/xmlform/Form.java,v 1.2
2002/04/17 17:59:15 ivelin Exp $
- * $Revision: 1.2 $
- * $Date: 2002/04/17 17:59:15 $
+ * $Header:
/home/cvs/xml-cocoon2/src/scratchpad/src/org/apache/cocoon/xmlform/Form.java,v 1.3
2002/04/24 12:22:51 ivelin Exp $
+ * $Revision: 1.3 $
+ * $Date: 2002/04/24 12:22:51 $
*
* ====================================================================
* The Apache Software License, Version 1.1
@@ -99,7 +99,7 @@
* NOTE: This class is NOT thread safe
*
* @author Ivelin Ivanov, [EMAIL PROTECTED]
- * @version $Revision: 1.2 $ $Date: 2002/04/17 17:59:15 $
+ * @version $Revision: 1.3 $ $Date: 2002/04/24 12:22:51 $
*/
public class Form
@@ -178,7 +178,7 @@
{
if ( model_ == null)
throw new IllegalStateException( "Form model not set" );
- Pointer pointer = jxcontext_.locateValue( xpath );
+ Pointer pointer = jxcontext_.locateValue( xpath );
setValue( pointer, value );
}
@@ -279,6 +279,31 @@
}
return property;
}
+
+
+ /**
+ * Resolves a nodeset selector
+ * into a list of concrete node locations
+ * @param xpath the nodeset selector
+ *
+ * @return a Set of XPath strings pointint to
+ * each nodeset satisfying the nodeset selector
+ *
+ */
+ public Set locate( String xpathSelector )
+ {
+ if (model_ == null)
+ throw new IllegalStateException( "Form model not set" );
+ Set nodeset = new HashSet();
+ Iterator iter = jxcontext_.locate( xpathSelector ).iterator ();
+ while ( iter.hasNext() )
+ {
+ Pointer nextPointer = (Pointer) iter.next();
+ nodeset.add ( nextPointer.asPath() );
+ }
+ return nodeset;
+ }
+
/**
1.3 +57 -28
xml-cocoon2/src/scratchpad/webapp/mount/xmlform/stylesheets/wizard2html.xsl
Index: wizard2html.xsl
===================================================================
RCS file:
/home/cvs/xml-cocoon2/src/scratchpad/webapp/mount/xmlform/stylesheets/wizard2html.xsl,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- wizard2html.xsl 19 Apr 2002 13:19:27 -0000 1.2
+++ wizard2html.xsl 24 Apr 2002 12:22:51 -0000 1.3
@@ -34,7 +34,8 @@
.error { color: #FF0000; }
.invalid { color: #FF0000; border: 2px solid #FF0000;
}
.info { color: #0000FF; border: 1px solid #0000FF; }
- .table { border: 1px inset #999999;border: 1px
inset #999999; width: 500px; }
+ .repeat { border: 0px inset #999999;border: 1px inset
#999999; width: 100%; }
+ .group { border: 0px inset #999999;border: 0px inset
#999999; width: 100%; }
.sub-table { border: none; }
.button { background-color: #FFFFFF; color: #000099; border: 1px
solid #666666; width: 70px; }
]]>
@@ -50,7 +51,7 @@
<xf:form method="post">
<xsl:copy-of select="@*" />
<br/><br/><br/><br/>
- <table align="center">
+ <table align="center" border="0">
<tr>
<td align="center" colspan="3">
<h1>
@@ -89,20 +90,7 @@
<xsl:choose>
<xsl:when test="name() = 'error'"/>
<xsl:when test="xf:*">
- <tr>
- <td>
- <xsl:value-of select="xf:caption" />
- </td>
- <td>
- <xsl:copy-of select="." />
- </td>
- <td class="{xf:violation[1]/@class}">
- <xsl:for-each select="xf:violation">
- * <xsl:value-of select="." />
- <br/>
- </xsl:for-each>
- </td>
- </tr>
+ <xsl:apply-templates select="."/>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
@@ -121,20 +109,61 @@
</xf:form>
</xsl:template>
- <xsl:template match="xf:output">
- <div align="center">
- <hr width="30%"/>
- <br/>
- <font size="-1">
- <code>
- <xsl:value-of select="xf:caption" /> :
- <xsl:copy-of select="." />
- </code>
- </font>
- <br/>
- </div>
+ <xsl:template match="xf:repeat">
+ <tr width="100%">
+ <td colspan="3" width="100%">
+ <table class="repeat">
+ <xsl:apply-templates select="*"/>
+ </table>
+ </td>
+ </tr>
+ </xsl:template>
+
+ <xsl:template match="xf:group">
+ <tr width="100%">
+ <td width="100%" colspan="2">
+ <table class="group" border="0">
+ <xsl:apply-templates select="*"/>
+ </table>
+ </td>
+ </tr>
+ </xsl:template>
+
+ <xsl:template match="xf:output[@form]">
+ <div align="center">
+ <hr width="30%"/>
+ <br/>
+ <font size="-1">
+ <code>
+ <xsl:value-of select="xf:caption" /> :
+ <xsl:copy-of select="." />
+ </code>
+ </font>
+ <br/>
+ </div>
</xsl:template>
+
+ <xsl:template match="xf:*">
+ <tr>
+ <td align="left">
+ <xsl:value-of select="xf:caption" />
+ </td>
+ <td>
+ <xsl:copy-of select="." />
+ </td>
+ <xsl:if test="xf:violation">
+ <td class="{xf:violation[1]/@class}" width="100%">
+ <xsl:for-each select="xf:violation">
+ * <xsl:value-of select="." />
+ <br/>
+ </xsl:for-each>
+ </td>
+ </xsl:if>
+ </tr>
+ </xsl:template>
+
+
<xsl:template match="*">
<xsl:copy-of select="." />
</xsl:template>
1.3 +11 -0
xml-cocoon2/src/scratchpad/webapp/mount/xmlform/wizard/confirm.xml
Index: confirm.xml
===================================================================
RCS file:
/home/cvs/xml-cocoon2/src/scratchpad/webapp/mount/xmlform/wizard/confirm.xml,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- confirm.xml 19 Apr 2002 13:19:27 -0000 1.2
+++ confirm.xml 24 Apr 2002 12:22:51 -0000 1.3
@@ -77,6 +77,17 @@
</xf:output>
+
+ <xf:group nodeset="" id="favorites_group">
+ <xf:caption>Favorite web sites</xf:caption>
+ <xf:repeat nodeset="/favorite[position() <= 3]" id="favorites">
+ <xf:output ref="." class="info">
+ <xf:caption>URL: </xf:caption>
+ </xf:output>
+ </xf:repeat>
+ </xf:group>
+
+
<!-- submit -->
<xf:submit id="prev" class="button">
1.3 +25 -0
xml-cocoon2/src/scratchpad/webapp/mount/xmlform/wizard/deployment.xml
Index: deployment.xml
===================================================================
RCS file:
/home/cvs/xml-cocoon2/src/scratchpad/webapp/mount/xmlform/wizard/deployment.xml,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- deployment.xml 19 Apr 2002 13:19:27 -0000 1.2
+++ deployment.xml 24 Apr 2002 12:22:51 -0000 1.3
@@ -35,6 +35,31 @@
<xf:caption>Publish</xf:caption>
</xf:selectBoolean>
+
+ <xf:group nodeset="" id="favorites_group">
+
+ <xf:caption>Favorite web sites</xf:caption>
+
+ <!--
+ repeat is a very powerful iterator tag,
+ because it iterates over a nodeset resulting from
+ a the nodeset selector attribute.
+ Very similar to xslt's for-each tag.
+
+ In this case we iterate over the top three favorite
+ web sites.
+ -->
+
+ <xf:repeat nodeset="/favorite[position() <= 3]" id="favorites">
+
+ <xf:textbox ref="." class="info">
+ <xf:caption>URL: </xf:caption>
+ </xf:textbox>
+
+ </xf:repeat>
+
+ </xf:group>
+
<xf:submit id="prev" class="button">
<xf:caption>Prev</xf:caption>
</xf:submit>
1.3 +104 -100
xml-cocoon2/src/scratchpad/webapp/mount/xmlform/wizard/system.xml
Index: system.xml
===================================================================
RCS file:
/home/cvs/xml-cocoon2/src/scratchpad/webapp/mount/xmlform/wizard/system.xml,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- system.xml 19 Apr 2002 13:19:27 -0000 1.2
+++ system.xml 24 Apr 2002 12:22:51 -0000 1.3
@@ -22,111 +22,115 @@
<xf:violations class="error"/>
</error>
- <xf:selectOne ref="/system/os">
- <xf:caption>OS</xf:caption>
- <xf:item id="unix">
- <xf:caption>Unix/Linux</xf:caption>
- <xf:value>Unix</xf:value>
- </xf:item>
- <xf:item id="mac">
- <xf:caption>Mac OS/X</xf:caption>
- <xf:value>Mac OS/X</xf:value>
- </xf:item>
- <xf:item id="win">
- <xf:caption>Windows 95/98/NT/2000</xf:caption>
- <xf:value>Windows</xf:value>
- </xf:item>
- <xf:item id="other">
- <xf:caption>Other</xf:caption>
- <xf:value>Other</xf:value>
- </xf:item>
- </xf:selectOne>
+ <xf:group ref="/system">
+
+ <xf:selectOne ref="os">
+ <xf:caption>OS</xf:caption>
+ <xf:item id="unix">
+ <xf:caption>Unix/Linux</xf:caption>
+ <xf:value>Unix</xf:value>
+ </xf:item>
+ <xf:item id="mac">
+ <xf:caption>Mac OS/X</xf:caption>
+ <xf:value>Mac OS/X</xf:value>
+ </xf:item>
+ <xf:item id="win">
+ <xf:caption>Windows 95/98/NT/2000</xf:caption>
+ <xf:value>Windows</xf:value>
+ </xf:item>
+ <xf:item id="other">
+ <xf:caption>Other</xf:caption>
+ <xf:value>Other</xf:value>
+ </xf:item>
+ </xf:selectOne>
- <xf:selectOne ref="/system/processor">
- <xf:caption>Processor</xf:caption>
- <xf:item>
- <xf:caption>AMD/Athlon</xf:caption>
- <xf:value>Athlon</xf:value>
- </xf:item>
- <xf:item>
- <xf:caption>AMD/Duron</xf:caption>
- <xf:value>Duron</xf:value>
- </xf:item>
- <xf:item>
- <xf:caption>Pentium Celeron</xf:caption>
- <xf:value>Celeron</xf:value>
- </xf:item>
- <xf:item>
- <xf:caption>Pentium III</xf:caption>
- <xf:value>p3</xf:value>
- </xf:item>
- <xf:item>
- <xf:caption>Pentium IV</xf:caption>
- <xf:value>p4</xf:value>
- </xf:item>
- <xf:item>
- <xf:caption>Other</xf:caption>
- <xf:value>other</xf:value>
- </xf:item>
- </xf:selectOne>
+ <xf:selectOne ref="processor">
+ <xf:caption>Processor</xf:caption>
+ <xf:item>
+ <xf:caption>AMD/Athlon</xf:caption>
+ <xf:value>Athlon</xf:value>
+ </xf:item>
+ <xf:item>
+ <xf:caption>AMD/Duron</xf:caption>
+ <xf:value>Duron</xf:value>
+ </xf:item>
+ <xf:item>
+ <xf:caption>Pentium Celeron</xf:caption>
+ <xf:value>Celeron</xf:value>
+ </xf:item>
+ <xf:item>
+ <xf:caption>Pentium III</xf:caption>
+ <xf:value>p3</xf:value>
+ </xf:item>
+ <xf:item>
+ <xf:caption>Pentium IV</xf:caption>
+ <xf:value>p4</xf:value>
+ </xf:item>
+ <xf:item>
+ <xf:caption>Other</xf:caption>
+ <xf:value>other</xf:value>
+ </xf:item>
+ </xf:selectOne>
- <xf:textbox ref="/system/@ram">
- <xf:caption>RAM</xf:caption>
- <xf:violations class="error"/>
- </xf:textbox>
+ <xf:textbox ref="@ram">
+ <xf:caption>RAM</xf:caption>
+ <xf:violations class="error"/>
+ </xf:textbox>
- <xf:selectOne ref="/system/servletEngine">
- <xf:caption>Servlet Engine</xf:caption>
- <xf:item>
- <xf:caption>Tomcat</xf:caption>
- <xf:value>Tomcat</xf:value>
- </xf:item>
- <xf:item>
- <xf:caption>Jetty</xf:caption>
- <xf:value>Jetty</xf:value>
- </xf:item>
- <xf:item>
- <xf:caption>Resin</xf:caption>
- <xf:value>Resin</xf:value>
- </xf:item>
- <xf:item>
- <xf:caption>Weblogic</xf:caption>
- <xf:value>weblogic</xf:value>
- </xf:item>
- <xf:item>
- <xf:caption>WebSphere</xf:caption>
- <xf:value>WebSphere</xf:value>
- </xf:item>
- <xf:item>
- <xf:caption>Other</xf:caption>
- <xf:value>other</xf:value>
- </xf:item>
- </xf:selectOne>
+ <xf:selectOne ref="servletEngine">
+ <xf:caption>Servlet Engine</xf:caption>
+ <xf:item>
+ <xf:caption>Tomcat</xf:caption>
+ <xf:value>Tomcat</xf:value>
+ </xf:item>
+ <xf:item>
+ <xf:caption>Jetty</xf:caption>
+ <xf:value>Jetty</xf:value>
+ </xf:item>
+ <xf:item>
+ <xf:caption>Resin</xf:caption>
+ <xf:value>Resin</xf:value>
+ </xf:item>
+ <xf:item>
+ <xf:caption>Weblogic</xf:caption>
+ <xf:value>weblogic</xf:value>
+ </xf:item>
+ <xf:item>
+ <xf:caption>WebSphere</xf:caption>
+ <xf:value>WebSphere</xf:value>
+ </xf:item>
+ <xf:item>
+ <xf:caption>Other</xf:caption>
+ <xf:value>other</xf:value>
+ </xf:item>
+ </xf:selectOne>
- <xf:selectOne ref="/system/javaVersion">
- <xf:caption>Java Version</xf:caption>
- <xf:item>
- <xf:caption>1.1</xf:caption>
- <xf:value>1.1</xf:value>
- </xf:item>
- <xf:item>
- <xf:caption>1.2</xf:caption>
- <xf:value>1.2</xf:value>
- </xf:item>
- <xf:item>
- <xf:caption>1.3</xf:caption>
- <xf:value>1.3</xf:value>
- </xf:item>
- <xf:item>
- <xf:caption>1.4</xf:caption>
- <xf:value>1.4</xf:value>
- </xf:item>
- <xf:item>
- <xf:caption>Other</xf:caption>
- <xf:value>Other</xf:value>
- </xf:item>
- </xf:selectOne>
+ <xf:selectOne ref="javaVersion">
+ <xf:caption>Java Version</xf:caption>
+ <xf:item>
+ <xf:caption>1.1</xf:caption>
+ <xf:value>1.1</xf:value>
+ </xf:item>
+ <xf:item>
+ <xf:caption>1.2</xf:caption>
+ <xf:value>1.2</xf:value>
+ </xf:item>
+ <xf:item>
+ <xf:caption>1.3</xf:caption>
+ <xf:value>1.3</xf:value>
+ </xf:item>
+ <xf:item>
+ <xf:caption>1.4</xf:caption>
+ <xf:value>1.4</xf:value>
+ </xf:item>
+ <xf:item>
+ <xf:caption>Other</xf:caption>
+ <xf:value>Other</xf:value>
+ </xf:item>
+ </xf:selectOne>
+ </xf:group>
+
<xf:submit id="prev" class="button">
<xf:caption>Prev</xf:caption>
</xf:submit>
----------------------------------------------------------------------
In case of troubles, e-mail: [EMAIL PROTECTED]
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]