You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by Dion Gillard <di...@gmail.com> on 2005/07/20 01:08:01 UTC

Re: svn commit: r219726 - in /jakarta/commons/proper/jelly/trunk: jelly-tags/xml/ jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/ jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/ src/java/org/apache/commons/jelly/ src/java/org/ap

Hi Paul,

could you make the <version> tag 1.2-SNAPSHOT instead of -dev? That
keeps it all consistent.

And how about an update to the changes.xml file?

On 7/20/05, polx@apache.org <po...@apache.org> wrote:
> Author: polx
> Date: Tue Jul 19 10:34:00 2005
> New Revision: 219726
> 
> URL: http://svn.apache.org/viewcvs?rev=219726&view=rev
> Log:
> Fixing treatment of namespaced-qualified attributes in XML taglib and
> in the xml-output.
> This fixes JELLY-213 and JELLY-214.
> paul
> 
> Added:
>     jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/ReplaceNamespaceTag.java
>     jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/attributeNameSpace.jelly
>     jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/attributeNameSpaceDefaultNS.jelly
>     jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/attributeNameSpaceDuplicatedNS.jelly
>     jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/attributeNameSpaceWithInnerElements.jelly
>     jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/elementWithNameSpace.jelly
>     jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/elementWithNameSpaceError.jelly
>     jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/namespaceReplace.jelly
>     jakarta/commons/proper/jelly/trunk/src/test/org/apache/commons/jelly/testStaticNamespacedAttributes.jelly
> Modified:
>     jakarta/commons/proper/jelly/trunk/jelly-tags/xml/project.xml
>     jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/AttributeTag.java
>     jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/ElementTag.java
>     jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/XMLTagLibrary.java
>     jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/TestXMLTags.java
>     jakarta/commons/proper/jelly/trunk/src/java/org/apache/commons/jelly/XMLOutput.java
>     jakarta/commons/proper/jelly/trunk/src/java/org/apache/commons/jelly/impl/StaticTag.java
>     jakarta/commons/proper/jelly/trunk/src/java/org/apache/commons/jelly/impl/StaticTagScript.java
>     jakarta/commons/proper/jelly/trunk/src/java/org/apache/commons/jelly/impl/TagScript.java
>     jakarta/commons/proper/jelly/trunk/src/java/org/apache/commons/jelly/parser/XMLParser.java
>     jakarta/commons/proper/jelly/trunk/src/test/org/apache/commons/jelly/TestCoreTags.java
>     jakarta/commons/proper/jelly/trunk/src/test/org/apache/commons/jelly/core/TestFileTag.java
> 
> Modified: jakarta/commons/proper/jelly/trunk/jelly-tags/xml/project.xml
> URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/jelly/trunk/jelly-tags/xml/project.xml?rev=219726&r1=219725&r2=219726&view=diff
> ==============================================================================
> --- jakarta/commons/proper/jelly/trunk/jelly-tags/xml/project.xml (original)
> +++ jakarta/commons/proper/jelly/trunk/jelly-tags/xml/project.xml Tue Jul 19 10:34:00 2005
> @@ -20,7 +20,7 @@
>    <extend>${basedir}/../tag-project.xml</extend>
>    <id>commons-jelly-tags-xml</id>
>    <name>commons-jelly-tags-xml</name>
> -  <currentVersion>1.1</currentVersion>
> +  <currentVersion>1.2-dev</currentVersion>
>    <package>org.apache.commons.jelly.tags.xml</package>
>    <description>The Jelly XML Tag Library</description>
>    <shortDescription>Commons Jelly XML Tag Library</shortDescription>
> @@ -37,6 +37,11 @@
>      </version>
>    </versions>
>    <dependencies>
> +    <dependency>
> +      <id>commons-jelly</id>
> +      <version>SNAPSHOT</version>
> +    </dependency>
> +
>      <!-- run time / in testing-->
> 
>      <dependency>
> 
> Modified: jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/AttributeTag.java
> URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/AttributeTag.java?rev=219726&r1=219725&r2=219726&view=diff
> ==============================================================================
> --- jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/AttributeTag.java (original)
> +++ jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/AttributeTag.java Tue Jul 19 10:34:00 2005
> @@ -26,6 +26,8 @@
>    * @version $Revision$
>    */
>  public class AttributeTag extends TagSupport {
> +     /** The namespace URI. */
> +    private String namespace;
> 
>      /** the name of the attribute. */
>      private String name;
> @@ -38,10 +40,11 @@
>      //-------------------------------------------------------------------------
>      public void doTag(XMLOutput output) throws JellyTagException {
>          ElementTag tag = (ElementTag) findAncestorWithClass( ElementTag.class );
> -        if ( tag == null ) {
> -            throw new JellyTagException( "<attribute> tag must be enclosed inside an <element> tag" );
> +        if (tag == null) {
> +            throw new JellyTagException(
> +                    "<attribute> tag must be enclosed inside an <element> tag" );
>          }
> -        tag.setAttributeValue( getName(), getBodyText( false ) );
> +        tag.setAttributeValue(getName(), getBodyText(false), getURI());
>      }
> 
>      // Properties
> @@ -53,10 +56,25 @@
>      public String getName() {
>          return name;
>      }
> +
>      /**
> -     * Sets the name of the attribute
> +     * Sets the name of the attribute.
>       */
>      public void setName(String name) {
>          this.name = name;
> +    }
> +
> +    /**
> +     * @return the namespace URI of the element
> +     */
> +    public String getURI() {
> +        return namespace;
> +    }
> +
> +    /**
> +     * Sets the namespace URI of the element
> +     */
> +    public void setURI(String namespace) {
> +        this.namespace = namespace;
>      }
>  }
> 
> Modified: jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/ElementTag.java
> URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/ElementTag.java?rev=219726&r1=219725&r2=219726&view=diff
> ==============================================================================
> --- jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/ElementTag.java (original)
> +++ jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/ElementTag.java Tue Jul 19 10:34:00 2005
> @@ -15,6 +15,7 @@
>   */
>  package org.apache.commons.jelly.tags.xml;
> 
> +import org.apache.commons.jelly.JellyException;
>  import org.apache.commons.jelly.JellyTagException;
>  import org.apache.commons.jelly.TagSupport;
>  import org.apache.commons.jelly.XMLOutput;
> @@ -22,8 +23,6 @@
>  import org.xml.sax.SAXException;
>  import org.xml.sax.helpers.AttributesImpl;
> 
> -import java.io.IOException;
> -
>  /** A tag to produce an XML element which can contain other attributes
>    * or elements like the <code>&lt;xsl:element&gt;</code> tag.
>    *
> @@ -32,16 +31,16 @@
>    */
>  public class ElementTag extends TagSupport {
> 
> -    /** The namespace URI */
> +    /** The namespace URI. */
>      private String namespace;
> 
> -    /** The qualified name */
> +    /** The qualified name. */
>      private String name;
> 
> -    /** The XML Attributes */
> +    /** The XML Attributes. */
>      private AttributesImpl attributes = new AttributesImpl();
> 
> -    /** flag set if attributes are output */
> +    /** flag set if attributes are output. */
>      private boolean outputAttributes;
> 
>      public ElementTag() {
> @@ -52,11 +51,12 @@
>       *
>       * @param name of the attribute
>       * @param value of the attribute
> -     * @throws JellyException if the start element has already been output.
> +     * @param uri namespace of the attribute
> +     * @throws JellyTagException if the start element has already been output.
>       *   Attributes must be set on the outer element before any content
>       *   (child elements or text) is output
>       */
> -    public void setAttributeValue( String name, String value ) throws JellyTagException {
> +    public void setAttributeValue(String name, String value, String uri) throws JellyTagException {
>          if (outputAttributes) {
>              throw new JellyTagException(
>                  "Cannot set the value of attribute: "
> @@ -67,13 +67,22 @@
>          // ### we'll assume that all attributes are in no namespace!
>          // ### this is severely limiting!
>          // ### we should be namespace aware
> -        int index = attributes.getIndex("", name);
> +        // NAMESPACE FIXED:
> +        int idx = name.indexOf(':');
> +        final String localName = (idx >= 0)
> +            ? name.substring(idx + 1)
> +            : name;
> +        final String nsUri = (uri != null)
> +            ? uri
> +            : "";
> +
> +        int index = attributes.getIndex(nsUri, localName);
>          if (index >= 0) {
>              attributes.removeAttribute(index);
>          }
>          // treat null values as no attribute
>          if (value != null) {
> -            attributes.addAttribute("", name, name, "CDATA", value);
> +            attributes.addAttribute(nsUri, localName, name, "CDATA", value);
>          }
>      }
> 
> @@ -107,22 +116,21 @@
>                  super.endElement(uri, localName, qName);
>              }
> 
> -            public void characters(char ch[], int start, int length) throws SAXException {
> +            public void characters(char[] ch, int start, int length) throws SAXException {
>                  initialize();
>                  super.characters(ch, start, length);
>              }
> 
> -            public void ignorableWhitespace(char ch[], int start, int length)
> +            public void ignorableWhitespace(char[] ch, int start, int length)
>                  throws SAXException {
>                  initialize();
>                  super.ignorableWhitespace(ch, start, length);
>              }
> 
>              public void objectData(Object object)
> -                throws SAXException
> -            {
> +                throws SAXException {
>                  initialize();
> -                super.objectData( object );
> +                super.objectData(object);
>              }
> 
>              public void processingInstruction(String target, String data)
> @@ -133,7 +141,7 @@
> 
>              /**
>               * Ensure that the outer start element is generated
> -             * before any content is output
> +             * before any content is output.
>               */
>              protected void initialize() throws SAXException {
>                  if (!outputAttributes) {
> 
> Added: jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/ReplaceNamespaceTag.java
> URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/ReplaceNamespaceTag.java?rev=219726&view=auto
> ==============================================================================
> --- jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/ReplaceNamespaceTag.java (added)
> +++ jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/ReplaceNamespaceTag.java Tue Jul 19 10:34:00 2005
> @@ -0,0 +1,128 @@
> +/*
> + * Copyright 2002,2004 The Apache Software Foundation.
> + *
> + * Licensed under the Apache License, Version 2.0 (the "License");
> + * you may not use this file except in compliance with the License.
> + * You may obtain a copy of the License at
> + *
> + *      http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +package org.apache.commons.jelly.tags.xml;
> +
> +import org.apache.commons.jelly.JellyTagException;
> +import org.apache.commons.jelly.MissingAttributeException;
> +import org.apache.commons.jelly.TagSupport;
> +import org.apache.commons.jelly.XMLOutput;
> +
> +import org.xml.sax.Attributes;
> +import org.xml.sax.SAXException;
> +import org.xml.sax.helpers.AttributesImpl;
> +
> +/**
> + * Replace namespace is a filter to change the namespace of any
> + * elemement attribute passing through it.
> + *
> + * @author Diogo Quintela <dq...@gmail.com>
> + */
> +public class ReplaceNamespaceTag extends TagSupport {
> +    private String fromNamespace;
> +    private String toNamespace;
> +
> +    public ReplaceNamespaceTag() {
> +    }
> +
> +    //  Tag interface
> +    //-------------------------------------------------------------------------
> +    public void doTag(XMLOutput output) throws MissingAttributeException, JellyTagException {
> +        final String fromURI = (fromNamespace != null) ? fromNamespace : "";
> +        final String toURI = (toNamespace != null) ? toNamespace : "";
> +        XMLOutput newOutput = output;
> +
> +        if (!toURI.equals(fromURI)) {
> +            newOutput = new XMLOutput(output) {
> +                public void startElement(String uri, String localName, String qName, Attributes atts)
> +                    throws SAXException {
> +                    super.startElement(replaceURI(uri), localName, qName, replaceURI(atts));
> +                }
> +
> +                public void endElement(String uri, String localName, String qName)
> +                    throws SAXException {
> +                    super.endElement(replaceURI(uri), localName, qName);
> +                }
> +
> +                public void startPrefixMapping(String prefix, String uri)
> +                    throws SAXException {
> +                    super.startPrefixMapping(prefix, replaceURI(uri));
> +                }
> +
> +                private String replaceURI(String uri) {
> +                    String newUri = uri;
> +
> +                    if (fromURI.equals((uri != null) ? uri : "")) {
> +                        newUri = toURI;
> +                    }
> +
> +                    return newUri;
> +                }
> +
> +                private Attributes replaceURI(Attributes atts) {
> +                    AttributesImpl newAttsImpl = new AttributesImpl();
> +
> +                    for (int i = 0; i < atts.getLength(); i++) {
> +                        // Normally attributes don't have namespaces
> +                        // But may have (only if on form prefix:attr) ?
> +                        // So, we'll only replace if needed
> +                        String QName = atts.getQName(i);
> +                        String newUri = atts.getURI(i);
> +                        int idx = QName.indexOf(':');
> +
> +                        if (idx >= 0) {
> +                            newUri = replaceURI(newUri);
> +                        }
> +
> +                        newAttsImpl.addAttribute(newUri, atts.getLocalName(i), atts.getQName(i),
> +                            atts.getType(i), atts.getValue(i));
> +                    }
> +
> +                    return newAttsImpl;
> +                }
> +            };
> +        }
> +
> +        invokeBody(newOutput);
> +    }
> +
> +    /**
> +     * @return the source namespace URI to replace
> +     */
> +    public String getFromURI() {
> +        return fromNamespace;
> +    }
> +
> +    /**
> +     * Sets the source namespace URI to replace.
> +     */
> +    public void setFromURI(String namespace) {
> +        this.fromNamespace = namespace;
> +    }
> +
> +    /**
> +     * @return the destination namespace URI to replace
> +     */
> +    public String getToURI() {
> +        return toNamespace;
> +    }
> +
> +    /**
> +     * Sets the destination namespace URI to replace.
> +     */
> +    public void setToURI(String namespace) {
> +        this.toNamespace = namespace;
> +    }
> +}
> \ No newline at end of file
> 
> Modified: jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/XMLTagLibrary.java
> URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/XMLTagLibrary.java?rev=219726&r1=219725&r2=219726&view=diff
> ==============================================================================
> --- jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/XMLTagLibrary.java (original)
> +++ jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/XMLTagLibrary.java Tue Jul 19 10:34:00 2005
> @@ -53,6 +53,7 @@
>          registerTag("expr", ExprTag.class);
>          registerTag("element", ElementTag.class);
>          registerTag("attribute", AttributeTag.class);
> +        registerTag("replaceNamespace", ReplaceNamespaceTag.class);
>          registerTag("copy", CopyTag.class);
>          registerTag("copyOf", CopyOfTag.class);
>          registerTag("comment", CommentTag.class);
> 
> Modified: jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/TestXMLTags.java
> URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/TestXMLTags.java?rev=219726&r1=219725&r2=219726&view=diff
> ==============================================================================
> --- jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/TestXMLTags.java (original)
> +++ jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/TestXMLTags.java Tue Jul 19 10:34:00 2005
> @@ -19,15 +19,20 @@
>  import java.io.FileInputStream;
>  import java.io.InputStream;
>  import java.io.StringWriter;
> +import java.util.HashMap;
>  import java.util.Iterator;
>  import java.util.List;
> +import java.util.Map;
> +import java.util.Set;
> 
> +import junit.framework.Assert;
>  import junit.framework.Test;
>  import junit.framework.TestCase;
>  import junit.framework.TestSuite;
>  import junit.textui.TestRunner;
> 
>  import org.apache.commons.jelly.JellyContext;
> +import org.apache.commons.jelly.JellyException;
>  import org.apache.commons.jelly.Script;
>  import org.apache.commons.jelly.XMLOutput;
>  import org.apache.commons.jelly.parser.XMLParser;
> @@ -36,6 +41,8 @@
>  import org.dom4j.Document;
>  import org.dom4j.DocumentHelper;
>  import org.dom4j.Node;
> +import org.dom4j.io.SAXContentHandler;
> +import org.dom4j.io.XMLWriter;
> 
>  /** Tests the parser, the engine and the XML tags
>    *
> @@ -84,57 +91,158 @@
>              log.debug("Evaluated script as...");
>              log.debug(text);
>          }
> -        assertEquals("Produces the correct output", "It works!", text);
> +        assertEquals("Should produce the correct output", "It works!", text);
> +    }
> +
> +    public void testElementWithNameSpace() throws Exception {
> +        String text = evaluteScriptAsText(testBaseDir + "/elementWithNameSpace.jelly");
> +        assertEquals("Should produce the correct output",
> +                "<env:Envelope "+
> +                "xmlns:env=\"http://schemas.xmlsoap.org/soap/envelope/\" "+
> +                "env:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"+
> +                "</env:Envelope>", text);
> +    }
> +
> +    public void testElementWithNameSpaceError() throws Exception {
> +        try {
> +            evaluteScriptAsText(testBaseDir + "/elementWithNameSpaceError.jelly");
> +            Assert.fail("We should have bailed out with an JellyException");
> +        } catch (JellyException jex) {
> +            assertTrue(jex.getReason().startsWith("Cannot set same prefix to diferent URI in same node"));
> +        }
> +    }
> +
> +    public void testNamespaceReplace() throws Exception {
> +        // For this test when we not set "ns" var with expected namespace, it
> +        // is expected to repeat the same two times
> +        String text = evaluteScriptAsText(testBaseDir + "/namespaceReplace.jelly");
> +        String repeatingText = "<test-subnode attr=\"test\"><test-anotherSubNode></test-anotherSubNode><test-anotherSubNodeAgain xmlns:other=\"\" other:abc=\"testValue\"></test-anotherSubNodeAgain></test-subnode>";
> +        assertEquals("Should produce the correct output",
> +                "<test-node xmlns:test=\"http://apache/testNS\" test:abc=\"testValue\">"+
> +                repeatingText + repeatingText +
> +                "</test-node>", text);
> +
> +        Map ctxVars = new HashMap();
> +        ctxVars.put("ns", "http://java/ns");
> +
> +        text = evaluteScriptAsText(testBaseDir + "/namespaceReplace.jelly", ctxVars);
> +
> +        String firstTrunk =
> +        "<test-subnode xmlns=\"\" attr=\"test\">" +
> +        "<test-anotherSubNode>" +
> +        "</test-anotherSubNode>" +
> +        "<test-anotherSubNodeAgain xmlns:other=\"http://java/ns\" xmlns=\"http://java/ns\" other:abc=\"testValue\">" +
> +        "</test-anotherSubNodeAgain>" +
> +        "</test-subnode>";
> +
> +        String secondTrunk =
> +            "<test-subnode attr=\"test\">" +
> +            "<test-anotherSubNode>" +
> +            "</test-anotherSubNode>" +
> +            "<test-anotherSubNodeAgain xmlns:other=\"http://java/ns\" other:abc=\"testValue\">" +
> +            "</test-anotherSubNodeAgain>" +
> +            "</test-subnode>";
> +
> +        System.out.println("TestXMLTags.testNamespaceReplace() text="+text);
> +        assertEquals("Should produce the correct output",
> +                "<test-node xmlns:test=\"http://apache/testNS\" xmlns=\"http://java/ns\" test:abc=\"testValue\">"+
> +                firstTrunk + secondTrunk +
> +                "</test-node>", text);
> +    }
> +
> +    public void testAttributeNameSpaceDuplicatedNS() throws Exception {
> +        try {
> +            evaluteScriptAsText(testBaseDir + "/attributeNameSpaceDuplicatedNS.jelly");
> +            Assert.fail("We should have bailed out with an JellyException");
> +        } catch (JellyException jex) {
> +            assertTrue(jex.getReason().startsWith("Cannot set same prefix to diferent URI in same node"));
> +        }
> +    }
> +
> +    public void testAttributeNameSpace() throws Exception {
> +        String text = evaluteScriptAsText(testBaseDir + "/attributeNameSpace.jelly");
> +        System.out.println(text);
> +        assertEquals("Should produce the correct output",
> +                "<top-node xmlns=\"abc\">"+
> +                "<test-node xmlns:test=\"http://apache/testNS\" xmlns=\"http://apache/trueNS\" test:abc=\"testValue\" abc2=\"testValue\" abc3=\"testValue\">"+
> +                "<test:test-subnode><node-at-same-ns-as-top xmlns=\"abc\">"+
> +                "</node-at-same-ns-as-top>"+
> +                "</test:test-subnode>"+
> +                "</test-node>"+
> +                "</top-node>", text);
> +    }
> +
> +    public void testAttributeNameSpaceDefaultNS() throws Exception {
> +        String text = evaluteScriptAsText(testBaseDir + "/attributeNameSpaceDefaultNS.jelly");
> +        System.out.println(text);
> +        assertEquals("Should produce the correct output",
> +                "<top-node>"+
> +                "<test-node xmlns:test=\"http://apache/testNS\" xmlns=\"http://apache/trueNS\" test:abc=\"testValue\" abc2=\"testValue\" abc3=\"testValue\">"+
> +                "<test:test-subnode><node-at-same-ns-as-top xmlns=\"\">"+
> +                "</node-at-same-ns-as-top>"+
> +                "</test:test-subnode>"+
> +                "</test-node>"+
> +                "</top-node>", text);
> +    }
> +
> +    public void testAttributeNameSpaceWithInnerElements() throws Exception {
> +        String text = evaluteScriptAsText(testBaseDir + "/attributeNameSpaceWithInnerElements.jelly");
> +        assertEquals("Should produce the correct output",
> +                "<test-node xmlns:test=\"http://apache/testNS\" test:abc=\"testValue\" abc2=\"testValue\" abc3=\"testValue\">"+
> +                "<test-sub-node xmlns:test2=\"http://apache/testNS\" xmlns:test3=\"http://apache/anotherNS\" test:abc=\"testValue\" test2:abc2=\"testValue\" test3:abc3=\"testValue\">"+
> +                "</test-sub-node>"+
> +                "</test-node>"
> +                , text);
>      }
> 
>      public void testTransform() throws Exception {
>          String text = evaluteScriptAsText(testBaseDir + "/transformExample.jelly");
> -        assertEquals("Produces the correct output", "It works!", text);
> +        assertEquals("Should produce the correct output", "It works!", text);
>      }
> 
>      public void testTransformAllInLine() throws Exception {
>          String text = evaluteScriptAsText(testBaseDir + "/transformExampleAllInLine.jelly");
> -        assertEquals("Produces the correct output", "It works!", text);
> +        assertEquals("Should produce the correct output", "It works!", text);
>      }
> 
>      public void testTransformParams() throws Exception {
>          String text = evaluteScriptAsText(testBaseDir + "/transformParamExample.jelly");
> -        assertEquals("Produces the correct output", "It works!", text);
> +        assertEquals("Should produce the correct output", "It works!", text);
>      }
> 
>      public void testTransformParamsInLine() throws Exception {
> 
>          String text = evaluteScriptAsText(testBaseDir + "/transformParamExample2.jelly");
> -        assertEquals("Produces the correct output", "It works!", text);
> +        assertEquals("Should produce the correct output", "It works!", text);
>      }
> 
>      public void testTransformSAXOutput() throws Exception {
>          String text = evaluteScriptAsText(testBaseDir + "/transformExampleSAXOutput.jelly");
> -        assertEquals("Produces the correct output", "It works!", text);
> +        assertEquals("Should produce the correct output", "It works!", text);
>      }
> 
>      public void testTransformSAXOutputNestedTransforms() throws Exception {
>          String text = evaluteScriptAsText(testBaseDir +
>              "/transformExampleSAXOutputNestedTransforms.jelly");
> -        assertEquals("Produces the correct output", "It works!", text);
> +        assertEquals("Should produce the correct output", "It works!", text);
>      }
> 
>      public void testTransformSchematron() throws Exception {
>          String text = evaluteScriptAsText(testBaseDir +
>              "/schematron/transformSchematronExample.jelly");
> -        assertEquals("Produces the correct output", "Report count=1:assert count=2", text);
> +        assertEquals("Should produce the correct output", "Report count=1:assert count=2", text);
>      }
> 
>      public void testTransformXmlVar() throws Exception {
>          String text = evaluteScriptAsText(testBaseDir +
>              "/transformExampleXmlVar.jelly");
> -        assertEquals("Produces the correct output", "It works!", text);
> +        assertEquals("Should produce the correct output", "It works!", text);
>      }
> 
>      public void testDoctype() throws Exception {
>          String text = evaluteScriptAsText(testBaseDir +
>              "/testDoctype.jelly");
> -        assertEquals("Produces the correct output", "<!DOCTYPE foo PUBLIC \"publicID\" \"foo.dtd\">\n<foo></foo>", text);
> +        assertEquals("Should produce the correct output", "<!DOCTYPE foo PUBLIC \"publicID\" \"foo.dtd\">\n<foo></foo>", text);
>      }
> 
>      public void runUnitTest(String name) throws Exception {
> @@ -172,7 +280,23 @@
>       * returns the whitespace trimmed output as text
>       */
>      protected String evaluteScriptAsText(String fileName) throws Exception {
> +        return evaluteScriptAsText(fileName, null);
> +    }
> +
> +    /**
> +     * Evaluates the script by the given file name and
> +     * returns the whitespace trimmed output as text
> +     */
> +    protected String evaluteScriptAsText(String fileName, Map ctxVars) throws Exception {
>          JellyContext context = new JellyContext();
> +        if (ctxVars != null) {
> +            Set keys = ctxVars.keySet();
> +            for (Iterator iterator = keys.iterator(); iterator.hasNext();) {
> +                String key = (String) iterator.next();
> +                Object value = ctxVars.get(key);
> +                context.setVariable(key, value);
> +            }
> +        }
> 
>          // allow scripts to refer to any resource inside this project
>          // using an absolute URI like /src/test/org/apache/foo.xml
> @@ -190,4 +314,49 @@
>          }
>          return text;
>      }
> +
> +    protected String evaluteScriptAsTextUsingSaxContentHandler(String fileName, Map ctxVars) throws Exception {
> +        org.dom4j.io.OutputFormat outputFormat = new org.dom4j.io.OutputFormat();
> +        outputFormat.setSuppressDeclaration(true);
> +        outputFormat.setNewlines(false);
> +        outputFormat.setIndent(false);
> +        outputFormat.setExpandEmptyElements(true);
> +        //outputFormat.setIndentSize(4);
> +
> +        StringWriter buffer = new StringWriter();
> +        XMLWriter xmlWriter = new XMLWriter(buffer, outputFormat);
> +        // xmlWriter.setEscapeText(false);
> +
> +        SAXContentHandler saxHandler = new SAXContentHandler();
> +        XMLOutput output = new XMLOutput(saxHandler);
> +
> +        // now run a script using a URL
> +        JellyContext context = new JellyContext();
> +        if (ctxVars != null) {
> +            Set keys = ctxVars.keySet();
> +            for (Iterator iterator = keys.iterator(); iterator.hasNext();) {
> +                String key = (String) iterator.next();
> +                Object value = ctxVars.get(key);
> +                context.setVariable(key, value);
> +            }
> +        }
> +
> +        // allow scripts to refer to any resource inside this project
> +        // using an absolute URI like /src/test/org/apache/foo.xml
> +        context.setRootURL(new File(".").toURL());
> +
> +        output.startDocument();
> +        context.runScript(new File(fileName), output);
> +        output.endDocument();
> +        xmlWriter.write(saxHandler.getDocument());
> +        xmlWriter.flush();
> +
> +        String text = buffer.toString().trim();
> +        if (log.isDebugEnabled()) {
> +            log.debug("Evaluated script as...");
> +            log.debug(text);
> +        }
> +        return text;
> +    }
> +
>  }
> 
> Added: jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/attributeNameSpace.jelly
> URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/attributeNameSpace.jelly?rev=219726&view=auto
> ==============================================================================
> --- jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/attributeNameSpace.jelly (added)
> +++ jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/attributeNameSpace.jelly Tue Jul 19 10:34:00 2005
> @@ -0,0 +1,15 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<j:jelly xmlns:j="jelly:core" xmlns:x="jelly:xml" xmlns="abc">
> +    <top-node>
> +        <x:element URI="http://apache/trueNS" name="test-node">
> +            <x:attribute URI="http://apache/testNS" name="test:abc" trim="true">testValue</x:attribute>
> +            <!-- attributes without ':' should not have namespace -->
> +            <x:attribute URI="http://apache/testNS" name="abc2" trim="true">testValue</x:attribute>
> +            <x:attribute name="abc3" trim="true">testValue</x:attribute>
> +            <x:element URI="http://apache/testNS" name="test:test-subnode">
> +                <node-at-same-ns-as-top/>
> +            </x:element>
> +        </x:element>
> +    </top-node>
> +</j:jelly>
> +
> 
> Added: jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/attributeNameSpaceDefaultNS.jelly
> URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/attributeNameSpaceDefaultNS.jelly?rev=219726&view=auto
> ==============================================================================
> --- jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/attributeNameSpaceDefaultNS.jelly (added)
> +++ jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/attributeNameSpaceDefaultNS.jelly Tue Jul 19 10:34:00 2005
> @@ -0,0 +1,15 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<j:jelly xmlns:j="jelly:core" xmlns:x="jelly:xml">
> +    <top-node>
> +        <x:element URI="http://apache/trueNS" name="test-node">
> +            <x:attribute URI="http://apache/testNS" name="test:abc" trim="true">testValue</x:attribute>
> +            <!-- attributes without ':' should not have namespace -->
> +            <x:attribute URI="http://apache/testNS" name="abc2" trim="true">testValue</x:attribute>
> +            <x:attribute name="abc3" trim="true">testValue</x:attribute>
> +            <x:element URI="http://apache/testNS" name="test:test-subnode">
> +                <node-at-same-ns-as-top/>
> +            </x:element>
> +        </x:element>
> +    </top-node>
> +</j:jelly>
> +
> 
> Added: jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/attributeNameSpaceDuplicatedNS.jelly
> URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/attributeNameSpaceDuplicatedNS.jelly?rev=219726&view=auto
> ==============================================================================
> --- jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/attributeNameSpaceDuplicatedNS.jelly (added)
> +++ jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/attributeNameSpaceDuplicatedNS.jelly Tue Jul 19 10:34:00 2005
> @@ -0,0 +1,8 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<j:jelly xmlns:j="jelly:core" xmlns:x="jelly:xml">
> +    <x:element name="test-node">
> +        <x:attribute URI="http://apache/testNS" name="test:abc" trim="true">testValue</x:attribute>
> +        <x:attribute URI="http://apache/anotherNS" name="test:abc2" trim="true">testValue</x:attribute>
> +    </x:element>
> +</j:jelly>
> +
> 
> Added: jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/attributeNameSpaceWithInnerElements.jelly
> URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/attributeNameSpaceWithInnerElements.jelly?rev=219726&view=auto
> ==============================================================================
> --- jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/attributeNameSpaceWithInnerElements.jelly (added)
> +++ jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/attributeNameSpaceWithInnerElements.jelly Tue Jul 19 10:34:00 2005
> @@ -0,0 +1,16 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<j:jelly xmlns:j="jelly:core" xmlns:x="jelly:xml">
> +    <x:element name="test-node">
> +        <x:attribute URI="http://apache/testNS" name="test:abc" trim="true">testValue</x:attribute>
> +        <!-- attributes without ':' should not have namespace -->
> +        <x:attribute URI="http://apache/testNS" name="abc2" trim="true">testValue</x:attribute>
> +        <x:attribute name="abc3" trim="true">testValue</x:attribute>
> +
> +        <x:element name="test-sub-node">
> +            <x:attribute URI="http://apache/testNS" name="test:abc" trim="true">testValue</x:attribute>
> +            <x:attribute URI="http://apache/testNS" name="test2:abc2" trim="true">testValue</x:attribute>
> +            <x:attribute URI="http://apache/anotherNS" name="test3:abc3" trim="true">testValue</x:attribute>
> +        </x:element>
> +    </x:element>
> +</j:jelly>
> +
> 
> Added: jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/elementWithNameSpace.jelly
> URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/elementWithNameSpace.jelly?rev=219726&view=auto
> ==============================================================================
> --- jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/elementWithNameSpace.jelly (added)
> +++ jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/elementWithNameSpace.jelly Tue Jul 19 10:34:00 2005
> @@ -0,0 +1,10 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<j:jelly xmlns:j="jelly:core" xmlns:x="jelly:xml">
> +    <x:element URI="http://schemas.xmlsoap.org/soap/envelope/" name="env:Envelope">
> +        <x:attribute URI="http://schemas.xmlsoap.org/soap/envelope/"
> +                     name="env:encodingStyle" trim="true">
> +            http://schemas.xmlsoap.org/soap/encoding/
> +        </x:attribute>
> +    </x:element>
> +</j:jelly>
> +
> 
> Added: jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/elementWithNameSpaceError.jelly
> URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/elementWithNameSpaceError.jelly?rev=219726&view=auto
> ==============================================================================
> --- jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/elementWithNameSpaceError.jelly (added)
> +++ jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/elementWithNameSpaceError.jelly Tue Jul 19 10:34:00 2005
> @@ -0,0 +1,9 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<j:jelly xmlns:j="jelly:core" xmlns:x="jelly:xml">
> +    <x:element URI="http://schemas.xmlsoap.org/soap/envelope/" name="env:Envelope">
> +        <x:attribute name="env:encodingStyle" trim="true">
> +            http://schemas.xmlsoap.org/soap/encoding/
> +        </x:attribute>
> +    </x:element>
> +</j:jelly>
> +
> 
> Added: jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/namespaceReplace.jelly
> URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/namespaceReplace.jelly?rev=219726&view=auto
> ==============================================================================
> --- jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/namespaceReplace.jelly (added)
> +++ jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/namespaceReplace.jelly Tue Jul 19 10:34:00 2005
> @@ -0,0 +1,23 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<j:jelly xmlns:j="jelly:core" xmlns:x="jelly:xml">
> +    <x:element URI="${ns}" name="test-node">
> +        <x:attribute URI="http://apache/testNS" name="test:abc" trim="true">testValue</x:attribute>
> +
> +        <test-subnode attr="test">
> +            <test-anotherSubNode />
> +            <x:element URI="${ns}" name="test-anotherSubNodeAgain">
> +                <x:attribute URI="${ns}" name="other:abc" trim="true">testValue</x:attribute>
> +            </x:element>
> +        </test-subnode>
> +
> +        <x:replaceNamespace toURI="${ns}">
> +            <test-subnode attr="test">
> +                <test-anotherSubNode />
> +                <x:element URI="${ns}" name="test-anotherSubNodeAgain">
> +                    <x:attribute URI="${ns}" name="other:abc" trim="true">testValue</x:attribute>
> +                </x:element>
> +            </test-subnode>
> +        </x:replaceNamespace>
> +    </x:element>
> +</j:jelly>
> +
> 
> Modified: jakarta/commons/proper/jelly/trunk/src/java/org/apache/commons/jelly/XMLOutput.java
> URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/jelly/trunk/src/java/org/apache/commons/jelly/XMLOutput.java?rev=219726&r1=219725&r2=219726&view=diff
> ==============================================================================
> --- jakarta/commons/proper/jelly/trunk/src/java/org/apache/commons/jelly/XMLOutput.java (original)
> +++ jakarta/commons/proper/jelly/trunk/src/java/org/apache/commons/jelly/XMLOutput.java Tue Jul 19 10:34:00 2005
> @@ -20,6 +20,11 @@
>  import java.io.OutputStream;
>  import java.io.UnsupportedEncodingException;
>  import java.io.Writer;
> +import java.util.ArrayList;
> +import java.util.HashMap;
> +import java.util.Iterator;
> +import java.util.List;
> +import java.util.Map;
> 
>  import org.apache.commons.logging.Log;
>  import org.apache.commons.logging.LogFactory;
> @@ -44,29 +49,35 @@
>  public class XMLOutput implements ContentHandler, LexicalHandler {
> 
>      protected static final String[] LEXICAL_HANDLER_NAMES =
> -        {
> -            "http://xml.org/sax/properties/lexical-handler",
> -            "http://xml.org/sax/handlers/LexicalHandler" };
> +     {
> +        "http://xml.org/sax/properties/lexical-handler",
> +        "http://xml.org/sax/handlers/LexicalHandler" };
> 
> -    /** empty attributes */
> +    /** Empty attributes. */
>      private static final Attributes EMPTY_ATTRIBUTES = new AttributesImpl();
> 
>      /** The Log to which logging calls will be made. */
>      private static final Log log = LogFactory.getLog(XMLOutput.class);
> 
> -    /** the default for escaping of text */
> +    /** the default for escaping of text. */
>      private static final boolean DEFAULT_ESCAPE_TEXT = false;
> 
> -    /** The SAX ContentHandler that output goes to */
> +    /** The SAX ContentHandler that output goes to. */
>      private ContentHandler contentHandler;
> 
> -    /** The SAX LexicalHandler that output goes to */
> +    /** The SAX LexicalHandler that output goes to. */
>      private LexicalHandler lexicalHandler;
> 
> +    /** Stack of kown namespaces. */
> +    private NamespaceStack namespaceStack = new NamespaceStack();
> 
>      public XMLOutput() {
>      }
> 
> +    /** The XML-output will relay the SAX events to the indicated
> +     * contentHandler.
> +     * @param contentHandler
> +     */
>      public XMLOutput(ContentHandler contentHandler) {
>          this.contentHandler = contentHandler;
>          // often classes will implement LexicalHandler as well
> @@ -75,6 +86,11 @@
>          }
>      }
> 
> +    /** The XML-output will relay the SAX events to the indicated
> +     * content-handler lexical-handler.
> +     * @param contentHandler
> +     * @param lexicalHandler
> +     */
>      public XMLOutput(
>          ContentHandler contentHandler,
>          LexicalHandler lexicalHandler) {
> @@ -92,16 +108,25 @@
>      }
> 
>      /**
> -     * Provides a useful hook that implementations can use to close the
> -     * underlying OutputStream or Writer
> +     * Provides a useful hook that implementations
> +     * can use to close the
> +     * underlying OutputStream or Writer.
> +     *
> +     * @throws IOException
>       */
>      public void close() throws IOException {
>      }
> 
> +    /** Flushes the underlying stream if {@link XMLWriter}
> +     * or {@link XMLOutput}.
> +     *
> +     * @throws IOException
> +     */
>      public void flush() throws IOException {
> -        if( contentHandler instanceof XMLWriter )
> -        {
> +        if (contentHandler instanceof XMLWriter) {
>              ((XMLWriter)contentHandler).flush();
> +        } else if (contentHandler instanceof XMLOutput) {
> +            ((XMLOutput)contentHandler).flush();
>          }
>      }
> 
> @@ -109,7 +134,7 @@
>      //-------------------------------------------------------------------------
> 
>      /**
> -     * Creates an XMLOutput from an existing SAX XMLReader
> +     * Creates an XMLOutput from an existing SAX XMLReader.
>       */
>      public static XMLOutput createXMLOutput(XMLReader xmlReader) {
>          XMLOutput output = new XMLOutput(xmlReader.getContentHandler());
> @@ -122,10 +147,11 @@
>                      output.setLexicalHandler((LexicalHandler) value);
>                      break;
>                  }
> -            }
> -            catch (Exception e) {
> +            } catch (Exception e) {
>                  // ignore any unsupported-operation exceptions
> -                if (log.isDebugEnabled()) log.debug("error setting lexical handler properties", e);
> +                if (log.isDebugEnabled()) {
> +                    log.debug("error setting lexical handler properties", e);
> +                }
>              }
>          }
>          return output;
> @@ -145,10 +171,9 @@
>       *
>       * @param writer is the writer to output to
>       * @param escapeText is whether or not text output will be escaped. This must be true
> -     * if the underlying output is XML or could be false if the underlying output is textual.
> +     *   if the underlying output is XML or could be false if the underlying output is textual.
>       */
> -    public static XMLOutput createXMLOutput(Writer writer, boolean escapeText)
> -    {
> +    public static XMLOutput createXMLOutput(Writer writer, boolean escapeText) {
>          XMLWriter xmlWriter = new XMLWriter(writer);
>          xmlWriter.setEscapeText(escapeText);
>          return createXMLOutput(xmlWriter);
> @@ -169,8 +194,11 @@
>       * @param out is the output stream to write
>       * @param escapeText is whether or not text output will be escaped. This must be true
>       * if the underlying output is XML or could be false if the underlying output is textual.
> +     * @throws UnsupportedEncodingException if the underlying write could not
> +     *   be created.
>       */
> -    public static XMLOutput createXMLOutput(OutputStream out, boolean escapeText) throws UnsupportedEncodingException {
> +    public static XMLOutput createXMLOutput(OutputStream out, boolean escapeText)
> +            throws UnsupportedEncodingException {
>          XMLWriter xmlWriter = new XMLWriter(out);
>          xmlWriter.setEscapeText(escapeText);
>          return createXMLOutput(xmlWriter);
> @@ -193,7 +221,7 @@
>      /**
>       * Outputs the given String as a piece of valid text in the
>       * XML event stream.
> -     * Any special XML characters should be properly escaped.
> +     * Any special XML characters should come out properly escaped.
>       */
>      public void write(String text) throws SAXException {
>          char[] ch = text.toCharArray();
> @@ -212,7 +240,7 @@
>      }
> 
>      /**
> -     * Outputs a comment to the XML stream
> +     * Outputs a comment to the XML stream.
>       */
>      public void writeComment(String text) throws SAXException {
>          char[] ch = text.toCharArray();
> @@ -220,21 +248,24 @@
>      }
> 
>      /**
> -     * Helper method for outputting a start element event for an element in no namespace
> +     * Helper method for outputting a start element event
> +     * for an element in no namespace.
>       */
>      public void startElement(String localName) throws SAXException {
>          startElement("", localName, localName, EMPTY_ATTRIBUTES);
>      }
> 
>      /**
> -     * Helper method for outputting a start element event for an element in no namespace
> +     * Helper method for outputting a start element event
> +     * for an element in no namespace.
>       */
>      public void startElement(String localName, Attributes attributes) throws SAXException {
>          startElement("", localName, localName, attributes);
>      }
> 
>      /**
> -     * Helper method for outputting an end element event for an element in no namespace
> +     * Helper method for outputting an end element event
> +     * for an element in no namespace.
>       */
>      public void endElement(String localName) throws SAXException {
>          endElement("", localName, localName);
> @@ -344,7 +375,9 @@
>       * @see #startElement
>       */
>      public void startPrefixMapping(String prefix, String uri) throws SAXException {
> -        contentHandler.startPrefixMapping(prefix, uri);
> +        namespaceStack.pushNamespace(prefix, uri);
> +        // contentHandler.startPrefixMapping(prefix, uri) will be called if needed
> +        // in pushNamespace
>      }
> 
>      /**
> @@ -364,7 +397,9 @@
>       * @see #endElement
>       */
>      public void endPrefixMapping(String prefix) throws SAXException {
> -        contentHandler.endPrefixMapping(prefix);
> +        namespaceStack.popNamespace(prefix);
> +        // End prefix mapping was already called after endElement
> +        // contentHandler.endPrefixMapping(prefix);
>      }
> 
>      /**
> @@ -435,7 +470,28 @@
>          String qName,
>          Attributes atts)
>          throws SAXException {
> +
> +        int idx = qName.indexOf(':');
> +        String attNsPrefix = "";
> +        if (idx >= 0) {
> +            attNsPrefix = qName.substring(0, idx);
> +        }
> +        namespaceStack.pushNamespace(attNsPrefix, uri);
> +        for (int i = 0; i < atts.getLength(); i++) {
> +            String attQName = atts.getQName(i);
> +            // An attribute only has an namespace if has a prefix
> +            // If not, stays in namespace of containing node
> +            idx = attQName.indexOf(':');
> +            if (idx >= 0) {
> +                attNsPrefix = attQName.substring(0, idx);
> +                String attUri = atts.getURI(i);
> +                namespaceStack.pushNamespace(attNsPrefix, attUri);
> +            }
> +        }
> +
>          contentHandler.startElement(uri, localName, qName, atts);
> +        // Inform namespaceStack of a new depth
> +        namespaceStack.increaseLevel();
>      }
> 
>      /**
> @@ -462,6 +518,9 @@
>      public void endElement(String uri, String localName, String qName)
>          throws SAXException {
>          contentHandler.endElement(uri, localName, qName);
> +        // Inform namespaceStack to return to previous depth
> +        namespaceStack.decreaseLevel();
> +        namespaceStack.popNamespaces();
>      }
> 
>      /**
> @@ -507,7 +566,7 @@
>       * @see #ignorableWhitespace
>       * @see org.xml.sax.Locator
>       */
> -    public void characters(char ch[], int start, int length) throws SAXException {
> +    public void characters(char[] ch, int start, int length) throws SAXException {
>          contentHandler.characters(ch, start, length);
>      }
> 
> @@ -535,7 +594,7 @@
>       *            wrapping another exception.
>       * @see #characters
>       */
> -    public void ignorableWhitespace(char ch[], int start, int length)
> +    public void ignorableWhitespace(char[] ch, int start, int length)
>          throws SAXException {
>          contentHandler.ignorableWhitespace(ch, start, length);
>      }
> @@ -855,4 +914,127 @@
>          return answer;
>      }
> 
> +    private final class NamespaceStack {
> +        /** A list of maps: Each map contains prefix->uri mapping */
> +        private List nsStack;
> +
> +        private NamespaceStack() {
> +            this.nsStack = new ArrayList();
> +            this.nsStack.add(new HashMap());
> +        }
> +
> +        private boolean isRootNodeDefaultNs(String prefix, String uri) {
> +            return ("".equals(prefix) && "".equals(uri) && nsStack.size() == 1);
> +        }
> +
> +        public void pushNamespace(String prefix, String uri) throws SAXException {
> +            Map prefixUriMap;
> +
> +            if (prefix == null) {
> +                prefix = "";
> +            }
> +            if (uri == null) {
> +                uri = "";
> +            }
> +
> +            if ("xml".equals(prefix)) {
> +                // We should ignore setting 'xml' prefix
> +                // As declared in java of ContentHandler#startPrefixMapping
> +                return;
> +            }
> +
> +
> +            // Lets find out if we already declared this same prefix,
> +            // if not declare in current depth map (the first of list)
> +            // and call contentHandler.startPrefixMapping(prefix, uri);
> +            boolean isNew = true;
> +            for (Iterator iter = nsStack.iterator(); iter.hasNext();) {
> +                prefixUriMap = (Map) iter.next();
> +                if (prefixUriMap.containsKey(prefix)) {
> +                    if (uri.equals(prefixUriMap.get(prefix))) {
> +                        // Its an active namespace already
> +                        // System.out.println(">>>"+XMLOutput.this.hashCode()+">NamespaceStack.pushNamespace() IS NOT NEW prefix="+prefix+",uri="+uri);
> +                        isNew = false;
> +                    }
> +                    // We found it in stack
> +                    // If it was exacly the same, we won't bother
> +                    break;
> +                }
> +            }
> +
> +            if (isNew) {
> +                // not declared sometime before
> +                prefixUriMap = (Map) nsStack.get(0); // Current depth map
> +                // Sanity check: Don't let two prefixes for diferent uris in
> +                // same depth
> +                if (prefixUriMap.containsKey(prefix)) {
> +                    if (!uri.equals(prefixUriMap.get(prefix))) {
> +                        throw new SAXException("Cannot set same prefix to diferent URI in same node: trying to add prefix \""
> +                                + prefix + "\" for uri \""+uri+"\" whereas the declared ones are " + prefixUriMap);
> +                    }
> +                } else {
> +                    prefixUriMap.put(prefix, uri);
> +
> +                    // To avoid setting xmlns="" for top node (not very nice :D)
> +                    // We need to especificaly check this condition
> +                    if (!isRootNodeDefaultNs(prefix, uri)) {
> +//                        System.out.println(">>>"+XMLOutput.this.hashCode()+">NamespaceStack.pushNamespace() prefix="+prefix+",uri="+uri);
> +                        contentHandler.startPrefixMapping(prefix, uri);
> +                    }
> +                }
> +            }
> +        }
> +
> +        public void popNamespaces() throws SAXException {
> +            Map prefixUriMap = (Map)nsStack.get(0);
> +            for (Iterator iter = prefixUriMap.keySet().iterator();iter.hasNext();) {
> +                String prefix = (String)iter.next();
> +                String uri = (String) prefixUriMap.get(prefix);
> +                iter.remove();
> +
> +                // If we havent called startPrefixMapping for root node if we wanted to avoid xmlns=""
> +                // We aren't going to call endPrefixMapping neither
> +                if (!isRootNodeDefaultNs(prefix, uri)) {
> +//                    System.out.println(">>>"+XMLOutput.this.hashCode()+">NamespaceStack.popNamespaces() prefix="+prefix);
> +                    contentHandler.endPrefixMapping(prefix);
> +                }
> +            }
> +        }
> +
> +        public void popNamespace(String prefix) throws SAXException {
> +            Map prefixUriMap = (Map)nsStack.get(0);
> +
> +            if (prefix == null) {
> +                prefix = "";
> +            }
> +
> +            if ("xml".equals(prefix)) {
> +                // We should ignore setting 'xml' prefix
> +                // As declared in java of ContentHandler#startPrefixMapping
> +                return;
> +            }
> +
> +            if (prefixUriMap.containsKey(prefix)) {
> +                String uri = (String) prefixUriMap.get(prefix);
> +                prefixUriMap.remove(prefix);
> +                // If we havent called startPrefixMapping for root node if we wanted to avoid xmlns=""
> +                // We aren't going to call endPrefixMapping neither
> +                if (!isRootNodeDefaultNs(prefix, uri)) {
> +//                    System.out.println(">>>"+XMLOutput.this.hashCode()+">NamespaceStack.popNamespace() prefix="+prefix);
> +                    contentHandler.endPrefixMapping(prefix);
> +                }
> +            }/* else {
> +                improper nesting ? or already removed in popNamespaces
> +            }
> +            */
> +        }
> +
> +        public void decreaseLevel() {
> +            nsStack.remove(0);
> +        }
> +
> +        public void increaseLevel() {
> +            nsStack.add(0, new HashMap());
> +        }
> +    }
>  }
> 
> Modified: jakarta/commons/proper/jelly/trunk/src/java/org/apache/commons/jelly/impl/StaticTag.java
> URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/jelly/trunk/src/java/org/apache/commons/jelly/impl/StaticTag.java?rev=219726&r1=219725&r2=219726&view=diff
> ==============================================================================
> --- jakarta/commons/proper/jelly/trunk/src/java/org/apache/commons/jelly/impl/StaticTag.java (original)
> +++ jakarta/commons/proper/jelly/trunk/src/java/org/apache/commons/jelly/impl/StaticTag.java Tue Jul 19 10:34:00 2005
> @@ -69,6 +69,15 @@
>          }
>      }
> 
> +    public void setAttribute(String name, String prefix, String nsURI, Object value) {
> +        if(value==null)
> +            return;
> +        if(prefix!=null && prefix.length()>0)
> +            attributes.addAttribute(nsURI,name,prefix+":"+name,"CDATA",value.toString());
> +        else
> +            attributes.addAttribute("",name,name,"CDATA",value.toString());
> +    }
> +
>      // DynaTag interface
>      //-------------------------------------------------------------------------
>      public void setAttribute(String name, Object value) throws JellyTagException {
> 
> Modified: jakarta/commons/proper/jelly/trunk/src/java/org/apache/commons/jelly/impl/StaticTagScript.java
> URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/jelly/trunk/src/java/org/apache/commons/jelly/impl/StaticTagScript.java?rev=219726&r1=219725&r2=219726&view=diff
> ==============================================================================
> --- jakarta/commons/proper/jelly/trunk/src/java/org/apache/commons/jelly/impl/StaticTagScript.java (original)
> +++ jakarta/commons/proper/jelly/trunk/src/java/org/apache/commons/jelly/impl/StaticTagScript.java Tue Jul 19 10:34:00 2005
> @@ -86,7 +86,10 @@
>              for (Iterator iter = attributes.entrySet().iterator(); iter.hasNext();) {
>                  Map.Entry entry = (Map.Entry) iter.next();
>                  String name = (String) entry.getKey();
> -                Expression expression = (Expression) entry.getValue();
> +                if(name.indexOf(':')!=-1)
> +                    name = name.substring(name.indexOf(':')+1);
> +                ExpressionAttribute expat = (ExpressionAttribute) entry.getValue();
> +                Expression expression = expat.exp;
> 
>                  Object value = null;
> 
> @@ -96,7 +99,10 @@
>                      value = expression.evaluate(context);
>                  }
> 
> -                dynaTag.setAttribute(name, value);
> +                if(expat.prefix!=null || expat.prefix.length()>0 && tag instanceof StaticTag)
> +                    ((StaticTag) dynaTag).setAttribute(name,expat.prefix, expat.nsURI,value);
> +                else
> +                    dynaTag.setAttribute(name, value);
>              }
> 
>              tag.doTag(output);
> 
> Modified: jakarta/commons/proper/jelly/trunk/src/java/org/apache/commons/jelly/impl/TagScript.java
> URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/jelly/trunk/src/java/org/apache/commons/jelly/impl/TagScript.java?rev=219726&r1=219725&r2=219726&view=diff
> ==============================================================================
> --- jakarta/commons/proper/jelly/trunk/src/java/org/apache/commons/jelly/impl/TagScript.java (original)
> +++ jakarta/commons/proper/jelly/trunk/src/java/org/apache/commons/jelly/impl/TagScript.java Tue Jul 19 10:34:00 2005
> @@ -170,7 +170,19 @@
>          if (log.isDebugEnabled()) {
>              log.debug("adding attribute name: " + name + " expression: " + expression);
>          }
> -        attributes.put(name, expression);
> +        attributes.put(name, new ExpressionAttribute(name,expression));
> +    }
> +
> +    /** Add an initialization attribute for the tag.
> +     * This method must be called after the setTag() method
> +     */
> +    public void addAttribute(String name, String prefix, String nsURI, Expression expression) {
> +        if (log.isDebugEnabled()) {
> +            log.debug("adding attribute name: " + name + " expression: " + expression);
> +        }
> +        if(name.indexOf(':')==-1)
> +            name = prefix + ':' + name;
> +        attributes.put(name, new ExpressionAttribute(name,prefix,nsURI,expression));
>      }
> 
>      /**
> @@ -206,7 +218,7 @@
>                  for (Iterator iter = attributes.entrySet().iterator(); iter.hasNext();) {
>                      Map.Entry entry = (Map.Entry) iter.next();
>                      String name = (String) entry.getKey();
> -                    Expression expression = (Expression) entry.getValue();
> +                    Expression expression = ((ExpressionAttribute) entry.getValue()).exp;
> 
>                      Class type = dynaTag.getAttributeType(name);
>                      Object value = null;
> @@ -225,7 +237,7 @@
>                  for (Iterator iter = attributes.entrySet().iterator(); iter.hasNext();) {
>                      Map.Entry entry = (Map.Entry) iter.next();
>                      String name = (String) entry.getKey();
> -                    Expression expression = (Expression) entry.getValue();
> +                    Expression expression = ((ExpressionAttribute) entry.getValue()).exp;
> 
>                      DynaProperty property = dynaBean.getDynaClass().getDynaProperty(name);
>                      if (property == null) {
> @@ -690,3 +702,21 @@
>          throw new JellyTagException(e, fileName, elementName, columnNumber, lineNumber);
>      }
>  }
> +
> +
> +class ExpressionAttribute {
> +    public ExpressionAttribute(String name, Expression exp) {
> +        this(name,"","",exp);
> +    }
> +    public ExpressionAttribute(String name, String prefix, String nsURI, Expression exp) {
> +        this.name = name;
> +        this.prefix = prefix;
> +        this.nsURI = nsURI;
> +        this.exp = exp;
> +    }
> +
> +    String name;
> +    String prefix;
> +    String nsURI;
> +    Expression exp;
> +}
> \ No newline at end of file
> 
> Modified: jakarta/commons/proper/jelly/trunk/src/java/org/apache/commons/jelly/parser/XMLParser.java
> URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/jelly/trunk/src/java/org/apache/commons/jelly/parser/XMLParser.java?rev=219726&r1=219725&r2=219726&view=diff
> ==============================================================================
> --- jakarta/commons/proper/jelly/trunk/src/java/org/apache/commons/jelly/parser/XMLParser.java (original)
> +++ jakarta/commons/proper/jelly/trunk/src/java/org/apache/commons/jelly/parser/XMLParser.java Tue Jul 19 10:34:00 2005
> @@ -1066,7 +1066,12 @@
>                          attributeValue, getExpressionFactory()
>                      );
>                  String attrQName = list.getQName(i);
> -                script.addAttribute(attrQName, expression);
> +                int p = attrQName.indexOf(':');
> +                String prefix = p>=0 ?
> +                        attrQName.substring(0,p):
> +                        "";
> +                script.addAttribute(list.getLocalName(i),
> +                        prefix, list.getURI(i), expression);
>              }
>              return script;
>          }
> 
> Modified: jakarta/commons/proper/jelly/trunk/src/test/org/apache/commons/jelly/TestCoreTags.java
> URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/jelly/trunk/src/test/org/apache/commons/jelly/TestCoreTags.java?rev=219726&r1=219725&r2=219726&view=diff
> ==============================================================================
> --- jakarta/commons/proper/jelly/trunk/src/test/org/apache/commons/jelly/TestCoreTags.java (original)
> +++ jakarta/commons/proper/jelly/trunk/src/test/org/apache/commons/jelly/TestCoreTags.java Tue Jul 19 10:34:00 2005
> @@ -105,4 +105,24 @@
>          textScript.trimStartWhitespace();
>          assertEquals("foo", textScript.getText());
>      }
> +
> +
> +    public void testStaticNamespacedAttributes() throws Exception {
> +        InputStream in = new FileInputStream("src/test/org/apache/commons/jelly/testStaticNamespacedAttributes.jelly");
> +        XMLParser parser = new XMLParser();
> +        Script script = parser.parse(in);
> +        script = script.compile();
> +        log.debug("Found: " + script);
> +        JellyContext context = new JellyContext();
> +        StringWriter buffer = new StringWriter();
> +        script.run(context, XMLOutput.createXMLOutput(buffer));
> +        String text = buffer.toString().trim();
> +        if (log.isDebugEnabled()) {
> +            log.debug("Evaluated script as...");
> +            log.debug(text);
> +        }
> +        assertEquals("Should produces the correct output",
> +                "<blip xmlns:blop=\"blop\" blop:x=\"blip\"></blip>",
> +                text);
> +    }
>  }
> 
> Modified: jakarta/commons/proper/jelly/trunk/src/test/org/apache/commons/jelly/core/TestFileTag.java
> URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/jelly/trunk/src/test/org/apache/commons/jelly/core/TestFileTag.java?rev=219726&r1=219725&r2=219726&view=diff
> ==============================================================================
> --- jakarta/commons/proper/jelly/trunk/src/test/org/apache/commons/jelly/core/TestFileTag.java (original)
> +++ jakarta/commons/proper/jelly/trunk/src/test/org/apache/commons/jelly/core/TestFileTag.java Tue Jul 19 10:34:00 2005
> @@ -55,7 +55,7 @@
> 
>          //FIXME This doesn't take into account attribute ordering
>          assertEquals("fully qualified attributes not passed",
> -                "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\"></html>",
> +                "<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\" xml:lang=\"en\"></html>",
>                  data);
>      }
> 
> 
> Added: jakarta/commons/proper/jelly/trunk/src/test/org/apache/commons/jelly/testStaticNamespacedAttributes.jelly
> URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/jelly/trunk/src/test/org/apache/commons/jelly/testStaticNamespacedAttributes.jelly?rev=219726&view=auto
> ==============================================================================
> --- jakarta/commons/proper/jelly/trunk/src/test/org/apache/commons/jelly/testStaticNamespacedAttributes.jelly (added)
> +++ jakarta/commons/proper/jelly/trunk/src/test/org/apache/commons/jelly/testStaticNamespacedAttributes.jelly Tue Jul 19 10:34:00 2005
> @@ -0,0 +1,4 @@
> +<?xml version="1.0" encoding="utf-8" ?>
> +<j:jelly xmlns:j="jelly:core">
> +       <blip xmlns:blop="blop" blop:x="blip"/>
> +</j:jelly>
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
> 
> 


-- 
http://www.multitask.com.au/people/dion/
"You are going to let the fear of poverty govern your life and your
reward will be that you will eat, but you will not live." - George
Bernard Shaw

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: svn commit: r219726 - in /jakarta/commons/proper/jelly/trunk: jelly-tags/xml/ jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/ jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/ src/java/org/apache/commons/jelly/ src/java/org/ap

Posted by Paul Libbrecht <pa...@activemath.org>.
Le 20 juil. 05, à 01:08, Dion Gillard a écrit :
> could you make the <version> tag 1.2-SNAPSHOT instead of -dev? That 
> keeps it all consistent.

I wanted to ask about this.
Actually, I've also made 1.1-dev into jelly's project.xml.
Isn't SNAPSHOT supposed to be a (fake but complete) version number? 
What we want is something else, or ?

> And how about an update to the changes.xml file?

Sure, that soon.

Also, how could I upload the snapshot at some point?

thanks

paul


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org