So here we go. I've added some test cases and javadoc comments and stuff...

In essence there's a new rule FragmentCreateRule (named to match the 
other factory rules), but all the work is done by an inner class called 
FragmentCreateRule.FragmentBuilder. I've not added a 
Digester.addFragmentCreate(...) method yet.

Have fun ;-)

Scott Sanders wrote:
> I think that is exactly what Jim is looking for.  Jim?
> 
> I would be interested in looking at it if submitted.
> 
> Scott
> 
>>-----Original Message-----
>>From: Christopher Lenz [mailto:[EMAIL PROTECTED]] 
>>Sent: Tuesday, September 10, 2002 10:14 AM
>>To: Jakarta Commons Users List
>>Subject: Re: Digester and XML Elements
>>
>>
>>It's not that bad either ;-)
>>
>>You need to write a rule that overrides the ContentHandler 
>>used by the 
>>XMLReader that Digester is using - which a rule has full read/write 
>>access to. That custom content handler creates the DOM of the element 
>>that triggered the rule. When the content handler encounters 
>>the end of 
>>the element it had started with, it gives control back to Digester.
>>
>>Actually, I've implemented such a creature last week or so, 
>>although a 
>>bit different: Triggered on some element, it builds a DOM 
>>DocumentFragment of all content *beneath* the element it was 
>>triggered 
>>on, and pushes that DocumentFragment on Digester's stack.
>>
>>I could cleanup the code and submit a patch, if there's 
>>interest (and a 
>>committer with some spare time to look at it ;-))...
>>
>>Scott Sanders wrote:
>>
>>>AFAIK, this is not possible with Digester today.  I suppose 
>>
>>you could 
>>
>>>write rules to stream events and build up an Element node, 
>>
>>but that is 
>>
>>>a lot of work.
>>>
>>>I would say that it is 'possible', but not terribly easy.
>>
>> >
>>
>>>Scott
>>>
>>>
>>>
>>>>-----Original Message-----
>>>>From: Jim Birchfield [mailto:[EMAIL PROTECTED]]
>>>>Sent: Tuesday, September 10, 2002 5:03 AM
>>>>To: [EMAIL PROTECTED]
>>>>Subject: Digester and XML Elements
>>>>
>>>>
>>>>I have been using Digester for a while and love it.  However
>>>>I am try to do something I have not seen an example of and 
>>>>cannot seem to figure out how to do it.  I need to grab a 
>>>>portion of my config file as the raw XML.  I want to be able 
>>>>to invoke a method passing in an Element object (or even a 
>>>>string if necessary) of a piece of XML in my file.  Is that 
>>>>possible with Digester today?

-- 
Christopher Lenz
/=/ cmlenz at gmx.de
Index: build.xml
===================================================================
RCS file: /home/cvs/jakarta-commons/digester/build.xml,v
retrieving revision 1.27
diff -u -r1.27 build.xml
--- build.xml   13 Aug 2002 16:28:59 -0000      1.27
+++ build.xml   10 Sep 2002 19:10:24 -0000
@@ -250,7 +250,8 @@
                                test.matching.extended,
                                test.rule,
                                test.bpsr,
-                               test.xmlrules
+                               test.xmlrules,
+                               test.fragment
                               "
    description="Run all unit test cases">
   </target>
@@ -331,6 +332,16 @@
     </java>
   </target>
 
+
+  <target name="test.fragment" depends="compile.tests"
+          description="Run FragmentCreateRule tests ...">
+    <echo message="Running FragmentCreateRule tests ..."/>
+    <java classname="${test.runner}" fork="yes"
+        failonerror="${test.failonerror}">
+      <arg value="org.apache.commons.digester.FragmentCreateRuleTestCase"/>
+      <classpath refid="test.classpath"/>
+    </java>
+  </target>
 
 
 </project>
Index: src/java/org/apache/commons/digester/FragmentCreateRule.java
===================================================================
RCS file: src/java/org/apache/commons/digester/FragmentCreateRule.java
diff -N src/java/org/apache/commons/digester/FragmentCreateRule.java
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/java/org/apache/commons/digester/FragmentCreateRule.java        10 Sep 2002 
+19:10:53 -0000
@@ -0,0 +1,328 @@
+/*
+ * $Header$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights 
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:  
+ *       "This product includes software developed by the 
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written 
+ *    permission, please contact [EMAIL PROTECTED]
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ * [Additional notices, if required by prior licensing conditions]
+ *
+ */
+
+package org.apache.commons.digester;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * A rule implementation that creates a DOM
+ * {@link org.w3c.dom.DocumentFragment DocumentFragment} containing all XML 
+ * nodes under the element the rule was triggered on.
+ * 
+ * <p>This is implemented by replacing the SAX
+ * {@link org.xml.sax.ContentHandler ContentHandler} in the parser used by 
+ * Digester, and resetting it when the matched element is closed. As a side 
+ * effect, rules that would match XML nodes under the element that matches 
+ * a FragmentCreateRule will never be triggered by Digester.</p>
+ * 
+ * <p>The created DocumentFragment will be pushed on Digester's object stack
+ * when done. To use it in the context of another DOM
+ * {@link org.w3c.dom.Document Document}, it must be imported first, using the
+ * Document method
+ * {@link org.w3c.dom.Document#importNode(org.w3c.dom.Node, boolean) importNode()}.
+ * </p>
+ * 
+ * <p>Note that the current implementation does not set the namespace prefixes
+ * in the exported nodes. The (usually more important) namespace URIs are set,
+ * of course.</p>
+ * 
+ * @author <a href="mailto:[EMAIL PROTECTED]";>Christopher Lenz</a>
+ * @version $Revision$
+ * @since Digester 1.4
+ */
+public class FragmentCreateRule extends Rule {
+
+
+    // ---------------------------------------------------------- Inner Classes
+
+
+    /**
+     * The SAX ContentHandler that does all the actual work of assembling the 
+     * DocumentFragment from the SAX events.
+     */
+    private class FragmentBuilder
+        extends DefaultHandler {
+
+
+        // ------------------------------------------------- Instance Variables
+
+
+        /**
+         * The content handler used by Digester before it was set to this 
+         * content handler.
+         */
+        private ContentHandler oldContentHandler = null;
+
+        
+        /**
+         * Depth of the current node, relative to the element where the content
+         * handler was put into action.
+         */
+        private int depth = 0;
+
+        
+        /**
+         * A DOM Document used to create the various Node instances.
+         */
+        private Document doc = null;
+
+        
+        /**
+         * The DOM DocumentFragment that will be pushed on Digester's stack.
+         */
+        private DocumentFragment fragment = null;
+
+        
+        /**
+         * The current top DOM Node.
+         */
+        private Node top = null;
+
+
+        // ------------------------------------------------------- Constructors
+
+
+        /**
+         * Constructor.
+         * 
+         * <p>Stores the content handler currently used by Digester so it can 
+         * be reset when done, and initializes the DOM objects needed to 
+         * build the fragment.
+         * 
+         * @throws ParserConfigurationException if the DocumentBuilderFactory 
+         *   could not be instantiated
+         * @throws SAXException if the XMLReader could not be instantiated by 
+         *   Digester (should not happen)
+         */
+        public FragmentBuilder()
+            throws ParserConfigurationException, SAXException {
+
+            oldContentHandler = digester.getXMLReader().getContentHandler();
+            DocumentBuilder builder =
+                DocumentBuilderFactory.newInstance().newDocumentBuilder();
+            doc = builder.newDocument();
+            fragment = doc.createDocumentFragment();
+            top = fragment;
+
+        }
+
+        
+        // --------------------------------------------- ContentHandler Methods
+
+
+        /**
+         * Appends a {@link org.w3c.dom.Text Text} node to the current node.
+         * 
+         * @param ch the characters from the XML document
+         * @param start the start position in the array
+         * @param length the number of characters to read from the array
+         * @throws SAXException if the DOM implementation throws an exception
+         */
+        public void characters(char[] ch, int start, int length)
+            throws SAXException {
+            
+            try {
+                String str = new String(ch, start, length).trim();
+                if (str.length() > 0) { 
+                    top.appendChild(doc.createTextNode(str));
+                }
+            } catch (DOMException e) {
+                throw new SAXException(e.getMessage());
+            }
+
+        }
+
+
+        /**
+         * Checks whether control needs to be returned to Digester.
+         * 
+         * @param namespaceURI the namespace URI
+         * @param localName the local name
+         * @param qName the qualified (prefixed) name
+         * @throws SAXException if the DOM implementation throws an exception
+         */
+        public void endElement(String namespaceURI, String localName,
+                               String qName)
+            throws SAXException {
+            
+            try {
+                if (depth == 0) {
+                    getDigester().getXMLReader().setContentHandler(
+                        oldContentHandler);
+                    getDigester().push(fragment);
+                    getDigester().endElement(namespaceURI, localName, qName);
+                }
+    
+                top = top.getParentNode();
+                depth--;
+            } catch (DOMException e) {
+                throw new SAXException(e.getMessage());
+            }
+
+        }
+
+
+        /**
+         * Adds a new
+         * {@link org.w3c.dom.ProcessingInstruction ProcessingInstruction} to 
+         * the fragment.
+         * 
+         * @param target the processing instruction target
+         * @param data the processing instruction data, or null if none was 
+         *   supplied
+         * @throws SAXException if the DOM implementation throws an exception
+         */
+        public void processingInstruction(String target, String data)
+            throws SAXException {
+            
+            try {
+                Node node = doc.createProcessingInstruction(target, data);
+            } catch (DOMException e) {
+                throw new SAXException(e.getMessage());
+            }
+
+        }
+
+
+        /**
+         * Adds a new {@link org.w3c.dom.Element Element} to the fragment.
+         * 
+         * @param namespaceURI the namespace URI
+         * @param localName the local name
+         * @param qName the qualified (prefixed) name
+         * @param atts the list of attributes
+         * @throws SAXException if the DOM implementation throws an exception
+         */
+        public void startElement(String namespaceURI, String localName,
+                                 String qName, Attributes atts)
+            throws SAXException {
+
+            try {
+                Node previousTop = top;
+                if ((localName == null) || (localName.length() == 0)) { 
+                    top = doc.createElement(qName);
+                } else {
+                    top = doc.createElementNS(namespaceURI, localName);
+                }
+                for (int i = 0; i < atts.getLength(); i++) {
+                    Attr attr = null;
+                    if ((atts.getLocalName(i) == null) ||
+                        (atts.getLocalName(i).length() == 0)) {
+                        attr = doc.createAttribute(atts.getQName(i));
+                        attr.setNodeValue(atts.getValue(i));
+                        ((Element)top).setAttributeNode(attr);
+                    } else {
+                        attr = doc.createAttributeNS(atts.getURI(i),
+                                                     atts.getLocalName(i));
+                        attr.setNodeValue(atts.getValue(i));
+                        ((Element)top).setAttributeNodeNS(attr);
+                    }
+                }
+                previousTop.appendChild(top);
+                depth++;
+            } catch (DOMException e) {
+                throw new SAXException(e.getMessage());
+            }
+
+        }
+
+    }
+
+
+    // ----------------------------------------------------------- Rule Methods
+
+
+    /**
+     * Implemented to replace the content handler currently in use by a 
+     * {@link FragmentBuilder FragmentBuilder}.
+     * 
+     * @param attributes the attributes of the current element
+     * @throws SAXException if the XMLReader could not be instantiated by 
+     *   Digester (should never happen)
+     * @throws ParserConfigurationException if no appropriate
+     *   DocumentBuilderFactory could be instantiated
+     */
+    public void begin(Attributes attributes)
+        throws SAXException, ParserConfigurationException {
+
+        getDigester().getXMLReader().setContentHandler(
+            new FragmentBuilder());
+
+    }
+
+
+}
Index: src/test/org/apache/commons/digester/FragmentCreateRuleTestCase.java
===================================================================
RCS file: src/test/org/apache/commons/digester/FragmentCreateRuleTestCase.java
diff -N src/test/org/apache/commons/digester/FragmentCreateRuleTestCase.java
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/test/org/apache/commons/digester/FragmentCreateRuleTestCase.java        10 Sep 
+2002 19:10:54 -0000
@@ -0,0 +1,361 @@
+/*
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact [EMAIL PROTECTED]
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+
+package org.apache.commons.digester;
+
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+
+
+/**
+ * <p>Test case for the <code>FragmentCreateRule</code>.
+ * 
+ * @author <a href="mailto:[EMAIL PROTECTED]";>Christopher Lenz</a>
+ * @version $Revision: $
+ */
+public class FragmentCreateRuleTestCase extends TestCase {
+
+
+    // ----------------------------------------------------- Instance Variables
+
+    /**
+     * Simple test xml document used in the tests.
+     */
+    protected final static String TEST_XML =
+        "<?xml version='1.0'?><root>ROOT BODY<alpha>ALPHA BODY</alpha>" +
+        "<beta>BETA BODY</beta><gamma>GAMMA BODY</gamma></root>";
+
+
+    /**
+     * The digester instance we will be processing.
+     */
+    protected Digester digester = null;
+
+
+    // ----------------------------------------------------------- Constructors
+
+
+    /**
+     * Construct a new instance of this test case.
+     *
+     * @param name Name of the test case
+     */
+    public FragmentCreateRuleTestCase(String name) {
+
+        super(name);
+
+    }
+
+
+    // --------------------------------------------------- Overall Test Methods
+
+
+    /**
+     * Set up instance variables required by this test case.
+     */
+    public void setUp() {
+
+        digester = new Digester();
+
+    }
+
+
+    /**
+     * Return the tests included in this test suite.
+     */
+    public static Test suite() {
+
+        return (new TestSuite(FragmentCreateRuleTestCase.class));
+
+    }
+
+
+    /**
+     * Tear down instance variables required by this test case.
+     */
+    public void tearDown() {
+
+        digester = null;
+
+    }
+
+
+
+    // ------------------------------------------------ Individual Test Methods
+
+
+    /**
+     * Tests simple fragment construction, using the {@link TEST_XML TEST_XML}
+     * XML input data.
+     */
+    public void testSimple() throws SAXException, IOException {
+
+        digester.addRule("root", new FragmentCreateRule());
+        Object result = digester.parse(new StringReader(TEST_XML));
+
+        assertNotNull(result);
+        assertTrue(result instanceof DocumentFragment);
+        DocumentFragment fragment = (DocumentFragment)result;
+        assertEquals(4, fragment.getChildNodes().getLength());
+
+        Node rootBody = fragment.getFirstChild();
+        assertEquals(Node.TEXT_NODE, rootBody.getNodeType());
+        assertEquals("ROOT BODY", rootBody.getNodeValue());
+
+        Node alpha = fragment.getChildNodes().item(1);
+        assertEquals(Node.ELEMENT_NODE, alpha.getNodeType());
+        assertEquals("alpha", alpha.getNodeName());
+        assertNull(((Element)alpha).getLocalName());
+        assertNull(((Element)alpha).getNamespaceURI());
+        assertEquals(1, alpha.getChildNodes().getLength());
+        assertEquals("ALPHA BODY", alpha.getFirstChild().getNodeValue());
+
+        Node beta = fragment.getChildNodes().item(2);
+        assertEquals(Node.ELEMENT_NODE, beta.getNodeType());
+        assertEquals("beta", beta.getNodeName());
+        assertNull(((Element)beta).getLocalName());
+        assertNull(((Element)beta).getNamespaceURI());
+        assertEquals(1, beta.getChildNodes().getLength());
+        assertEquals("BETA BODY", beta.getFirstChild().getNodeValue());
+
+        Node gamma = fragment.getChildNodes().item(3);
+        assertEquals(Node.ELEMENT_NODE, gamma.getNodeType());
+        assertEquals("gamma", gamma.getNodeName());
+        assertNull(((Element)gamma).getLocalName());
+        assertNull(((Element)gamma).getNamespaceURI());
+        assertEquals(1, gamma.getChildNodes().getLength());
+        assertEquals("GAMMA BODY", gamma.getFirstChild().getNodeValue());
+
+    }
+
+
+    /**
+     * Tests whether control is returned to digester after fragment
+     * construction.
+     */
+    public void testNested() throws SAXException, IOException {
+
+        digester.addObjectCreate("root", ArrayList.class);
+        digester.addRule("root/a/b", new FragmentCreateRule());
+        digester.addSetRoot("root/a/b", "add");
+        digester.addObjectCreate("root/b", String.class);
+        digester.addSetRoot("root/b", "add");
+        Object result = digester.parse(getInputStream("Test4.xml"));
+
+        assertNotNull(result);
+        assertTrue(result instanceof List);
+        List list = (List)result;
+        assertEquals(2, list.size());
+
+        assertTrue(list.get(0) instanceof DocumentFragment);
+        DocumentFragment fragment = (DocumentFragment)list.get(0);
+
+        assertEquals(Node.ELEMENT_NODE,
+                     fragment.getFirstChild().getNodeType());
+        Element a = (Element)fragment.getFirstChild();
+        assertEquals("a", a.getNodeName());
+        assertEquals(1, a.getAttributes().getLength());
+        assertEquals("THREE", a.getAttribute("name"));
+
+        assertTrue(list.get(1) instanceof String);
+
+    }
+
+
+    /**
+     * Tests whether attributes are correctly imported into the fragment, using
+     * the example in the Test1 XML file.
+     */
+    public void testWithAttributes() throws SAXException, IOException {
+
+        digester.addRule("employee", new FragmentCreateRule());
+        Object result = digester.parse(getInputStream("Test1.xml"));
+
+        assertNotNull(result);
+        assertTrue(result instanceof DocumentFragment);
+        DocumentFragment fragment = (DocumentFragment)result;
+        assertEquals(2, fragment.getChildNodes().getLength());
+
+        assertEquals(Node.ELEMENT_NODE, fragment.getFirstChild().getNodeType());
+        Element address1 = (Element)fragment.getFirstChild();
+        assertEquals("address", address1.getNodeName());
+        assertEquals(5, address1.getAttributes().getLength());
+        assertEquals("home", address1.getAttribute("type"));
+        assertEquals("Home Street", address1.getAttribute("street"));
+        assertEquals("Home City", address1.getAttribute("city"));
+        assertEquals("HS", address1.getAttribute("state"));
+        assertEquals("HmZip", address1.getAttribute("zipCode"));
+
+        assertEquals(Node.ELEMENT_NODE, fragment.getLastChild().getNodeType());
+        Element address2 = (Element)fragment.getLastChild();
+        assertEquals("address", address2.getNodeName());
+        assertEquals(5, address2.getAttributes().getLength());
+        assertEquals("office", address2.getAttribute("type"));
+        assertEquals("Office Street", address2.getAttribute("street"));
+        assertEquals("Office City", address2.getAttribute("city"));
+        assertEquals("OS", address2.getAttribute("state"));
+        assertEquals("OfZip", address2.getAttribute("zipCode"));
+
+    }
+
+
+    /**
+     * Tests whether namespaces are handled correctly, using the example from 
+     * the file Test3 XML file.
+     */
+    public void testWithNamespaces() throws SAXException, IOException {
+
+        digester.setNamespaceAware(true);
+        digester.setRuleNamespaceURI(null);
+        digester.addRule("employee", new FragmentCreateRule());
+        Object result = digester.parse(getInputStream("Test3.xml"));
+
+        assertNotNull(result);
+        assertTrue(result instanceof DocumentFragment);
+        DocumentFragment fragment = (DocumentFragment)result;
+        assertEquals(2, fragment.getChildNodes().getLength());
+
+        assertEquals(Node.ELEMENT_NODE, fragment.getFirstChild().getNodeType());
+        Element address1 = (Element)fragment.getFirstChild();
+        assertEquals("address", address1.getNodeName());
+        assertEquals("http://jakarta.apache.org/digester/Bar";,
+                     address1.getNamespaceURI());
+        assertEquals("address", address1.getLocalName());
+        assertEquals(5, address1.getAttributes().getLength());
+        assertEquals("home", address1.getAttribute("type"));
+        assertEquals("Home Street", address1.getAttribute("street"));
+        assertEquals("Home City", address1.getAttribute("city"));
+        assertEquals("HS", address1.getAttribute("state"));
+        assertEquals("HmZip", address1.getAttribute("zipCode"));
+
+        assertEquals(Node.ELEMENT_NODE, fragment.getLastChild().getNodeType());
+        Element address2 = (Element)fragment.getLastChild();
+        assertEquals("address", address2.getNodeName());
+        assertEquals("http://jakarta.apache.org/digester/Bar";,
+                     address2.getNamespaceURI());
+        assertEquals("address", address2.getLocalName());
+        assertEquals(5, address2.getAttributes().getLength());
+        assertEquals("office", address2.getAttribute("type"));
+        assertEquals("Office Street", address2.getAttribute("street"));
+        assertEquals("Office City", address2.getAttribute("city"));
+        assertEquals("OS", address2.getAttribute("state"));
+        assertEquals("OfZip", address2.getAttribute("zipCode"));
+
+    }
+
+
+    /**
+     * Tests whether the created fragment can be imported into an existing 
+     * document.
+     */
+    public void testImport()
+        throws SAXException, ParserConfigurationException, IOException {
+
+        digester.addRule("root", new FragmentCreateRule());
+        Object result = digester.parse(new StringReader(TEST_XML));
+        DocumentFragment fragment = (DocumentFragment)result;
+
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        DocumentBuilder builder = factory.newDocumentBuilder();
+        Document doc = builder.newDocument();
+        Node importedFragment = doc.importNode(fragment, true);
+        doc.appendChild(doc.createElement("root"));
+        doc.getFirstChild().appendChild(importedFragment);
+
+    }
+
+    // ------------------------------------------------ Utility Support Methods
+
+
+    /**
+     * Return an appropriate InputStream for the specified test file (which
+     * must be inside our current package.
+     *
+     * @param name Name of the test file we want
+     *
+     * @exception IOException if an input/output error occurs
+     */
+    protected InputStream getInputStream(String name) throws IOException {
+
+        return (this.getClass().getResourceAsStream
+                ("/org/apache/commons/digester/" + name));
+
+    }
+
+
+}
+
+

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to