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]