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]>