auto import from //depot/cupcake/@135843
diff --git a/xml/MODULE_LICENSE_APACHE2 b/xml/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/xml/MODULE_LICENSE_APACHE2
diff --git a/xml/MODULE_LICENSE_BSD_LIKE b/xml/MODULE_LICENSE_BSD_LIKE
new file mode 100644
index 0000000..b56941c
--- /dev/null
+++ b/xml/MODULE_LICENSE_BSD_LIKE
@@ -0,0 +1 @@
+For KXML2.
diff --git a/xml/MODULE_LICENSE_W3C b/xml/MODULE_LICENSE_W3C
new file mode 100644
index 0000000..3f41106
--- /dev/null
+++ b/xml/MODULE_LICENSE_W3C
@@ -0,0 +1,3 @@
+For org.w3c.dom code.
+
+See <http://www.w3.org/Consortium/Legal/>.
diff --git a/xml/src/main/java/javax/xml/XMLConstants.java b/xml/src/main/java/javax/xml/XMLConstants.java
new file mode 100644
index 0000000..88fcdad
--- /dev/null
+++ b/xml/src/main/java/javax/xml/XMLConstants.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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 javax.xml;
+
+/**
+ * Defines several standard constants that are often used during XML processing.
+ *  
+ * @since Android 1.0
+ */
+public class XMLConstants {
+
+    /**
+     * The default namespace prefix. Defined to be the empty string. 
+     */
+    public static final String DEFAULT_NS_PREFIX = "";
+
+    /**
+     * The SAX feature name for secure processing. Turning on this feature
+     * might result in a parser rejecting XML documents that are considered
+     * "insecure" (having a potential for DOS attacks, for example). The
+     * Android XML parsing implementation currently ignores this feature.  
+     */
+    public static final String FEATURE_SECURE_PROCESSING = 
+        "http://javax.xml.XMLConstants/feature/secure-processing";
+
+    /**
+     * The namespace URI for the case that no namespace is being used at all.
+     * Defined to be the empty string.
+     */
+    public static final String NULL_NS_URI = "";
+
+    /**
+     * The official Relax-NG namespace URI.
+     */
+    public static final String RELAXNG_NS_URI = 
+        "http://relaxng.org/ns/structure/1.0";
+
+    /**
+     * The official XSchema instance namespace URI, as defined by W3C.
+     */
+    public static final String W3C_XML_SCHEMA_INSTANCE_NS_URI = 
+        "http://www.w3.org/2001/XMLSchema-instance";
+
+    /**
+     * The official XSchema namespace URI, as defined by W3C.
+     */
+    public static final String W3C_XML_SCHEMA_NS_URI = 
+        "http://www.w3.org/2001/XMLSchema";
+
+    /**
+     * The official XPath datatype namespace URI, as defined by W3C.
+     */
+    public static final String W3C_XPATH_DATATYPE_NS_URI = 
+        "http://www.w3.org/2003/11/xpath-datatypes";
+
+    /**
+     * The official XML namespace attribute, as defined by W3C.
+     */
+    public static final String XMLNS_ATTRIBUTE = "xmlns";
+
+    /**
+     * The official XML namespace attribute URI, as defined by W3C.
+     */
+    public static final String XMLNS_ATTRIBUTE_NS_URI = 
+        "http://www.w3.org/2000/xmlns/";
+
+    /**
+     * The official XML DTD namespace URI, as defined by W3C.
+     */
+    public static final String XML_DTD_NS_URI = "http://www.w3.org/TR/REC-xml";
+
+    /**
+     * The official XML namespace prefix, as defined by W3C. 
+     */
+    public static final String XML_NS_PREFIX = "xml";
+
+    /**
+     * The official XML namespace URI, as defined by W3C. 
+     */
+    public static final String XML_NS_URI = 
+        "http://www.w3.org/XML/1998/namespace";
+
+}
diff --git a/xml/src/main/java/javax/xml/package.html b/xml/src/main/java/javax/xml/package.html
new file mode 100644
index 0000000..5a4621d
--- /dev/null
+++ b/xml/src/main/java/javax/xml/package.html
@@ -0,0 +1,8 @@
+<html>
+  <body>
+    <p>
+      Provides a utility class with useful XML constants.
+    </p>
+    @since Android 1.0
+  </body>
+</html>
\ No newline at end of file
diff --git a/xml/src/main/java/javax/xml/parsers/DocumentBuilder.java b/xml/src/main/java/javax/xml/parsers/DocumentBuilder.java
new file mode 100644
index 0000000..6fd6550
--- /dev/null
+++ b/xml/src/main/java/javax/xml/parsers/DocumentBuilder.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 javax.xml.parsers;
+
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Defines a bridge from XML sources (files, stream etc.) to DOM trees. Can be
+ * used for easily obtaining a {@link org.w3c.dom.Document} for the input. The
+ * class itself is abstract. The class {@link DocumentBuilderFactory} is able to
+ * provide instances (of concrete subclasses known to the system).
+ * 
+ * @since Android 1.0
+ */
+public abstract class DocumentBuilder {
+
+    /**
+     * Do-nothing constructor. Prevents instantiation. To be overridden by
+     * concrete subclasses.
+     * 
+     * @since Android 1.0
+     */
+    protected DocumentBuilder() {
+        // Does nothing.
+    }
+
+    /**
+     * Queries the DOM implementation this {@code DocumentBuilder} is working
+     * on.
+     * 
+     * @return the DOM implementation
+     * 
+     * @since Android 1.0
+     */
+    public abstract DOMImplementation getDOMImplementation();
+
+// TODO No XSchema support in Android 1.0. Maybe later.
+//    /**
+//     * Queries the XML schema used by the DocumentBuilder.
+//     * 
+//     * @return The XML schema
+//     * 
+//     * @throws UnsupportedOperationException when the underlying implementation
+//     *         doesn't support XML schemas.
+//     */
+//    public javax.xml.validation.Schema getSchema() throws
+//            UnsupportedOperationException {
+//        throw new UnsupportedOperationException();
+//    }
+     
+    /**
+     * Queries whether the {@code DocumentBuilder} has namespace support
+     * enabled.
+     * 
+     * @return {@code true} if namespaces are turned on, {@code false}
+     *         otherwise.
+     * 
+     * @since Android 1.0
+     */
+    public abstract boolean isNamespaceAware();
+
+    /**
+     * Queries whether the {@code DocumentBuilder} has validation support
+     * enabled.
+     * 
+     * @return {@code true} if validation is turned on, {@code false} otherwise.
+     * 
+     * @since Android 1.0
+     */
+    public abstract boolean isValidating();
+
+    /**
+     * Queries whether the {@code DocumentBuilder} has XInclude support enabled.
+     * 
+     * @return {@code true} if XInclude support is turned on, {@code false}
+     *         otherwise.
+     * 
+     * @throws UnsupportedOperationException if the underlying implementation
+     *         doesn't support XInclude.
+     * 
+     * @since Android 1.0
+     */
+    public boolean isXIncludeAware() throws UnsupportedOperationException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Creates a new, empty document, serving as the starting point for a DOM
+     * tree.
+     * 
+     * @return the document.
+     * 
+     * @since Android 1.0
+     */
+    public abstract Document newDocument();
+
+    /**
+     * Parses a given XML file and builds a DOM tree from it.
+     * 
+     * @param file the file to be parsed.
+     * @return the document element that represents the root of the DOM tree.
+     * 
+     * @throws SAXException if the XML parsing fails.
+     * @throws IOException if an input/output error occurs.
+     * 
+     * @since Android 1.0
+     */
+    public Document parse(File file) throws SAXException, IOException {
+        if (file == null) {
+            throw new IllegalArgumentException();
+        }
+        
+        return parse(new BufferedInputStream(new FileInputStream(file), 8192));
+    }
+
+    /**
+     * Parses a given XML input stream and builds a DOM tree from it.
+     * 
+     * @param stream the stream to be parsed.
+     * @return the document element that represents the root of the DOM tree.
+     * 
+     * @throws SAXException if the XML parsing fails.
+     * @throws IOException if an input/output error occurs.
+     * 
+     * @since Android 1.0
+     */
+    public Document parse(InputStream stream) throws SAXException, IOException {
+        if (stream == null) {
+            throw new IllegalArgumentException();
+        }
+        
+        return parse(new InputSource(stream));
+    }
+
+    /**
+     * Parses a given XML input stream and builds a DOM tree from it.
+     * 
+     * @param stream the stream to be parsed.
+     * @param systemId the base for resolving relative URIs.
+     * @return the document element that represents the root of the DOM tree.
+     * 
+     * @throws SAXException if the XML parsing fails.
+     * @throws IOException if an input/output error occurs.
+     * 
+     * @since Android 1.0
+     */
+    public org.w3c.dom.Document parse(InputStream stream, String systemId)
+            throws SAXException, IOException {
+        if (stream == null) {
+            throw new IllegalArgumentException();
+        }
+        
+        InputSource source = new InputSource(stream);
+        source.setSystemId(systemId);
+        return parse(source);
+    }
+
+    /**
+     * Parses an XML input stream from a given URI and builds a DOM tree from
+     * it.
+     * 
+     * @param uri the URI to fetch the XML stream from.
+     * @return the document element that represents the root of the DOM tree.
+     * 
+     * @throws SAXException if the XML parsing fails.
+     * @throws IOException if an input/output error occurs.
+     * 
+     * @since Android 1.0
+     */
+    public org.w3c.dom.Document parse(String uri) throws SAXException,
+            IOException {
+        if (uri == null) {
+            throw new IllegalArgumentException();
+        }
+        
+        return parse(new InputSource(uri));
+    }
+
+    /**
+     * Parses an XML input source and builds a DOM tree from it.
+     * 
+     * @param source the input source to parse.
+     * @return the document element that represents the root of the DOM tree.
+     * 
+     * @throws SAXException if the XML parsing fails.
+     * @throws IOException if an input/output error occurs.
+     * 
+     * @since Android 1.0
+     */
+    public abstract org.w3c.dom.Document parse(InputSource source)
+            throws SAXException, IOException;
+
+    /**
+     * Resets the DocumentBuilder to the same state is was in after its
+     * creation.
+     * 
+     * @since Android 1.0
+     */
+    public void reset() {
+        // Do nothing.
+    }
+
+    /**
+     * Sets the {@link EntityResolver} used for resolving entities encountered
+     * during the parse process. Passing {@code null} results in the
+     * {@code DocumentBuilder}'s own {@code EntityResolver} being used.
+     * 
+     * @param resolver the {@code EntityResolver} to use, or null for the
+     *        built-in one.
+     * 
+     * @since Android 1.0
+     */
+    public abstract void setEntityResolver(EntityResolver resolver);
+
+    /**
+     * Sets the {@link ErrorHandler} used for dealing with errors encountered
+     * during the parse process. Passing {@code null} results in the
+     * {@code DocumentBuilder}'s own {@code ErrorHandler} being used.
+     * 
+     * @param handler the {@code ErrorHandler} to use, or {@code null} for the
+     *        built-in one.
+     * 
+     * @since Android 1.0
+     */
+    public abstract void setErrorHandler(ErrorHandler handler);
+
+}
diff --git a/xml/src/main/java/javax/xml/parsers/DocumentBuilderFactory.java b/xml/src/main/java/javax/xml/parsers/DocumentBuilderFactory.java
new file mode 100644
index 0000000..4e186c1
--- /dev/null
+++ b/xml/src/main/java/javax/xml/parsers/DocumentBuilderFactory.java
@@ -0,0 +1,405 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 javax.xml.parsers;
+
+import org.apache.harmony.xml.parsers.DocumentBuilderFactoryImpl;
+
+/**
+ * Provides a factory for {@link DocumentBuilder} instances. The class first
+ * needs to be instantiated using the {@link #newInstance()} method. The
+ * instance can be configured as desired. A call to
+ * {@link #newDocumentBuilder()} then provides a {@code DocumentBuilder}
+ * instance matching this configuration (if possible).
+ * 
+ * @since Android 1.0
+ */
+public abstract class DocumentBuilderFactory extends Object {
+
+    private boolean coalesce;
+
+    private boolean expandEntityReferences;
+
+    private boolean ignoreComments;
+
+    private boolean ignoreElementContentWhitespace;
+
+    private boolean namespaceAware;
+
+    private boolean validate;
+
+    /**
+     * Do-nothing constructor. To be overridden by concrete document builders.
+     * 
+     * @since Android 1.0
+     */
+    protected DocumentBuilderFactory() {
+        // Does nothing.
+    }
+
+    /**
+     * Queries an attribute from the underlying implementation.
+     * 
+     * @param name the name of the attribute.
+     * @return the value of the attribute.
+     * 
+     * @throws IllegalArgumentException if the argument is unknown to the
+     *         underlying implementation.
+     * 
+     * @since Android 1.0
+     */
+    public abstract Object getAttribute(String name)
+            throws IllegalArgumentException;
+
+    /**
+     * Queries a feature from the underlying implementation.
+     * 
+     * @param name The name of the feature. The default Android implementation
+     *             of {@link DocumentBuilder} supports only the following three
+     *             features:
+     *             
+     *             <dl>
+     *               <dt>{@code http://xml.org/sax/features/namespaces}</dt>
+     *               <dd>Queries the state of namespace-awareness.</dd>
+     *               
+     *               <dt>
+     *                 {@code http://xml.org/sax/features/namespace-prefixes}
+     *               </dt>
+     *               <dd>Queries the state of namespace prefix processing</dd>
+     *
+     *               <dt>
+     *                 {@code http://xml.org/sax/features/validation}
+     *               </dt>
+     *               <dd>Queries the state of validation.</dd>
+     *             </dl>
+     *             
+     *             Note that despite the ability to query the validation
+     *             feature, there is currently no validating parser available.
+     *             Also note that currently either namespaces or 
+     *             namespace prefixes can be enabled, but not both at the same 
+     *             time.
+     * 
+     * @return the status of the feature.
+     * 
+     * @throws IllegalArgumentException if the feature is unknown to
+     *         the underlying implementation.
+     * @throws ParserConfigurationException if the feature is
+     *         known, but not supported.
+     * 
+     * @since Android 1.0
+     */
+    public abstract boolean getFeature(String name)
+            throws ParserConfigurationException;
+
+// TODO No XSchema support in Android 1.0. Maybe later.
+//    /**
+//     * Queries the desired XML Schema object.
+//     * 
+//     * @return The XML Schema object, if it has been set by a call to setSchema,
+//     *         or null otherwise.
+//     */
+//    public javax.xml.validation.Schema getSchema() {
+//        return schema;
+//    }
+    
+    /**
+     * Queries whether the factory is configured to deliver parsers that convert
+     * CDATA nodes to text nodes and melt them with neighboring nodes. This is
+     * called "coalescing".
+     * 
+     * @return {@code true} if coalescing is desired, {@code false} otherwise.
+     * 
+     * @since Android 1.0
+     */
+    public boolean isCoalescing() {
+        return coalesce;
+    }
+
+    /**
+     * Queries whether the factory is configured to deliver parsers that expand
+     * entity references.
+     * 
+     * @return {@code true} if entity expansion is desired, {@code false}
+     * otherwise.
+     * 
+     * @since Android 1.0
+     */
+    public boolean isExpandEntityReferences() {
+        return expandEntityReferences;
+    }
+
+    /**
+     * Queries whether the factory is configured to deliver parsers that ignore
+     * comments.
+     * 
+     * @return {@code true} if comment ignorance is desired, {@code false}
+     * otherwise.
+     * 
+     * @since Android 1.0
+     */
+    public boolean isIgnoringComments() {
+        return ignoreComments;
+    }
+
+    /**
+     * Queries whether the factory is configured to deliver parsers that ignore
+     * whitespace in elements.
+     * 
+     * @return {@code true} if whitespace ignorance is desired, {@code false}
+     * otherwise.
+     * 
+     * @since Android 1.0
+     */
+    public boolean isIgnoringElementContentWhitespace() {
+        return ignoreElementContentWhitespace;
+    }
+
+    /**
+     * Queries whether the factory is configured to deliver parsers that are
+     * namespace-aware.
+     * 
+     * @return {@code true} if namespace-awareness is desired, {@code false}
+     * otherwise.
+     * 
+     * @since Android 1.0
+     */
+    public boolean isNamespaceAware() {
+        return namespaceAware;
+    }
+
+    /**
+     * Queries whether the factory is configured to deliver parsers that are
+     * validating.
+     * 
+     * @return {@code true} if validating is desired, {@code false} otherwise.
+     * 
+     * @since Android 1.0
+     */
+    public boolean isValidating() {
+        return validate;
+    }
+
+    /**
+     * Queries whether the factory is configured to deliver parsers that are
+     * XInclude-aware.
+     * 
+     * @return {@code true} if XInclude-awareness is desired, {@code false}
+     * otherwise.
+     * 
+     * @since Android 1.0
+     */
+    public boolean isXIncludeAware() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Creates a new {@link DocumentBuilder} that matches the current
+     * configuration of the factory.
+     * 
+     * @return the DocumentBuilder.
+     * @throws ParserConfigurationException if no matching
+     *         {@code DocumentBuilder} could be found.
+     * 
+     * @since Android 1.0
+     */
+    public abstract DocumentBuilder newDocumentBuilder()
+            throws ParserConfigurationException;
+
+    /**
+     * Creates a new DocumentBuilderFactory that can be configured and then be
+     * used for creating DocumentBuilder objects. The method first checks the
+     * value of the {@code DocumentBuilderFactory} property.
+     * If this is non-{@code null}, it is assumed to be the name of a class
+     * that serves as the factory. The class is instantiated, and the instance
+     * is returned. If the property value is {@code null}, the system's default
+     * factory implementation is returned.
+     * 
+     * @return the DocumentBuilderFactory.
+     * @throws FactoryConfigurationError if no {@code DocumentBuilderFactory}
+     *         can be created.
+     * 
+     * @since Android 1.0
+     */
+    public static DocumentBuilderFactory newInstance()
+            throws FactoryConfigurationError {
+        // TODO Properties file and META-INF case missing here. See spec.
+        String factory = System
+                .getProperty("javax.xml.parsers.DocumentBuilderFactory");
+        if (factory != null) {
+            try {
+                return (DocumentBuilderFactory) Class.forName(factory)
+                        .newInstance();
+            } catch (Exception ex) {
+                // Ignore.
+            }
+        }
+
+        try {
+            return new DocumentBuilderFactoryImpl();
+        } catch (Exception ex) {
+            // Ignore.
+        }
+
+        throw new FactoryConfigurationError(
+                "Cannot create DocumentBuilderFactory");
+    }
+
+    /**
+     * Sets an attribute in the underlying implementation.
+     * 
+     * @param name the name of the attribute.
+     * @param value the value of the attribute.
+     * 
+     * @throws IllegalArgumentException if the argument is unknown to the
+     *         underlying implementation.
+     * 
+     * @since Android 1.0
+     */
+    public abstract void setAttribute(String name, Object value)
+            throws IllegalArgumentException;
+
+    /**
+     * Determines whether the factory is configured to deliver parsers that
+     * convert CDATA nodes to text nodes and melt them with neighboring nodes.
+     * This is called "coalescing".
+     * 
+     * @param value turns coalescing on or off.
+     * 
+     * @since Android 1.0
+     */
+    public void setCoalescing(boolean value) {
+        coalesce = value;
+    }
+
+    /**
+     * Determines whether the factory is configured to deliver parsers that
+     * expands entity references.
+     * 
+     * @param value turns entity reference expansion on or off.
+     * 
+     * @since Android 1.0
+     */
+    public void setExpandEntityReferences(boolean value) {
+        expandEntityReferences = value;
+    }
+
+    /**
+     * Sets a feature in the underlying implementation.
+     * 
+     * @param name the name of the feature. The default Android implementation
+     *             of {@link DocumentBuilder} supports only the following three
+     *             features:
+     *             
+     *             <dl>
+     *               <dt>{@code http://xml.org/sax/features/namespaces}</dt>
+     *               <dd>Sets the state of namespace-awareness.</dd>
+     *               
+     *               <dt>
+     *                 {@code http://xml.org/sax/features/namespace-prefixes}
+     *               </dt>
+     *               <dd>Sets the state of namespace prefix processing</dd>
+     *
+     *               <dt>{@code http://xml.org/sax/features/validation}</dt>
+     *               <dd>Sets the state of validation.</dd>
+     *             </dl>
+     *             
+     *             Note that despite the ability to set the validation
+     *             feature, there is currently no validating parser available.
+     *             Also note that currently either namespaces or
+     *             namespace prefixes can be enabled, but not both at the same
+     *             time.
+     * 
+     * @param value the value of the feature.
+     * 
+     * @throws ParserConfigurationException if the feature is unknown to the
+     *         underlying implementation.
+     * 
+     * @since Android 1.0
+     */
+    public abstract void setFeature(String name, boolean value)
+            throws ParserConfigurationException;
+
+    /**
+     * Determines whether the factory is configured to deliver parsers that
+     * ignore comments.
+     * 
+     * @param value turns comment ignorance on or off.
+     * 
+     * @since Android 1.0
+     */
+    public void setIgnoringComments(boolean value) {
+        ignoreComments = value;
+    }
+
+    /**
+     * Determines whether the factory is configured to deliver parsers that
+     * ignores element whitespace.
+     * 
+     * @param value turns element whitespace ignorance on or off.
+     * 
+     * @since Android 1.0
+     */
+    public void setIgnoringElementContentWhitespace(boolean value) {
+        ignoreElementContentWhitespace = value;
+    }
+
+    /**
+     * Determines whether the factory is configured to deliver parsers that are
+     * namespace-aware.
+     * 
+     * @param value turns namespace-awareness on or off.
+     * 
+     * @since Android 1.0
+     */
+    public void setNamespaceAware(boolean value) {
+        namespaceAware = value;
+    }
+
+// TODO No XSchema support in Android 1.0. Maybe later.
+//    /**
+//     * Sets the desired XML Schema object.
+//     * 
+//     * @param schema The XML Schema object.
+//     */
+//    public void setSchema(Schema schema) {
+//        this.schema = schema;
+//    }
+    
+    /**
+     * Determines whether the factory is configured to deliver parsers that are
+     * validating.
+     * 
+     * @param value turns validation on or off.
+     * 
+     * @since Android 1.0
+     */
+    public void setValidating(boolean value) {
+        validate = value;
+    }
+
+    /**
+     * Determines whether the factory is configured to deliver parsers that are
+     * XInclude-aware.
+     * 
+     * @param value turns XInclude-awareness on or off.
+     * 
+     * @since Android 1.0
+     */
+    public void setXIncludeAware(boolean value) {
+        throw new UnsupportedOperationException();
+    }
+
+}
diff --git a/xml/src/main/java/javax/xml/parsers/FactoryConfigurationError.java b/xml/src/main/java/javax/xml/parsers/FactoryConfigurationError.java
new file mode 100644
index 0000000..f5e0c03
--- /dev/null
+++ b/xml/src/main/java/javax/xml/parsers/FactoryConfigurationError.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 javax.xml.parsers;
+
+/**
+ * Represents an error that occurred during the configuration of parser factory.
+ * 
+ * @since Android 1.0
+ */
+public class FactoryConfigurationError extends Error {
+
+    /**
+     * The nested exception that caused this exception. Note that the nested
+     * exception will be stored in a special attribute, and can be queried using
+     * the {@link #getException()} method. It does not use the facility the
+     * {@link Exception} class provides for storing nested exceptions, since the
+     * XML API predates that facility.
+     */
+    private Exception cause;
+    
+    /**
+     * Creates a new {@code FactoryConfigurationError} with no error message and
+     * no cause.
+     * 
+     * @since Android 1.0
+     */
+    public FactoryConfigurationError() {
+        super();
+    }
+
+    /**
+     * Creates a new {@code FactoryConfigurationError} with no error message and
+     * a given cause.
+     * 
+     * @param cause the cause of the error. Note that the nested exception will
+     *        be stored in a special attribute, and can be queried using the
+     *        {@link #getException()} method. It does not use the facility the
+     *        Exception class provides for storing nested exceptions, since the
+     *        XML API predates that facility.
+     * 
+     * @since Android 1.0
+     */
+    public FactoryConfigurationError(Exception cause) {
+        super();
+        this.cause = cause;
+    }
+
+    /**
+     * Creates a new {@code FactoryConfigurationError} with a given error
+     * message and cause.
+     * 
+     * @param cause the cause of the error. Note that the nested exception will
+     *        be stored in a special attribute, and can be queried using the
+     *        {@link #getException()} method. It does not use the facility the
+     *        {@link Exception} class provides for storing nested exceptions,
+     *        since the XML API predates that facility.
+     * @param message The error message.
+     * 
+     * @since Android 1.0
+     */
+    public FactoryConfigurationError(Exception cause, String message) {
+        super(message);
+        this.cause = cause;
+    }
+
+    /**
+     * Creates a new {@code FactoryConfigurationError} with a given error
+     * message and no cause.
+     * 
+     * @param message the error message.
+     * 
+     * @since Android 1.0
+     */
+    public FactoryConfigurationError(String message) {
+        super(message);
+    }
+
+    /**
+     * Returns the cause of the error, in case there is one.
+     * 
+     * @return the exception that caused the error, or {@code null} if none is
+     *         set.
+     * 
+     * @since Android 1.0
+     */
+    public Exception getException() {
+        return cause;
+    }
+
+    /**
+     * Returns the message of the error, in case there is one.
+     * 
+     * @return the message. If an explicit error message has been assigned to
+     *         the exception, this one is returned. If not, and there is an
+     *         underlying exception (the cause), then the result of invoking
+     *         {@link #toString()} on that object is returned. Otherwise, {@code
+     *         null} is returned.
+     * 
+     * @since Android 1.0
+     */
+    public String getMessage() {
+        String message = super.getMessage();
+
+        if (message != null) {
+            return message;
+        } else if (cause != null) {
+            return cause.toString();
+        } else {
+            return null;
+        }
+    }
+}
diff --git a/xml/src/main/java/javax/xml/parsers/ParserConfigurationException.java b/xml/src/main/java/javax/xml/parsers/ParserConfigurationException.java
new file mode 100644
index 0000000..49875d6
--- /dev/null
+++ b/xml/src/main/java/javax/xml/parsers/ParserConfigurationException.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 javax.xml.parsers;
+
+/**
+ * Represents an exception that occurred during the configuration of parser.
+ * 
+ * @since Android 1.0
+ */
+public class ParserConfigurationException extends Exception {
+
+    /**
+     * Creates a new {@code ParserConfigurationException} with no error message.
+     * 
+     * @since Android 1.0
+     */
+    public ParserConfigurationException() {
+        super();
+    }
+
+    /**
+     * Creates a new {@code ParserConfigurationException} with a given error
+     * message.
+     * 
+     * @param msg the error message.
+     * 
+     * @since Android 1.0
+     */
+    public ParserConfigurationException(String msg) {
+        super(msg);
+    }
+
+}
diff --git a/xml/src/main/java/javax/xml/parsers/SAXParser.java b/xml/src/main/java/javax/xml/parsers/SAXParser.java
new file mode 100644
index 0000000..73cc0eb
--- /dev/null
+++ b/xml/src/main/java/javax/xml/parsers/SAXParser.java
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 javax.xml.parsers;
+
+import org.xml.sax.HandlerBase;
+import org.xml.sax.InputSource;
+import org.xml.sax.Parser;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Provides a wrapper around a SAX {@link XMLReader}. This abstract
+ * class only defines the interface, whereas the {@link SAXParserFactory} class
+ * is used to obtain instances of concrete subclasses.
+ * 
+ * @since Android 1.0
+ */
+public abstract class SAXParser extends java.lang.Object {
+
+    /**
+     * Do-nothing constructor. Prevents instantiation. To be overridden by
+     * concrete subclasses.
+     * 
+     * @since Android 1.0
+     */
+    protected SAXParser() {
+        // Does nothing.
+    }
+
+    /**
+     * Queries the underlying SAX {@link Parser} object.
+     * 
+     * @return the SAX {@code Parser}.
+     * 
+     * @throws SAXException if a problem occurs.
+     * 
+     * @since Android 1.0
+     */
+    public abstract Parser getParser()
+            throws SAXException;
+
+    /**
+     * Queries a property of the underlying SAX {@link XMLReader}.
+     * 
+     * @param name the name of the property.
+     * @return the value of the property.
+     * 
+     * @throws SAXNotRecognizedException if the property is not known to the
+     *         underlying SAX {@code XMLReader}.
+     * @throws SAXNotSupportedException if the property is known, but not
+     *         supported by the underlying SAX {@code XMLReader}.
+     * 
+     * @since Android 1.0
+     */
+    public abstract Object getProperty(String name)
+            throws SAXNotRecognizedException, SAXNotSupportedException;
+
+// TODO No XSchema support in Android 1.0. Maybe later.
+//    /**
+//     * Queries the XML Schema used by the underlying XMLReader.
+//     * 
+//     * @return The XML Schema.
+//     */
+//    public Schema getSchema() {
+//        return schema;
+//    }
+    
+    /**
+     * Queries the underlying SAX XMLReader object.
+     * 
+     * @return the SAX XMLREader.
+     * 
+     * @throws SAXException if a problem occurs.
+     * 
+     * @since Android 1.0
+     */
+    public abstract XMLReader getXMLReader() throws SAXException;
+
+    /**
+     * Reflects whether this {@code SAXParser} is namespace-aware.
+     * 
+     * @return {@code true} if the {@code SAXParser} is namespace-aware, or
+     * {@code false} otherwise.
+     * 
+     * @since Android 1.0
+     */
+    public abstract boolean isNamespaceAware();
+
+    /**
+     * Reflects whether this {@code SAXParser} is validating.
+     * 
+     * @return {@code true} if the {@code SAXParser} is validating, or {@code
+     * false} otherwise.
+     * 
+     * @since Android 1.0
+     */
+    public abstract boolean isValidating();
+
+    /**
+     * Reflects whether this {@code SAXParser} is XInclude-aware.
+     * 
+     * @return {@code true} if the {@code SAXParser} is XInclude-aware, or
+     *         {@code false} otherwise.
+     * 
+     * @throws UnsupportedOperationException if the underlying implementation
+     *         doesn't know about XInclude at all (backwards compatibility).
+     * 
+     * @since Android 1.0
+     */
+    public boolean isXIncludeAware() throws UnsupportedOperationException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Parses the given XML file using the given SAX event handler.
+     * 
+     * @param file the file containing the XML document.
+     * @param handler the SAX handler.
+     * 
+     * @throws SAXException if a problem occurs during SAX parsing.
+     * @throws IOException if a general IO problem occurs.
+     * 
+     * @since Android 1.0
+     */
+    public void parse(File file, HandlerBase handler) throws SAXException,
+            IOException {
+        if (file == null) {
+            throw new IllegalArgumentException("file must not be null");
+        }
+        if (file.isDirectory()) {
+            throw new IllegalArgumentException("file must not be a directory");
+        }
+        InputSource source = new InputSource("file:" + file.getAbsolutePath());
+        parse(source, handler);
+    }
+
+    /**
+     * Parses the given XML file using the given SAX event handler.
+     * 
+     * @param file the file containing the XML document.
+     * @param handler the SAX handler.
+     * 
+     * @throws SAXException if a problem occurs during SAX parsing.
+     * @throws IOException if a general IO problem occurs.
+     * 
+     * @since Android 1.0
+     */
+    public void parse(File file, DefaultHandler handler) throws SAXException,
+            IOException {
+        if (file == null) {
+            throw new IllegalArgumentException("file must not be null");
+        }
+        if (file.isDirectory()) {
+            throw new IllegalArgumentException("file must not be a directory");
+        }
+        InputSource source = new InputSource("file:" + file.getAbsolutePath());
+        parse(source, handler);
+    }
+
+    /**
+     * Parses the given XML InputStream using the given SAX event handler.
+     * 
+     * @param stream the InputStream containing the XML document.
+     * @param handler the SAX handler.
+     * 
+     * @throws SAXException if a problem occurs during SAX parsing.
+     * @throws IOException if a general IO problem occurs.
+     * 
+     * @since Android 1.0
+     */
+    public void parse(InputStream stream, HandlerBase handler)
+            throws SAXException, IOException {
+        if (stream == null) {
+            throw new IllegalArgumentException("stream must not be null");
+        }
+        parse(new InputSource(stream), handler);
+    }
+
+    /**
+     * Parses the given XML InputStream using the given SAX event handler and
+     * system ID.
+     * 
+     * @param stream the InputStream containing the XML document.
+     * @param handler the SAX handler.
+     * @param systemId the system ID.
+     * 
+     * @throws SAXException if a problem occurs during SAX parsing.
+     * @throws IOException if a general IO problem occurs.
+     * 
+     * @since Android 1.0
+     */
+    public void parse(InputStream stream, HandlerBase handler, String systemId)
+            throws SAXException, IOException {
+        if (stream == null) {
+            throw new IllegalArgumentException("stream must not be null");
+        }
+        InputSource source = new InputSource(stream);
+        if (systemId != null) {
+            source.setSystemId(systemId);
+        }
+        parse(source, handler);
+    }
+
+    /**
+     * Parses the given XML InputStream using the given SAX event handler.
+     * 
+     * @param stream the InputStream containing the XML document.
+     * @param handler the SAX handler.
+     * 
+     * @throws SAXException if a problem occurs during SAX parsing.
+     * @throws IOException if a general IO problem occurs.
+     * 
+     * @since Android 1.0
+     */
+    public void parse(InputStream stream, DefaultHandler handler)
+            throws SAXException, IOException {
+        parse(new InputSource(stream), handler);
+    }
+
+    /**
+     * Parses the given XML InputStream using the given SAX event handler and
+     * system ID.
+     * 
+     * @param stream the InputStream containing the XML document.
+     * @param handler the SAX handler.
+     * @param systemId the system ID.
+     * 
+     * @throws SAXException if a problem occurs during SAX parsing.
+     * @throws IOException if a general IO problem occurs.
+     * 
+     * @since Android 1.0
+     */
+    public void parse(InputStream stream, DefaultHandler handler,
+            String systemId) throws SAXException, IOException {
+        if (stream  == null) {
+            throw new IllegalArgumentException("stream must not be null");
+        }
+        InputSource source = new InputSource(stream);
+        if (systemId != null) {
+            source.setSystemId(systemId);
+        }
+        parse(source, handler);
+    }
+
+    /**
+     * Parses the contents of the given URI using the given SAX event handler.
+     * 
+     * @param uri the URI pointing to the XML document.
+     * @param handler the SAX handler.
+     * 
+     * @throws SAXException if a problem occurs during SAX parsing.
+     * @throws IOException if a general IO problem occurs.
+     * 
+     * @since Android 1.0
+     */
+    public void parse(String uri, HandlerBase handler) throws SAXException,
+            IOException {
+        if (uri == null) {
+            throw new IllegalArgumentException("uri must not be null");
+        }
+        parse(new InputSource(uri), handler);
+    }
+
+    /**
+     * Parses the contents of the given URI using the given SAX event handler.
+     * 
+     * @param uri the URI pointing to the XML document.
+     * @param handler the SAX handler.
+     * 
+     * @throws SAXException if a problem occurs during SAX parsing.
+     * @throws IOException if a general IO problem occurs.
+     * 
+     * @since Android 1.0
+     */
+    public void parse(String uri, DefaultHandler handler) throws SAXException,
+            IOException {
+        if (uri == null) {
+            throw new IllegalArgumentException("uri must not be null");
+        }
+        parse(new InputSource(uri), handler);
+    }
+
+    /**
+     * Parses the given SAX {@link InputSource} using the given SAX event
+     * handler.
+     * 
+     * @param source the SAX {@code InputSource} containing the XML document.
+     * @param handler the SAX handler.
+     * 
+     * @throws SAXException if a problem occurs during SAX parsing.
+     * @throws IOException if a general IO problem occurs.
+     * 
+     * @since Android 1.0
+     */
+    public void parse(InputSource source, HandlerBase handler)
+            throws SAXException, IOException {
+        Parser parser = getParser();
+        if (source == null) {
+            throw new IllegalArgumentException("source must not be null");
+        }
+
+        if (handler != null) {
+            parser.setDocumentHandler(handler);
+            parser.setDTDHandler(handler);
+            parser.setEntityResolver(handler);
+            parser.setErrorHandler(handler);
+        }
+
+        parser.parse(source);
+    }
+
+    /**
+     * Parses the given SAX {@link InputSource} using the given SAX event
+     * handler.
+     * 
+     * @param source the SAX {@code InputSource} containing the XML document.
+     * @param handler the SAX handler.
+     * 
+     * @throws SAXException if a problem occurs during SAX parsing.
+     * @throws IOException if a general IO problem occurs.
+     * 
+     * @since Android 1.0
+     */
+    public void parse(InputSource source, DefaultHandler handler)
+            throws SAXException, IOException {
+        if (source == null) {
+            throw new IllegalArgumentException("source must not be null");
+        }
+        XMLReader reader = getXMLReader();
+
+        if (handler != null) {
+            reader.setContentHandler(handler);
+            reader.setDTDHandler(handler);
+            reader.setEntityResolver(handler);
+            reader.setErrorHandler(handler);
+        }
+
+        reader.parse(source);
+    }
+
+    /**
+     * Resets the {@code SAXParser} to the same state is was in after its
+     * creation.
+     * 
+     * @since Android 1.0
+     */
+    public void reset() {
+        // Do nothing.
+    }
+
+    /**
+     * Sets a property of the underlying SAX {@link XMLReader}.
+     * 
+     * @param name the name of the property.
+     * @param value the value of the property.
+     * 
+     * @throws SAXNotRecognizedException if the property is not known to the
+     *         underlying SAX {@code XMLReader}.
+     * @throws SAXNotSupportedException if the property is known, but not
+     *         supported by the underlying SAX {@code XMLReader}.
+     * 
+     * @since Android 1.0
+     */
+    public abstract void setProperty(String name, Object value)
+            throws SAXNotRecognizedException, SAXNotSupportedException;
+
+}
diff --git a/xml/src/main/java/javax/xml/parsers/SAXParserFactory.java b/xml/src/main/java/javax/xml/parsers/SAXParserFactory.java
new file mode 100644
index 0000000..ebf0531
--- /dev/null
+++ b/xml/src/main/java/javax/xml/parsers/SAXParserFactory.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 javax.xml.parsers;
+
+import org.apache.harmony.xml.parsers.SAXParserFactoryImpl;
+
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.SAXException;
+
+/**
+ * Provides a factory for {@link SAXParser} instances. The class first needs to
+ * be instantiated using the {@link #newInstance()} method. The instance can be
+ * configured as desired. A call to its {@link #newSAXParser()} then provides a
+ * {@code SAXParser} instance matching this configuration, if possible.
+ * 
+ * @since Android 1.0
+ */
+public abstract class SAXParserFactory {
+
+    private boolean namespaceAware;
+
+    private boolean validating;
+
+    private boolean xincludeAware;
+
+    /**
+     * Do-nothing constructor. Prevents instantiation. To be overridden by
+     * concrete subclasses.
+     * 
+     * @since Android 1.0
+     */
+    protected SAXParserFactory() {
+        // Does nothing.
+    }
+
+    /**
+     * Queries a feature from the underlying implementation.
+     * 
+     * @param name The name of the feature. The default Android implementation
+     *             of {@link SAXParser} supports only the following three
+     *             features:
+     *             
+     *             <dl>
+     *               <dt>{@code http://xml.org/sax/features/namespaces}</dt>
+     *               <dd>Queries the state of namespace-awareness.</dd>
+     *               
+     *               <dt>
+     *                 {@code http://xml.org/sax/features/namespace-prefixes}
+     *               </dt>
+     *               <dd>Queries the state of namespace prefix processing</dd>
+     *
+     *               <dt>{@code http://xml.org/sax/features/validation}</dt>
+     *               <dd>Queries the state of validation.</dd>
+     *             </dl>
+     *             
+     *             Note that despite the ability to query the validation
+     *             feature, there is currently no validating parser available.
+     *             Also note that currently either namespaces or 
+     *             namespace prefixes can be enabled, but not both at the same 
+     *             time.
+     *             
+     * @return the status of the feature.
+     * 
+     * @throws ParserConfigurationException if no {@code SAXParser} matching the
+     *         given criteria is available.
+     * @throws SAXNotRecognizedException if the given feature is not known to
+     *         the underlying implementation.
+     * @throws SAXNotSupportedException if the given features is known, but not
+     *         supported by the underlying implementation.
+     *         
+     * @since Android 1.0
+     */
+    public abstract boolean getFeature(String name)
+            throws ParserConfigurationException, SAXNotRecognizedException,
+            SAXNotSupportedException;
+
+// TODO No XSchema support in Android 1.0. Maybe later.
+//    /**
+//     * Queries the desired XML Schema object.
+//     * 
+//     * @return The XML Schema object, if it has been set by a call to setSchema,
+//     *         or null otherwise.
+//     */
+//    public javax.xml.validation.Schema getSchema() {
+//        return schema;
+//    }
+    
+    /**
+     * Queries whether the factory is configured to deliver parsers that are
+     * namespace-aware.
+     * 
+     * @return {@code true} if namespace-awareness is desired, {@code false}
+     *         otherwise.
+     * 
+     * @since Android 1.0
+     */
+    public boolean isNamespaceAware() {
+        return namespaceAware;
+    }
+
+    /**
+     * Queries whether the factory is configured to deliver parsers that are
+     * validating.
+     * 
+     * @return {@code true} if validating is desired, {@code false} otherwise.
+     * 
+     * @since Android 1.0
+     */
+    public boolean isValidating() {
+        return validating;
+    }
+
+    /**
+     * Queries whether the factory is configured to deliver parsers that are
+     * XInclude-aware.
+     * 
+     * @return {@code true} if XInclude-awareness is desired, {@code false}
+     *         otherwise.
+     * 
+     * @since Android 1.0
+     */
+    public boolean isXIncludeAware() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Creates a new {@code SAXParserFactory} that can be configured and then be
+     * used for creating {@link SAXParser} objects. The method first checks the
+     * value of the {@code SAXParserFactory} property. If this
+     * is non-{@code null}, it is assumed to be the name of a class that serves
+     * as the factory. The class is instantiated, and the instance is returned.
+     * If the property value is {@code null}, the system's default factory
+     * implementation is returned. 
+     * 
+     * @return the {@code SAXParserFactory}.
+     * 
+     * @throws FactoryConfigurationError if no {@code SAXParserFactory} can be
+     *         created.
+     *         
+     * @since Android 1.0
+     */
+    public static SAXParserFactory newInstance()
+            throws FactoryConfigurationError {
+        // TODO Properties file and META-INF case missing here. See spec.
+        String factory = System
+                .getProperty("javax.xml.parsers.SAXParserFactory");
+        if (factory != null) {
+            try {
+                return (SAXParserFactory) Class.forName(factory).newInstance();
+            } catch (Exception ex) {
+                throw new FactoryConfigurationError(factory);
+            }
+        }
+
+        try {
+            return new SAXParserFactoryImpl();
+        } catch (Exception ex) {
+            // Ignore.
+        }
+
+        throw new FactoryConfigurationError("Cannot create SAXParserFactory");
+    }
+
+    /**
+     * Creates a new {@link SAXParser} that matches the current configuration of
+     * the factory.
+     * 
+     * @return the {@code SAXParser}.
+     * 
+     * @throws ParserConfigurationException if no matching {@code SAXParser}
+     *         could be found.
+     * @throws SAXException if creating the {@code SAXParser} failed due to some
+     *         other reason.
+     * 
+     * @since Android 1.0
+     */
+    public abstract SAXParser newSAXParser()
+            throws ParserConfigurationException, SAXException;
+
+    /**
+     * Sets a feature in the underlying implementation.
+     * 
+     * @param name the name of the feature. The default Android implementation
+     *             of {@link SAXParser} supports only the following three
+     *             features:
+     *             
+     *             <dl>
+     *               <dt>{@code http://xml.org/sax/features/namespaces}</dt>
+     *               <dd>Sets the state of namespace-awareness.</dd>
+     *
+     *               <dt>
+     *                 {@code http://xml.org/sax/features/namespace-prefixes}
+     *               </dt>
+     *               <dd>Sets the state of namespace prefix processing</dd>
+     *
+     *               <dt>{@code http://xml.org/sax/features/validation}</dt>
+     *               <dd>Sets the state of validation.</dd>
+     *             </dl>
+     *             
+     *             Note that despite the ability to query the validation
+     *             feature, there is currently no validating parser available.
+     *             Also note that currently either namespaces or 
+     *             namespace prefixes can be enabled, but not both at the same 
+     *             time.
+     *             
+     * @param value the status of the feature.
+     * 
+     * @throws ParserConfigurationException if no {@code SAXParser} matching
+     *         the given criteria is available.
+     * @throws SAXNotRecognizedException if the given feature is not known to
+     *         the underlying implementation.
+     * @throws SAXNotSupportedException if the given features is known, but not
+     *         supported by the underlying implementation.
+     *         
+     * @since Android 1.0
+     */
+    public abstract void setFeature(String name, boolean value)
+            throws ParserConfigurationException, SAXNotRecognizedException,
+            SAXNotSupportedException;
+
+    /**
+     * Determines whether the factory is configured to deliver parsers that are
+     * namespace-aware.
+     * 
+     * @param value turns namespace-awareness on or off.
+     * 
+     * @since Android 1.0
+     */
+    public void setNamespaceAware(boolean value) {
+        namespaceAware = value;
+    }
+
+// TODO No XSchema support in Android 1.0. Maybe later.
+//    /**
+//     * Sets the desired XML Schema object.
+//     * 
+//     * @param schema The XML Schema object.
+//     */
+//    public void setSchema(Schema schema) {
+//       this.schema = schema;
+//    }
+
+    /**
+     * Determines whether the factory is configured to deliver parsers that are
+     * validating.
+     * 
+     * @param value turns validation on or off.
+     * 
+     * @since Android 1.0
+     */
+    public void setValidating(boolean value) {
+        validating = value;
+    }
+
+    /**
+     * Determines whether the factory is configured to deliver parsers that are
+     * XInclude-aware.
+     * 
+     * @param value turns XInclude-awareness on or off.
+     * 
+     * @since Android 1.0
+     */
+    public void setXIncludeAware(boolean value) {
+        throw new UnsupportedOperationException();
+    }
+
+}
+
diff --git a/xml/src/main/java/javax/xml/parsers/package.html b/xml/src/main/java/javax/xml/parsers/package.html
new file mode 100644
index 0000000..7e0921d
--- /dev/null
+++ b/xml/src/main/java/javax/xml/parsers/package.html
@@ -0,0 +1,24 @@
+<html>
+  <body>
+    <p>
+      Provides facilities for parsing XML documents and building Document Object
+      Model (DOM) trees from them. The
+      {@link javax.xml.parsers.SAXParserFactory} class serves as an entry point
+      to event-based XML parsing. The
+      {@link javax.xml.parsers.DocumentBuilderFactory} class is an entry point
+      for dealing with DOM trees. Both factories are usually configured
+      before their factory methods are invoked. They then try to create a
+      {@link javax.xml.parsers.SAXParser} or a
+      {@link javax.xml.parsers.DocumentBuilder} (respectively) suiting the
+      application's needs. If none can be found, an Exception is thrown. 
+    </p>
+    <p>
+      Note that in order to cater for resource-constrained environments,
+      Android's XML packages currently only provide DOM Level 2 Core support
+      and a non-validating parser. This means that (a) the interface for the
+      various DOM classes might differ from other implementations and (b)
+      requesting a validating parser will always fail.
+    </p>
+    @since Android 1.0
+  </body>
+</html>
\ No newline at end of file
diff --git a/xml/src/main/java/org/apache/harmony/xml/ExpatAttributes.java b/xml/src/main/java/org/apache/harmony/xml/ExpatAttributes.java
new file mode 100644
index 0000000..ed6cb11
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/ExpatAttributes.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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.harmony.xml;
+
+import org.xml.sax.Attributes;
+
+/**
+ * Wraps native attribute array.
+ */
+abstract class ExpatAttributes implements Attributes {
+
+    /**
+     * Since we don't do validation, pretty much everything is CDATA type.
+     */
+    private static final String CDATA = "CDATA";
+
+    /**
+     * Gets the number of attributes.
+     */
+    public abstract int getLength();
+
+    /**
+     * Gets the pointer to the parser. We need this so we can get to the
+     * interned string pool.
+     */
+    abstract int getParserPointer();
+
+    /**
+     * Gets the pointer to the underlying attribute array. Can be 0 if the
+     * length is 0.
+     */
+    public abstract int getPointer();
+
+    public String getURI(int index) {
+        if (index < 0 || index >= getLength()) {
+            return null;
+        }
+        return getURI(getParserPointer(), getPointer(), index);
+    }
+
+    public String getLocalName(int index) {
+        return (index < 0 || index >= getLength())
+                ? null
+                : getLocalName(getParserPointer(), getPointer(), index);
+    }
+
+    public String getQName(int index) {
+        return (index < 0 || index >= getLength())
+                ? null
+                : getQName(getParserPointer(), getPointer(), index);
+    }
+
+    public String getType(int index) {
+        return (index < 0 || index >= getLength()) ? null : CDATA;
+    }
+
+    public String getValue(int index) {
+        return (index < 0 || index >= getLength())
+                ? null
+                : getValue(getPointer(), index);
+    }
+
+    public int getIndex(String uri, String localName) {
+        if (uri == null) {
+            throw new NullPointerException("uri");
+        }
+        if (localName == null) {
+            throw new NullPointerException("local name");
+        }
+        int pointer = getPointer();
+        if (pointer == 0) {
+            return -1;
+        }
+        return getIndex(pointer, uri, localName);
+    }
+
+    public int getIndex(String qName) {
+        if (qName == null) {
+            throw new NullPointerException("uri");
+        }
+        int pointer = getPointer();
+        if (pointer == 0) {
+            return -1;
+        }
+        return getIndex(pointer, qName);
+    }
+
+    public String getType(String uri, String localName) {
+        if (uri == null) {
+            throw new NullPointerException("uri");
+        }
+        if (localName == null) {
+            throw new NullPointerException("local name");
+        }
+        return getIndex(uri, localName) == -1 ? null : CDATA;
+    }
+
+    public String getType(String qName) {
+        return getIndex(qName) == -1 ? null : CDATA;
+    }
+
+    public String getValue(String uri, String localName) {
+        if (uri == null) {
+            throw new NullPointerException("uri");
+        }
+        if (localName == null) {
+            throw new NullPointerException("local name");
+        }
+        int pointer = getPointer();
+        if (pointer == 0) {
+            return null;
+        }
+        return getValue(pointer, uri, localName);
+    }
+
+    public String getValue(String qName) {
+        if (qName == null) {
+            throw new NullPointerException("qName");
+        }
+        int pointer = getPointer();
+        if (pointer == 0) {
+            return null;
+        }
+        return getValue(pointer, qName);
+    }
+
+    static native String getURI(int pointer, int attributePointer, int index);
+    static native String getLocalName(int pointer, int attributePointer,
+            int index);
+    static native String getQName(int pointer, int attributePointer,
+            int index);
+    static native String getValue(int attributePointer, int index);
+    static native int getIndex(int attributePointer, String uri,
+            String localName);
+    static native int getIndex(int attributePointer, String qName);
+    static native String getValue(int attributePointer,
+            String uri, String localName);
+    static native String getValue(int attributePointer, String qName);
+    static native void freeAttributes(int pointer);
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/ExpatException.java b/xml/src/main/java/org/apache/harmony/xml/ExpatException.java
new file mode 100644
index 0000000..da3db9d
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/ExpatException.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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.harmony.xml;
+
+/**
+ * Used internally to propogate Expat errors. We convert these exceptions into
+ * SAXParseExceptions before propogating them to the client.
+ */
+class ExpatException extends Exception {
+
+    public ExpatException(String message) {
+        super(message);
+    }
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/ExpatParser.java b/xml/src/main/java/org/apache/harmony/xml/ExpatParser.java
new file mode 100644
index 0000000..60d74b8
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/ExpatParser.java
@@ -0,0 +1,794 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.ext.LexicalHandler;
+
+import java.io.Reader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URLConnection;
+import java.net.URL;
+import java.util.logging.Logger;
+import java.util.logging.Level;
+
+/**
+ * Adapts SAX API to the Expat native XML parser. Not intended for reuse
+ * across documents.
+ *
+ * @see org.apache.harmony.xml.ExpatPullParser
+ * @see org.apache.harmony.xml.ExpatReader
+ */
+class ExpatParser {
+
+    private static final int BUFFER_SIZE = 8096; // in bytes
+
+    /** Pointer to XML_Parser instance. */
+    private int pointer;
+
+    private boolean inStartElement = false;
+    private int attributeCount = -1;
+    private int attributePointer = 0;
+
+    private final Locator locator = new ExpatLocator();
+
+    private final ExpatReader xmlReader;
+
+    private final String publicId;
+    private final String systemId;
+
+    private final String encoding;
+
+    private final ExpatAttributes attributes = new CurrentAttributes();
+
+    private static final String OUTSIDE_START_ELEMENT
+            = "Attributes can only be used within the scope of startElement().";
+
+    /** We default to UTF-8 when the user doesn't specify an encoding. */
+    private static final String DEFAULT_ENCODING = "UTF-8";
+
+    /** Encoding used for Java chars, used to parse Readers and Strings */
+    /*package*/ static final String CHARACTER_ENCODING = "UTF-16";
+
+    /** Timeout for HTTP connections (in ms) */
+    private static final int TIMEOUT = 20 * 1000;
+
+    /**
+     * Constructs a new parser with the specified encoding.
+     */
+    /*package*/ ExpatParser(String encoding, ExpatReader xmlReader,
+            boolean processNamespaces, String publicId, String systemId) {
+        this.publicId = publicId;
+        this.systemId = systemId;
+
+        this.xmlReader = xmlReader;
+
+        /*
+         * TODO: Let Expat try to guess the encoding instead of defaulting.
+         * Unfortunately, I don't know how to tell which encoding Expat picked,
+         * so I won't know how to encode "<externalEntity>" below. The solution
+         * I think is to fix Expat to not require the "<externalEntity>"
+         * workaround.
+         */
+        this.encoding = encoding == null ? DEFAULT_ENCODING : encoding;
+        this.pointer = initialize(
+            this.encoding,
+            processNamespaces
+        );
+    }
+
+    /**
+     * Used by {@link EntityParser}.
+     */
+    private ExpatParser(String encoding, ExpatReader xmlReader, int pointer,
+            String publicId, String systemId) {
+        this.encoding = encoding;
+        this.xmlReader = xmlReader;
+        this.pointer = pointer;
+        this.systemId = systemId;
+        this.publicId = publicId;
+    }
+
+    /**
+     * Initializes native resources.
+     *
+     * @return the pointer to the native parser
+     */
+    private native int initialize(String encoding, boolean namespacesEnabled);
+
+    /**
+     * Called at the start of an element.
+     *
+     * @param uri namespace URI of element or "" if namespace processing is
+     *  disabled
+     * @param localName local name of element or "" if namespace processing is
+     *  disabled
+     * @param qName qualified name or "" if namespace processing is enabled
+     * @param attributePointer pointer to native attribute char*--we keep
+     *  a separate pointer so we can detach it from the parser instance
+     * @param attributeCount number of attributes
+     */
+    /*package*/ void startElement(String uri, String localName, String qName,
+            int attributePointer, int attributeCount) throws SAXException {
+        ContentHandler contentHandler = xmlReader.contentHandler;
+        if (contentHandler == null) {
+            return;
+        }
+
+        try {
+            inStartElement = true;
+            this.attributePointer = attributePointer;
+            this.attributeCount = attributeCount;
+
+            contentHandler.startElement(
+                    uri, localName, qName, this.attributes);
+        }
+        finally {
+            inStartElement = false;
+            this.attributeCount = -1;
+            this.attributePointer = 0;
+        }
+    }
+
+    /*package*/ void endElement(String uri, String localName, String qName)
+            throws SAXException {
+        ContentHandler contentHandler = xmlReader.contentHandler;
+        if (contentHandler != null) {
+            contentHandler.endElement(uri, localName, qName);
+        }
+    }
+
+    /*package*/ void text(char[] text, int length) throws SAXException {
+        ContentHandler contentHandler = xmlReader.contentHandler;
+        if (contentHandler != null) {
+            contentHandler.characters(text, 0, length);
+        }
+    }
+
+    /*package*/ void comment(char[] text, int length) throws SAXException {
+        LexicalHandler lexicalHandler = xmlReader.lexicalHandler;
+        if (lexicalHandler != null) {
+            lexicalHandler.comment(text, 0, length);
+        }
+    }
+
+    /*package*/ void startCdata() throws SAXException {
+        LexicalHandler lexicalHandler = xmlReader.lexicalHandler;
+        if (lexicalHandler != null) {
+            lexicalHandler.startCDATA();
+        }
+    }
+
+    /*package*/ void endCdata() throws SAXException {
+        LexicalHandler lexicalHandler = xmlReader.lexicalHandler;
+        if (lexicalHandler != null) {
+            lexicalHandler.endCDATA();
+        }
+    }
+
+    /*package*/ void startNamespace(String prefix, String uri)
+            throws SAXException {
+        ContentHandler contentHandler = xmlReader.contentHandler;
+        if (contentHandler != null) {
+            contentHandler.startPrefixMapping(prefix, uri);
+        }
+    }
+
+    /*package*/ void endNamespace(String prefix) throws SAXException {
+        ContentHandler contentHandler = xmlReader.contentHandler;
+        if (contentHandler != null) {
+            contentHandler.endPrefixMapping(prefix);
+        }
+    }
+
+    /*package*/ void startDtd(String name, String publicId, String systemId)
+            throws SAXException {
+        LexicalHandler lexicalHandler = xmlReader.lexicalHandler;
+        if (lexicalHandler != null) {
+            lexicalHandler.startDTD(name, publicId, systemId);
+        }
+    }
+
+    /*package*/ void endDtd() throws SAXException {
+        LexicalHandler lexicalHandler = xmlReader.lexicalHandler;
+        if (lexicalHandler != null) {
+            lexicalHandler.endDTD();
+        }
+    }
+
+    /*package*/ void processingInstruction(String target, String data)
+            throws SAXException {
+        ContentHandler contentHandler = xmlReader.contentHandler;
+        if (contentHandler != null) {
+            contentHandler.processingInstruction(target, data);
+        }        
+    }
+
+    /**
+     * Handles an external entity.
+     *
+     * @param context to be passed back to Expat when we parse the entity
+     * @param publicId the publicId of the entity
+     * @param systemId the systemId of the entity
+     */
+    /*package*/ void handleExternalEntity(String context, String publicId,
+            String systemId) throws SAXException, IOException {
+        EntityResolver entityResolver = xmlReader.entityResolver;
+        if (entityResolver == null) {
+            return;
+        }
+
+        /*
+         * The spec. is terribly under-specified here. It says that if the
+         * systemId is a URL, we should try to resolve it, but it doesn't
+         * specify how to tell whether or not the systemId is a URL let alone
+         * how to resolve it.
+         *
+         * Other implementations do various insane things. We try to keep it
+         * simple: if the systemId parses as a URI and it's relative, we try to
+         * resolve it against the parent document's systemId. If anything goes
+         * wrong, we go with the original systemId. If crazybob had designed
+         * the API, he would have left all resolving to the EntityResolver.
+         */
+        if (this.systemId != null) {
+            try {
+                URI systemUri = new URI(systemId);
+                if (!systemUri.isAbsolute() && !systemUri.isOpaque()) {
+                    // It could be relative (or it may not be a URI at all!)
+                    URI baseUri = new URI(this.systemId);
+                    systemUri = baseUri.resolve(systemUri);
+
+                    // Replace systemId w/ resolved URI
+                    systemId = systemUri.toString();
+                }
+            } catch (Exception e) {
+                Logger.getLogger(ExpatParser.class.getName()).log(Level.INFO,
+                        "Could not resolve '" + systemId + "' relative to"
+                        + " '" + this.systemId + "' at " + locator, e);
+            }
+        }
+
+        InputSource inputSource = entityResolver.resolveEntity(
+                publicId, systemId);
+        if (inputSource == null) {
+            /*
+             * The spec. actually says that we should try to treat systemId
+             * as a URL and download and parse its contents here, but an
+             * entity resolver can easily accomplish the same by returning
+             * new InputSource(systemId).
+             *
+             * Downloading external entities by default would result in several
+             * unwanted DTD downloads, not to mention pose a security risk
+             * when parsing untrusted XML (http://tinyurl.com/56ggrk),
+             * so we just do nothing instead. This also enables the user to
+             * opt out of entity parsing when using
+             * {@link org.xml.sax.helpers.DefaultHandler}, something that
+             * wouldn't be possible otherwise.
+             */
+            return;
+        }
+
+        String encoding = pickEncoding(inputSource);
+        int pointer = createEntityParser(this.pointer, context, encoding);
+        try {
+            EntityParser entityParser = new EntityParser(encoding, xmlReader,
+                    pointer, inputSource.getPublicId(),
+                    inputSource.getSystemId());
+
+            parseExternalEntity(entityParser, inputSource);
+        } finally {
+            releaseParser(pointer);
+        }
+    }
+
+    /**
+     * Picks an encoding for an external entity. Defaults to UTF-8.
+     */
+    private String pickEncoding(InputSource inputSource) {
+        Reader reader = inputSource.getCharacterStream();
+        if (reader != null) {
+            return CHARACTER_ENCODING;
+        }
+
+        String encoding = inputSource.getEncoding();
+        return encoding == null ? DEFAULT_ENCODING : encoding;
+    }
+
+    /**
+     * Parses the the external entity provided by the input source.
+     */
+    private void parseExternalEntity(ExpatParser entityParser,
+            InputSource inputSource) throws IOException, SAXException {
+        /*
+         * Expat complains if the external entity isn't wrapped with a root
+         * element so we add one and ignore it later on during parsing.
+         */
+        
+        // Try the character stream.
+        Reader reader = inputSource.getCharacterStream();
+        if (reader != null) {
+            try {
+                entityParser.append("<externalEntity>");
+                entityParser.parseFragment(reader);
+                entityParser.append("</externalEntity>");
+            } finally {
+                // TODO: Don't eat original exception when close() throws.
+                reader.close();
+            }
+            return;
+        }
+
+        // Try the byte stream.
+        InputStream in = inputSource.getByteStream();
+        if (in != null) {
+            try {
+                entityParser.append("<externalEntity>"
+                        .getBytes(entityParser.encoding));
+                entityParser.parseFragment(in);
+                entityParser.append("</externalEntity>"
+                        .getBytes(entityParser.encoding));
+            } finally {
+                // TODO: Don't eat original exception when close() throws.
+                in.close();
+            }
+            return;
+        }
+
+        // Make sure we use the user-provided systemId.
+        String systemId = inputSource.getSystemId();
+        if (systemId == null) {
+            // TODO: We could just try our systemId here.
+            throw new ParseException("No input specified.", locator);
+        }
+
+        // Try the system id.
+        in = openUrl(systemId);
+        try {
+            entityParser.append("<externalEntity>"
+                    .getBytes(entityParser.encoding));
+            entityParser.parseFragment(in);
+            entityParser.append("</externalEntity>"
+                    .getBytes(entityParser.encoding));
+        } finally {
+            in.close();
+        }
+    }
+
+    /**
+     * Creates a native entity parser.
+     *
+     * @param parentPointer pointer to parent Expat parser
+     * @param context passed to {@link #handleExternalEntity}
+     * @param encoding
+     * @return pointer to native parser
+     */
+    private static native int createEntityParser(int parentPointer,
+            String context, String encoding);
+
+    /**
+     * Appends part of an XML document. This parser will parse the given XML to
+     * the extent possible and dispatch to the appropriate methods.
+     *
+     * @param xml a whole or partial snippet of XML
+     * @throws SAXException if an error occurs during parsing
+     */
+    /*package*/ void append(String xml) throws SAXException {
+        try {
+            append(this.pointer, xml, false);
+        } catch (ExpatException e) {
+            throw new ParseException(e.getMessage(), this.locator);
+        }
+    }
+
+    private native void append(int pointer, String xml, boolean isFinal)
+            throws SAXException, ExpatException;
+
+    /**
+     * Appends part of an XML document. This parser will parse the given XML to
+     * the extent possible and dispatch to the appropriate methods.
+     *
+     * @param xml a whole or partial snippet of XML
+     * @param offset into the char[]
+     * @param length of characters to use
+     * @throws SAXException if an error occurs during parsing
+     */
+    /*package*/ void append(char[] xml, int offset, int length)
+            throws SAXException {
+        try {
+            append(this.pointer, xml, offset, length);
+        } catch (ExpatException e) {
+            throw new ParseException(e.getMessage(), this.locator);
+        }
+    }
+
+    private native void append(int pointer, char[] xml, int offset,
+            int length) throws SAXException, ExpatException;
+
+    /**
+     * Appends part of an XML document. This parser will parse the given XML to
+     * the extent possible and dispatch to the appropriate methods.
+     *
+     * @param xml a whole or partial snippet of XML
+     * @throws SAXException if an error occurs during parsing
+     */
+    /*package*/ void append(byte[] xml) throws SAXException {
+        append(xml, 0, xml.length);
+    }
+
+    /**
+     * Appends part of an XML document. This parser will parse the given XML to
+     * the extent possible and dispatch to the appropriate methods.
+     *
+     * @param xml a whole or partial snippet of XML
+     * @param offset into the byte[]
+     * @param length of bytes to use
+     * @throws SAXException if an error occurs during parsing
+     */
+    /*package*/ void append(byte[] xml, int offset, int length)
+            throws SAXException {
+        try {
+            append(this.pointer, xml, offset, length);
+        } catch (ExpatException e) {
+            throw new ParseException(e.getMessage(), this.locator);
+        }
+    }
+
+    private native void append(int pointer, byte[] xml, int offset,
+            int length) throws SAXException, ExpatException;
+
+    /**
+     * Parses an XML document from the given input stream.
+     */
+    /*package*/ void parseDocument(InputStream in) throws IOException,
+            SAXException {
+        startDocument();
+        parseFragment(in);
+        finish();
+        endDocument();
+    }
+
+    /**
+     * Parses an XML Document from the given reader.
+     */
+    /*package*/ void parseDocument(Reader in) throws IOException, SAXException {
+        startDocument();
+        parseFragment(in);
+        finish();
+        endDocument();
+    }
+
+    /**
+     * Parses XML from the given Reader.
+     */
+    private void parseFragment(Reader in) throws IOException, SAXException {
+        char[] buffer = new char[BUFFER_SIZE / 2];
+        int length;
+        while ((length = in.read(buffer)) != -1) {
+            try {
+                append(this.pointer, buffer, 0, length);
+            } catch (ExpatException e) {
+                throw new ParseException(e.getMessage(), locator);
+            }
+        }
+    }
+
+    /**
+     * Parses XML from the given input stream.
+     */
+    private void parseFragment(InputStream in)
+            throws IOException, SAXException {
+        byte[] buffer = new byte[BUFFER_SIZE];
+        int length;
+        while ((length = in.read(buffer)) != -1) {
+            try {
+                append(this.pointer, buffer, 0, length);
+            } catch (ExpatException e) {
+                throw new ParseException(e.getMessage(), this.locator);
+            }
+        }
+    }
+
+    private void startDocument() throws SAXException {
+        ContentHandler contentHandler = xmlReader.contentHandler;
+        if (contentHandler != null) {
+            contentHandler.setDocumentLocator(this.locator);
+            contentHandler.startDocument();
+        }
+    }
+
+    private void endDocument() throws SAXException {
+        ContentHandler contentHandler;
+        contentHandler = xmlReader.contentHandler;
+        if (contentHandler != null) {
+            contentHandler.endDocument();
+        }
+    }
+
+    /**
+     * Indicate that we're finished parsing.
+     *
+     * @throws SAXException if the xml is incomplete
+     */
+    /*package*/ void finish() throws SAXException {
+        try {
+            append(this.pointer, "", true);
+        } catch (ExpatException e) {
+            throw new ParseException(e.getMessage(), this.locator);
+        }
+    }
+
+    @Override
+    @SuppressWarnings("FinalizeDoesntCallSuperFinalize")
+    protected synchronized void finalize() throws Throwable {
+        if (this.pointer != 0) {
+            release(this.pointer);
+            this.pointer = 0;
+        }
+    }
+
+    /**
+     * Releases all native objects.
+     */
+    private native void release(int pointer);
+
+    /**
+     * Releases native parser only.
+     */
+    private static native void releaseParser(int pointer);
+
+    /**
+     * Initialize static resources.
+     */
+    private static native void staticInitialize(String emptyString);
+
+    static {
+        staticInitialize("");
+    }
+
+    /**
+     * Gets the current line number within the XML file.
+     */
+    private int line() {
+        return line(this.pointer);
+    }
+
+    private static native int line(int pointer);
+
+    /**
+     * Gets the current column number within the XML file.
+     */
+    private int column() {
+        return column(this.pointer);
+    }
+
+    private static native int column(int pointer);
+
+    /**
+     * Clones the current attributes so they can be used outside of
+     * startElement().
+     */
+    /*package*/ Attributes cloneAttributes() {
+        if (!inStartElement) {
+            throw new IllegalStateException(OUTSIDE_START_ELEMENT);
+        }
+
+        if (attributeCount == 0) {
+            return ClonedAttributes.EMPTY;
+        }
+
+        int clonePointer
+                = cloneAttributes(this.attributePointer, this.attributeCount);
+        return new ClonedAttributes(pointer, clonePointer, attributeCount);
+    }
+
+    private static native int cloneAttributes(int pointer, int attributeCount);
+
+    /**
+     * Used for cloned attributes.
+     */
+    private static class ClonedAttributes extends ExpatAttributes {
+
+        private static final Attributes EMPTY = new ClonedAttributes(0, 0, 0);
+
+        private final int parserPointer;
+        private int pointer;
+        private final int length;
+
+        /**
+         * Constructs a Java wrapper for native attributes.
+         *
+         * @param parserPointer pointer to the parse, can be 0 if length is 0.
+         * @param pointer pointer to the attributes array, can be 0 if the
+         *  length is 0.
+         * @param length number of attributes
+         */
+        private ClonedAttributes(int parserPointer, int pointer, int length) {
+            this.parserPointer = parserPointer;
+            this.pointer = pointer;
+            this.length = length;
+        }
+
+        @Override
+        public int getParserPointer() {
+            return this.parserPointer;
+        }
+
+        @Override
+        public int getPointer() {
+            return pointer;
+        }
+
+        @Override
+        public int getLength() {
+            return length;
+        }
+
+        @Override
+        @SuppressWarnings("FinalizeDoesntCallSuperFinalize")
+        protected synchronized void finalize() throws Throwable {
+            if (pointer != 0) {
+                freeAttributes(pointer);
+                pointer = 0;
+            }
+        }
+    }
+
+    private class ExpatLocator implements Locator {
+
+        public String getPublicId() {
+            return publicId;
+        }
+
+        public String getSystemId() {
+            return systemId;
+        }
+
+        public int getLineNumber() {
+            return line();
+        }
+
+        public int getColumnNumber() {
+            return column();
+        }
+
+        @Override
+        public String toString() {
+            return "Locator[publicId: " + publicId + ", systemId: " + systemId
+                + ", line: " + getLineNumber()
+                + ", column: " + getColumnNumber() + "]";
+        }
+    }
+
+    /**
+     * Attributes that are only valid during startElement().
+     */
+    private class CurrentAttributes extends ExpatAttributes {
+
+        @Override
+        public int getParserPointer() {
+            return pointer;
+        }
+
+        @Override
+        public int getPointer() {
+            if (!inStartElement) {
+                throw new IllegalStateException(OUTSIDE_START_ELEMENT);
+            }
+            return attributePointer;
+        }
+
+        @Override
+        public int getLength() {
+            if (!inStartElement) {
+                throw new IllegalStateException(OUTSIDE_START_ELEMENT);
+            }
+            return attributeCount;
+        }
+    }
+
+    /**
+     * Includes line and column in the message.
+     */
+    private static class ParseException extends SAXParseException {
+
+        private ParseException(String message, Locator locator) {
+            super(makeMessage(message, locator), locator);
+        }
+
+        private static String makeMessage(String message, Locator locator) {
+            return makeMessage(message, locator.getLineNumber(),
+                    locator.getColumnNumber());
+        }
+
+        private static String makeMessage(
+                String message, int line, int column) {
+            return "At line " + line + ", column "
+                    + column + ": " + message;
+        }
+    }
+    
+    /**
+     * Opens an InputStream for the given URL.
+     */
+    /*package*/ static InputStream openUrl(String url) throws IOException {
+        try {
+            URLConnection urlConnection = new URL(url).openConnection();
+            urlConnection.setConnectTimeout(TIMEOUT);
+            urlConnection.setReadTimeout(TIMEOUT);
+            urlConnection.setDoInput(true);
+            urlConnection.setDoOutput(false);
+            return urlConnection.getInputStream();
+        } catch (Exception e) {
+            IOException ioe = new IOException("Couldn't open " + url);
+            ioe.initCause(e);
+            throw ioe;
+        }
+    }
+
+    /**
+     * Parses an external entity.
+     */
+    private static class EntityParser extends ExpatParser {
+
+        private int depth = 0; 
+
+        private EntityParser(String encoding, ExpatReader xmlReader,
+                int pointer, String publicId, String systemId) {
+            super(encoding, xmlReader, pointer, publicId, systemId);
+        }
+
+        @Override
+        void startElement(String uri, String localName, String qName,
+                int attributePointer, int attributeCount) throws SAXException {
+            /*
+             * Skip topmost element generated by our workaround in
+             * {@link #handleExternalEntity}.
+             */
+            if (depth++ > 0) {
+                super.startElement(uri, localName, qName, attributePointer,
+                        attributeCount);
+            }
+        }
+        
+        @Override
+        void endElement(String uri, String localName, String qName)
+                throws SAXException {
+            if (--depth > 0) {
+                super.endElement(uri, localName, qName);
+            }
+        }
+
+        @Override
+        @SuppressWarnings("FinalizeDoesntCallSuperFinalize")
+        protected synchronized void finalize() throws Throwable {
+            /*
+             * Don't release our native resources. We do so explicitly in
+             * {@link #handleExternalEntity} and we don't want to release the
+             * parsing context--our parent is using it.
+             */
+        }
+    }
+}
+
diff --git a/xml/src/main/java/org/apache/harmony/xml/ExpatPullParser.java b/xml/src/main/java/org/apache/harmony/xml/ExpatPullParser.java
new file mode 100644
index 0000000..4759718
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/ExpatPullParser.java
@@ -0,0 +1,964 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+/**
+ * Fast, partial XmlPullParser implementation based upon Expat. Does not
+ * support validation or {@code DOCTYPE} processing.
+ */
+public class ExpatPullParser implements XmlPullParser {
+    /**
+     * This feature is identified by http://xmlpull.org/v1/doc/features.html#relaxed
+     * If this feature is supported that means that XmlPull parser will be
+     * lenient when checking XML well formedness.
+     * NOTE: use it only if XML input is not well-formed and in general usage
+     * if this feature is discouraged
+     * NOTE: as there is no definition of what is relaxed XML parsing
+     * therefore what parser will do completely depends on implementation used
+     */
+    public static final String FEATURE_RELAXED =
+            "http://xmlpull.org/v1/doc/features.html#relaxed";
+
+    private static final int BUFFER_SIZE = 8096;
+
+    private static final String NOT_A_START_TAG = "This is not a start tag.";
+
+    private Document document;
+    private boolean processNamespaces = false;
+    private boolean relaxed = false;
+
+    public void setFeature(String name, boolean state)
+            throws XmlPullParserException {
+        if (name == null) {
+            // Required by API.          
+            throw new IllegalArgumentException("Null feature name");
+        }
+
+        if (name.equals(FEATURE_PROCESS_NAMESPACES)) {
+            processNamespaces = state;
+            return;
+        }
+
+        if (name.equals(FEATURE_RELAXED)) {
+            relaxed = true;
+            return;
+        }
+
+        // You're free to turn these features off because we don't support them.
+        if (!state && (name.equals(FEATURE_REPORT_NAMESPACE_ATTRIBUTES)
+                || name.equals(FEATURE_PROCESS_DOCDECL)
+                || name.equals(FEATURE_VALIDATION))) {
+            return;
+        }
+
+        throw new XmlPullParserException("Unsupported feature: " + name);
+    }
+
+    public boolean getFeature(String name) {
+        if (name == null) {
+            // Required by API.
+            throw new IllegalArgumentException("Null feature name");
+        }
+
+        // We always support namespaces, but no other features.
+        return name.equals(FEATURE_PROCESS_NAMESPACES) && processNamespaces;
+    }
+
+    /**
+     * Returns true if this parser processes namespaces.
+     *
+     * @see #setNamespaceProcessingEnabled(boolean)
+     */
+    public boolean isNamespaceProcessingEnabled() {
+        return processNamespaces;
+    }
+
+    /**
+     * Enables or disables namespace processing. Set to false by default.
+     *
+     * @see #isNamespaceProcessingEnabled()
+     */
+    public void setNamespaceProcessingEnabled(boolean processNamespaces) {
+        this.processNamespaces = processNamespaces;
+    }
+
+    public void setProperty(String name, Object value)
+            throws XmlPullParserException {
+        if (name == null) {
+            // Required by API.
+            throw new IllegalArgumentException("Null feature name");
+        }
+
+        // We don't support any properties.
+        throw new XmlPullParserException("Properties aren't supported.");
+    }
+
+    public Object getProperty(String name) {
+        return null;
+    }
+
+    public void setInput(Reader in) throws XmlPullParserException {
+        this.document = new CharDocument(in, processNamespaces);
+    }
+
+    public void setInput(InputStream in, String encodingName)
+            throws XmlPullParserException {
+        this.document = new ByteDocument(in, encodingName, processNamespaces);
+    }
+
+    public String getInputEncoding() {
+        return this.document.getEncoding();
+    }
+
+    /**
+     * Not supported.
+     *
+     * @throws UnsupportedOperationException always
+     */
+    public void defineEntityReplacementText(String entityName,
+            String replacementText) throws XmlPullParserException {
+        throw new UnsupportedOperationException();
+    }
+
+    public int getNamespaceCount(int depth) throws XmlPullParserException {
+        return document.currentEvent.namespaceStack.countAt(depth);
+    }
+
+    public String getNamespacePrefix(int pos) throws XmlPullParserException {
+        String prefix = document.currentEvent.namespaceStack.prefixAt(pos);
+        @SuppressWarnings("StringEquality")
+        boolean hasPrefix = prefix != "";
+        return hasPrefix ? prefix : null;
+    }
+
+    public String getNamespaceUri(int pos) throws XmlPullParserException {
+        return document.currentEvent.namespaceStack.uriAt(pos);
+    }
+
+    public String getNamespace(String prefix) {
+        // In XmlPullParser API, null == default namespace.
+        if (prefix == null) {
+            // Internally, we use empty string instead of null.
+            prefix = "";
+        }
+
+        return document.currentEvent.namespaceStack.uriFor(prefix);
+    }
+
+    public int getDepth() {
+        return this.document.getDepth();
+    }
+
+    public String getPositionDescription() {
+        return "line " + getLineNumber() + ", column " + getColumnNumber();
+    }
+
+    /**
+     * Not supported.
+     *
+     * @return {@literal -1} always
+     */
+    public int getLineNumber() {
+        // We would have to record the line number in each event.
+        return -1;
+    }
+
+    /**
+     * Not supported.
+     *
+     * @return {@literal -1} always
+     */
+    public int getColumnNumber() {
+        // We would have to record the column number in each event.
+        return -1;
+    }
+
+    public boolean isWhitespace() throws XmlPullParserException {
+        if (getEventType() != TEXT) {
+            throw new XmlPullParserException("Not on text.");
+        }
+
+        String text = getText();
+
+        if (text.length() == 0) {
+            return true;
+        }
+
+        int length = text.length();
+        for (int i = 0; i < length; i++) {
+            if (!Character.isWhitespace(text.charAt(i))) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    public String getText() {
+        final StringBuilder builder = this.document.currentEvent.getText();
+        return builder == null ? null : builder.toString();
+    }
+
+    public char[] getTextCharacters(int[] holderForStartAndLength) {
+        final StringBuilder builder = this.document.currentEvent.getText();
+
+        final int length = builder.length();
+        char[] characters = new char[length];
+        builder.getChars(0, length, characters, 0);
+
+        holderForStartAndLength[0] = 0;
+        holderForStartAndLength[1] = length;
+
+        return characters;
+    }
+
+    public String getNamespace() {
+        return this.document.currentEvent.getNamespace();
+    }
+
+    public String getName() {
+        return this.document.currentEvent.getName();
+    }
+
+    /**
+     * Not supported.
+     *
+     * @throws UnsupportedOperationException always
+     */
+    public String getPrefix() {
+        throw new UnsupportedOperationException();
+    }
+
+    public boolean isEmptyElementTag() throws XmlPullParserException {
+        return this.document.isCurrentElementEmpty();
+    }
+
+    public int getAttributeCount() {
+        return this.document.currentEvent.getAttributeCount();
+    }
+
+    public String getAttributeNamespace(int index) {
+        return this.document.currentEvent.getAttributeNamespace(index);
+    }
+
+    public String getAttributeName(int index) {
+        return this.document.currentEvent.getAttributeName(index);
+    }
+
+    /**
+     * Not supported.
+     *
+     * @throws UnsupportedOperationException always
+     */
+    public String getAttributePrefix(int index) {
+        throw new UnsupportedOperationException();
+    }
+
+    public String getAttributeType(int index) {
+        return "CDATA";
+    }
+
+    public boolean isAttributeDefault(int index) {
+        return false;
+    }
+
+    public String getAttributeValue(int index) {
+        return this.document.currentEvent.getAttributeValue(index);
+    }
+
+    public String getAttributeValue(String namespace, String name) {
+        return this.document.currentEvent.getAttributeValue(namespace, name);
+    }
+
+    public int getEventType() throws XmlPullParserException {
+        return this.document.currentEvent.getType();
+    }
+
+    public int next() throws XmlPullParserException, IOException {
+        return this.document.dequeue();
+    }
+
+    /**
+     * Not supported.
+     *
+     * @throws UnsupportedOperationException always
+     */
+    public int nextToken() throws XmlPullParserException, IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    public void require(int type, String namespace, String name)
+            throws XmlPullParserException, IOException {
+        if (type != getEventType()
+                || (namespace != null && !namespace.equals(getNamespace()))
+                || (name != null && !name.equals(getName()))) {
+            throw new XmlPullParserException("expected "
+                    + TYPES[type] + getPositionDescription());
+        }
+    }
+
+    public String nextText() throws XmlPullParserException, IOException {
+        if (this.document.currentEvent.getType() != START_TAG)
+            throw new XmlPullParserException("Not on start tag.");
+
+        int next = this.document.dequeue();
+        switch (next) {
+            case TEXT: return getText();
+            case END_TAG: return "";
+            default: throw new XmlPullParserException(
+                "Unexpected event type: " + TYPES[next]);
+        }
+    }
+
+    public int nextTag() throws XmlPullParserException, IOException {
+        int eventType = next();
+        if (eventType == TEXT && isWhitespace()) {
+            eventType = next();
+        }
+        if (eventType != START_TAG && eventType != END_TAG) {
+            throw new XmlPullParserException(
+                "Expected start or end tag", this, null);
+        }
+        return eventType;
+    }
+
+    /**
+     * Immutable namespace stack. Pushing a new namespace on to the stack
+     * only results in one object allocation. Most operations are O(N) where
+     * N is the stack size. Accessing recently pushed namespaces, like those
+     * for the current element, is significantly faster.
+     */
+    static class NamespaceStack {
+
+        /** An empty stack. */
+        static final NamespaceStack EMPTY = new NamespaceStack();
+
+        private final NamespaceStack parent;
+        private final String prefix;
+        private final String uri;
+        private final int index;
+        private final int depth;
+
+        /**
+         * Constructs an actual namespace stack node. Internally, the nodes
+         * and the stack are one in the same making for a very efficient
+         * implementation. The user just sees an immutable stack and the
+         * builder.
+         */
+        private NamespaceStack(NamespaceStack parent, String prefix,
+                String uri, int depth) {
+            this.parent = parent;
+            this.prefix = prefix;
+            this.uri = uri;
+            this.index = parent.index + 1;
+            this.depth = depth;
+        }
+
+        /**
+         * Constructs a dummy node which only serves to point to the bottom
+         * of the stack. Using an actual node instead of null simplifies the
+         * code.
+         */
+        private NamespaceStack() {
+            this.parent = null;
+            this.prefix = null;
+            this.uri = null;
+
+            // This node has an index of -1 since the actual first node in the
+            // stack has index 0.
+            this.index = -1;
+            
+            // The actual first node will have a depth of 1.
+            this.depth = 0;
+        }
+
+        String uriFor(String prefix) {
+            for (NamespaceStack node = this; node.index >= 0;
+                    node = node.parent) {
+                if (node.prefix.equals(prefix)) {
+                    return node.uri;
+                }
+            }
+
+            // Not found.
+            return null;
+        }
+
+        /**
+         * Gets the prefix at the given index in the stack.
+         */
+        String prefixAt(int index) {
+            return nodeAt(index).prefix;
+        }
+
+        /**
+         * Gets the URI at the given index in the stack.
+         */
+        String uriAt(int index) {
+            return nodeAt(index).uri;
+        }
+
+        private NamespaceStack nodeAt(int index) {
+            if (index > this.index) {
+                throw new IndexOutOfBoundsException("Index > size.");
+            }
+            if (index < 0) {
+                throw new IndexOutOfBoundsException("Index < 0.");
+            }
+
+            NamespaceStack node = this;
+            while (index != node.index) {
+                node = node.parent;
+            }
+            return node;
+        }
+
+        /**
+         * Gets the size of the stack at the given element depth.
+         */
+        int countAt(int depth) {
+            if (depth > this.depth) {
+                throw new IndexOutOfBoundsException("Depth > maximum.");
+            }
+            if (depth < 0) {
+                throw new IndexOutOfBoundsException("Depth < 0.");
+            }
+
+            NamespaceStack node = this;
+            while (depth < node.depth) {
+                node = node.parent;
+            }
+            return node.index + 1;         
+        }
+
+        /** Builds a NamespaceStack. */
+        static class Builder {
+
+            NamespaceStack top = EMPTY;
+
+            /**
+             * Pushes a namespace onto the stack.
+             *
+             * @param depth of the element upon which the namespace was
+             *  declared
+             */
+            void push(String prefix, String uri, int depth) {
+                top = new NamespaceStack(top, prefix, uri, depth);
+            }
+
+            /**
+             * Pops all namespaces from the given element depth.
+             */
+            void pop(int depth) {
+                // Remove all nodes at the specified depth.
+                while (top != null && top.depth == depth) {
+                    top = top.parent;
+                }
+            }
+
+            /** Returns the current stack. */
+            NamespaceStack build() {
+                return top;
+            }
+        }
+    }
+
+    /**
+     * Base class for events. Implements event chaining and defines event API
+     * along with common implementations which can be overridden.
+     */
+    static abstract class Event {
+
+        /** Element depth at the time of this event. */
+        final int depth;
+
+        /** The namespace stack at the time of this event. */
+        final NamespaceStack namespaceStack;
+
+        /** Next event in the queue. */ 
+        Event next = null;
+
+        Event(int depth, NamespaceStack namespaceStack) {
+            this.depth = depth;
+            this.namespaceStack = namespaceStack;
+        }
+
+        void setNext(Event next) {
+            this.next = next;
+        }
+
+        Event getNext() {
+            return next;
+        }
+
+        StringBuilder getText() {
+            return null;
+        }
+
+        String getNamespace() {
+            return null;
+        }
+
+        String getName() {
+            return null;
+        }
+
+        int getAttributeCount() {
+            return -1;
+        }
+
+        String getAttributeNamespace(int index) {
+            throw new IndexOutOfBoundsException(NOT_A_START_TAG);
+        }
+
+        String getAttributeName(int index) {
+            throw new IndexOutOfBoundsException(NOT_A_START_TAG);
+        }
+
+        String getAttributeValue(int index) {
+            throw new IndexOutOfBoundsException(NOT_A_START_TAG);
+        }
+
+        abstract int getType();
+
+        String getAttributeValue(String namespace, String name) {
+            throw new IndexOutOfBoundsException(NOT_A_START_TAG);
+        }
+
+        public int getDepth() {
+            return this.depth;
+        }
+    }
+
+    static class StartDocumentEvent extends Event {
+
+        public StartDocumentEvent() {
+            super(0, NamespaceStack.EMPTY);
+        }
+
+        @Override
+        int getType() {
+            return START_DOCUMENT;
+        }
+    }
+
+    static class StartTagEvent extends Event {
+
+        final String name;
+        final String namespace;
+        final Attributes attributes;
+        final boolean processNamespaces;
+
+        StartTagEvent(String namespace,
+                String name,
+                ExpatParser expatParser,
+                int depth,
+                NamespaceStack namespaceStack,
+                boolean processNamespaces) {
+            super(depth, namespaceStack);
+            this.namespace = namespace;
+            this.name = name;
+            this.attributes = expatParser.cloneAttributes();
+            this.processNamespaces = processNamespaces;
+        }
+
+        @Override
+        String getNamespace() {
+            return namespace;
+        }
+
+        @Override
+        String getName() {
+            return name;
+        }
+
+        @Override
+        int getAttributeCount() {
+            return attributes.getLength();
+        }
+
+        @Override
+        String getAttributeNamespace(int index) {
+            return attributes.getURI(index);
+        }
+
+        @Override
+        String getAttributeName(int index) {
+            return processNamespaces ? attributes.getLocalName(index)
+                    : attributes.getQName(index);
+        }
+
+        @Override
+        String getAttributeValue(int index) {
+            return attributes.getValue(index);
+        }
+
+        @Override
+        String getAttributeValue(String namespace, String name) {
+            if (namespace == null) {
+                namespace = "";
+            }
+
+            return attributes.getValue(namespace, name);
+        }
+
+        @Override
+        int getType() {
+            return START_TAG;
+        }
+    }
+
+    static class EndTagEvent extends Event {
+
+        final String namespace;
+        final String localName;
+
+        EndTagEvent(String namespace, String localName, int depth,
+                NamespaceStack namespaceStack) {
+            super(depth, namespaceStack);
+            this.namespace = namespace;
+            this.localName = localName;
+        }
+
+        @Override
+        String getName() {
+            return this.localName;
+        }
+
+        @Override
+        String getNamespace() {
+            return this.namespace;
+        }
+
+        @Override
+        int getType() {
+            return END_TAG;
+        }
+    }
+
+    static class TextEvent extends Event {
+
+        final StringBuilder builder;
+
+        public TextEvent(int initialCapacity, int depth,
+                NamespaceStack namespaceStack) {
+            super(depth, namespaceStack);
+            this.builder = new StringBuilder(initialCapacity);
+        }
+
+        @Override
+        int getType() {
+            return TEXT;
+        }
+
+        @Override
+        StringBuilder getText() {
+            return this.builder;
+        }
+
+        void append(char[] text, int start, int length) {
+            builder.append(text, start, length);
+        }
+    }
+
+    static class EndDocumentEvent extends Event {
+
+        EndDocumentEvent() {
+            super(0, NamespaceStack.EMPTY);
+        }
+
+        @Override
+        Event getNext() {
+            throw new IllegalStateException("End of document.");
+        }
+
+        @Override
+        void setNext(Event next) {
+            throw new IllegalStateException("End of document.");
+        }
+
+        @Override
+        int getType() {
+            return END_DOCUMENT;
+        }
+    }
+
+    /**
+     * Encapsulates the parsing context of the current document.
+     */
+    abstract class Document {
+
+        final String encoding;
+        final ExpatParser parser;
+        final boolean processNamespaces;
+
+        TextEvent textEvent = null;
+        boolean finished = false;
+
+        Document(String encoding, boolean processNamespaces) {
+            this.encoding = encoding;
+            this.processNamespaces = processNamespaces;
+
+            ExpatReader xmlReader = new ExpatReader();
+            xmlReader.setContentHandler(new SaxHandler());
+
+            this.parser = new ExpatParser(
+                    encoding, xmlReader, processNamespaces, null, null);
+        }
+
+        /** Namespace stack builder. */
+        NamespaceStack.Builder namespaceStackBuilder
+                = new NamespaceStack.Builder();
+        
+        Event currentEvent = new StartDocumentEvent();
+        Event last = currentEvent;
+
+        /**
+         * Sends some more XML to the parser.
+         */
+        void pump() throws IOException, XmlPullParserException {
+            if (this.finished) {
+                return;
+            }
+
+            int length = buffer();
+
+            // End of document.
+            if (length == -1) {
+                this.finished = true;
+                if (!relaxed) {
+                    try {
+                        parser.finish();
+                    } catch (SAXException e) {
+                        throw new XmlPullParserException(
+                            "Premature end of document.", ExpatPullParser.this, e);
+                    }
+                }
+                add(new EndDocumentEvent());
+                return;
+            }
+
+            if (length == 0) {
+                return;
+            }
+
+            flush(parser, length);
+        }
+
+        /**
+         * Reads data into the buffer.
+         *
+         * @return the length of data buffered or {@code -1} if we've reached
+         *  the end of the data.
+         */
+        abstract int buffer() throws IOException;
+
+        /**
+         * Sends buffered data to the parser.
+         *
+         * @param parser the parser to flush to
+         * @param length of data buffered
+         */
+        abstract void flush(ExpatParser parser, int length)
+                throws XmlPullParserException;
+
+        /**
+         * Adds an event.
+         */
+        void add(Event event) {
+            // Flush pre-exising text event if necessary.
+            if (textEvent != null) {
+                last.setNext(textEvent);
+                last = textEvent;
+                textEvent = null;
+            }
+
+            last.setNext(event);
+            last = event;
+        }
+
+        /**
+         * Moves to the next event in the queue.
+         *
+         * @return type of next event
+         */
+        int dequeue() throws XmlPullParserException, IOException {
+            Event next;
+
+            while ((next = currentEvent.getNext()) == null) {
+                pump();
+            }
+
+            currentEvent.next = null;
+            currentEvent = next;
+
+            return currentEvent.getType();
+        }
+
+        String getEncoding() {
+            return this.encoding;
+        }
+
+        int getDepth() {
+            return currentEvent.getDepth();
+        }
+
+        /**
+         * Returns true if we're on a start element and the next event is
+         * its corresponding end element.
+         *
+         * @throws XmlPullParserException if we aren't on a start element
+         */
+        boolean isCurrentElementEmpty() throws XmlPullParserException {
+            if (currentEvent.getType() != START_TAG) {
+                throw new XmlPullParserException(NOT_A_START_TAG);
+            }
+
+            Event next;
+
+            try {
+                while ((next = currentEvent.getNext()) == null) {
+                    pump();
+                }
+            } catch (IOException ex) {
+                throw new XmlPullParserException(ex.toString());
+            }
+
+            return next.getType() == END_TAG;
+        }
+
+        private class SaxHandler implements ContentHandler {
+
+            int depth = 0;
+
+            public void startPrefixMapping(String prefix, String uri)
+                    throws SAXException {
+                // Depth + 1--we aren't actually in the element yet.
+                namespaceStackBuilder.push(prefix, uri, depth + 1);
+            }
+
+            public void startElement(String uri, String localName, String qName,
+                    Attributes attributes) {
+                String name = processNamespaces ? localName : qName;
+
+                add(new StartTagEvent(uri, name, parser, ++this.depth,
+                        namespaceStackBuilder.build(), processNamespaces));
+            }
+
+            public void endElement(String uri, String localName, String qName) {
+                String name = processNamespaces ? localName : qName;
+
+                int depth = this.depth--;
+                add(new EndTagEvent(uri, name, depth,
+                        namespaceStackBuilder.build()));
+                namespaceStackBuilder.pop(depth);
+            }
+
+            public void characters(char ch[], int start, int length) {
+                // Ignore empty strings.
+                if (length == 0) {
+                    return;
+                }
+
+                // Start a new text event if necessary.
+                if (textEvent == null) {
+                    textEvent = new TextEvent(length, this.depth,
+                            namespaceStackBuilder.build());
+                }
+
+                // Append to an existing text event.
+                textEvent.append(ch, start, length);
+            }
+
+            public void setDocumentLocator(Locator locator) {}
+            public void startDocument() throws SAXException {}
+            public void endDocument() throws SAXException {}
+            public void endPrefixMapping(String prefix) throws SAXException {}
+            public void ignorableWhitespace(char ch[], int start, int length)
+                    throws SAXException {}
+            public void processingInstruction(String target, String data)
+                    throws SAXException {}
+            public void skippedEntity(String name) throws SAXException {}
+        }
+    }
+
+    class CharDocument extends Document {
+
+        final char[] buffer = new char[BUFFER_SIZE / 2];
+        final Reader in;
+
+        CharDocument(Reader in, boolean processNamespaces) {
+            super("UTF-16", processNamespaces);
+            this.in = in;
+        }
+
+        @Override
+        int buffer() throws IOException {
+            return in.read(buffer);
+        }
+
+        @Override
+        void flush(ExpatParser parser, int length)
+                throws XmlPullParserException {
+            try {
+                parser.append(buffer, 0, length);
+            } catch (SAXException e) {
+                throw new XmlPullParserException(
+                        "Error parsing document.", ExpatPullParser.this, e);
+            }
+        }
+    }
+
+    class ByteDocument extends Document {
+
+        final byte[] buffer = new byte[BUFFER_SIZE];
+        final InputStream in;
+
+        ByteDocument(InputStream in, String encoding,
+                boolean processNamespaces) {
+            super(encoding, processNamespaces);
+            this.in = in;
+        }
+
+        @Override
+        int buffer() throws IOException {
+            return in.read(buffer);
+        }
+
+        @Override
+        void flush(ExpatParser parser, int length)
+                throws XmlPullParserException {
+            try {
+                parser.append(buffer, 0, length);
+            } catch (SAXException e) {
+                throw new XmlPullParserException(
+                        "Error parsing document.", ExpatPullParser.this, e);
+            }
+        }
+    }
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/ExpatReader.java b/xml/src/main/java/org/apache/harmony/xml/ExpatReader.java
new file mode 100644
index 0000000..a6a83a0
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/ExpatReader.java
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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.harmony.xml;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ext.LexicalHandler;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.InputStream;
+import java.util.logging.Logger;
+
+/**
+ * SAX wrapper around Expat. Interns strings. Does not support validation.
+ * Does not support {@link DTDHandler}.
+ */
+public class ExpatReader implements XMLReader {
+
+    private static final Logger logger
+            = Logger.getLogger(ExpatReader.class.getName());
+
+    /*
+     * ExpatParser accesses these fields directly during parsing. The user
+     * should be able to safely change them during parsing.
+     */
+    /*package*/ ContentHandler contentHandler;
+    /*package*/ EntityResolver entityResolver;
+    /*package*/ ErrorHandler errorHandler;
+    /*package*/ LexicalHandler lexicalHandler;
+
+    private boolean processNamespaces = true;
+    private boolean processNamespacePrefixes = false;
+
+    private static final String LEXICAL_HANDLER_PROPERTY
+            = "http://xml.org/sax/properties/lexical-handler";
+
+    private static class Feature {
+
+        private static final String BASE_URI = "http://xml.org/sax/features/";
+
+        private static final String VALIDATION = BASE_URI + "validation";
+        private static final String NAMESPACES = BASE_URI + "namespaces";
+        private static final String NAMESPACE_PREFIXES
+                = BASE_URI + "namespace-prefixes";
+        private static final String STRING_INTERNING
+                = BASE_URI + "string-interning";
+    }
+
+    public boolean getFeature(String name)
+            throws SAXNotRecognizedException, SAXNotSupportedException {
+        if (name == null) {
+            throw new NullPointerException("name");
+        }
+
+        if (name.equals(Feature.VALIDATION)) {
+            return false;
+        }
+
+        if (name.equals(Feature.NAMESPACES)) {
+            return processNamespaces;
+        }
+
+        if (name.equals(Feature.NAMESPACE_PREFIXES)) {
+            return processNamespacePrefixes;
+        }
+
+        if (name.equals(Feature.STRING_INTERNING)) {
+            return true;
+        }
+
+        throw new SAXNotRecognizedException(name);
+    }
+
+    public void setFeature(String name, boolean value)
+            throws SAXNotRecognizedException, SAXNotSupportedException {
+        if (name == null) {
+            throw new NullPointerException("name");
+        }
+
+        if (name.equals(Feature.VALIDATION)) {
+            if (value) {
+                throw new SAXNotSupportedException("Cannot enable " + name);
+            } else {
+                // Default.
+                return;
+            }
+        }
+
+        if (name.equals(Feature.NAMESPACES)) {
+            processNamespaces = value;
+            return;
+        }
+
+        if (name.equals(Feature.NAMESPACE_PREFIXES)) {
+            processNamespacePrefixes = value;
+            return;
+        }
+
+        if (name.equals(Feature.STRING_INTERNING)) {
+            if (value) {
+                // Default.
+                return;
+            } else {
+                throw new SAXNotSupportedException("Cannot disable " + name);
+            }
+        }
+
+        throw new SAXNotRecognizedException(name);
+    }
+
+    public Object getProperty(String name)
+            throws SAXNotRecognizedException, SAXNotSupportedException {
+        if (name == null) {
+            throw new NullPointerException("name");
+        }
+
+        if (name.equals(LEXICAL_HANDLER_PROPERTY)) {
+            return lexicalHandler;
+        }
+
+        throw new SAXNotRecognizedException(name);
+    }
+
+    public void setProperty(String name, Object value)
+            throws SAXNotRecognizedException, SAXNotSupportedException {
+        if (name == null) {
+            throw new NullPointerException("name");
+        }
+
+        if (name.equals(LEXICAL_HANDLER_PROPERTY)) {
+            // The object must implement LexicalHandler
+            if (value instanceof LexicalHandler) {
+                this.lexicalHandler = (LexicalHandler) value;
+                return;
+            }
+            throw new SAXNotSupportedException("value doesn't implement " +
+                    "org.xml.sax.ext.LexicalHandler");
+        }
+
+        throw new SAXNotRecognizedException(name);
+    }
+
+    public void setEntityResolver(EntityResolver resolver) {
+        this.entityResolver = resolver;
+    }
+
+    public EntityResolver getEntityResolver() {
+        return entityResolver;
+    }
+
+    /**
+     * Not implemented.
+     */
+    public void setDTDHandler(DTDHandler ignored) {
+        logger.warning("DTD handlers aren't supported.");
+    }
+
+    /**
+     * Always returns null.
+     */
+    public DTDHandler getDTDHandler() {
+        return null;
+    }
+
+    public void setContentHandler(ContentHandler handler) {
+        this.contentHandler = handler;
+    }
+
+    public ContentHandler getContentHandler() {
+        return this.contentHandler;
+    }
+
+    public void setErrorHandler(ErrorHandler handler) {
+        this.errorHandler = handler;
+    }
+
+    public ErrorHandler getErrorHandler() {
+        return errorHandler;
+    }
+
+    /**
+     * Returns the current lexical handler.
+     *
+     * @return the current lexical handler, or null if none has been registered
+     * @see #setLexicalHandler
+     */
+    public LexicalHandler getLexicalHandler() {
+        return lexicalHandler;
+    }
+
+    /**
+     * Registers a lexical event handler. Supports neither
+     * {@link LexicalHandler#startEntity(String)} nor
+     * {@link LexicalHandler#endEntity(String)}.
+     *
+     * <p>If the application does not register a lexical handler, all
+     * lexical events reported by the SAX parser will be silently
+     * ignored.</p>
+     *
+     * <p>Applications may register a new or different handler in the
+     * middle of a parse, and the SAX parser must begin using the new
+     * handler immediately.</p>
+     *
+     * @param lexicalHandler listens for lexical events
+     * @see #getLexicalHandler()
+     */
+    public void setLexicalHandler(LexicalHandler lexicalHandler) {
+        this.lexicalHandler = lexicalHandler;
+    }
+
+    /**
+     * Returns true if this SAX parser processes namespaces.
+     *
+     * @see #setNamespaceProcessingEnabled(boolean)
+     */
+    public boolean isNamespaceProcessingEnabled() {
+        return processNamespaces;
+    }
+
+    /**
+     * Enables or disables namespace processing. Set to true by default. If you
+     * enable namespace processing, the parser will invoke
+     * {@link ContentHandler#startPrefixMapping(String, String)} and
+     * {@link ContentHandler#endPrefixMapping(String)}, and it will filter
+     * out namespace declarations from element attributes.
+     *
+     * @see #isNamespaceProcessingEnabled()
+     */
+    public void setNamespaceProcessingEnabled(boolean processNamespaces) {
+        this.processNamespaces = processNamespaces;
+    }
+
+    public void parse(InputSource input) throws IOException, SAXException {
+        if (processNamespacePrefixes == processNamespaces) {
+            /*
+             * Expat has XML_SetReturnNSTriplet, but that still doesn't
+             * include xmlns attributes like this feature requires. We may
+             * have to implement namespace processing ourselves if we want
+             * this (not too difficult). We obviously "support" namespace
+             * prefixes if namespaces are disabled.
+             */
+            throw new SAXNotSupportedException("The 'namespace-prefix' " +
+                    "feature is not supported while the 'namespaces' " +
+                    "feature is enabled.");
+        }
+
+        // Try the character stream.
+        Reader reader = input.getCharacterStream();
+        if (reader != null) {
+            try {
+                parse(reader, input.getPublicId(), input.getSystemId());
+            } finally {
+                // TODO: Don't eat original exception when close() throws.
+                reader.close();
+            }
+            return;
+        }
+
+        // Try the byte stream.
+        InputStream in = input.getByteStream();
+        String encoding = input.getEncoding();
+        if (in != null) {
+            try {
+                parse(in, encoding, input.getPublicId(), input.getSystemId());
+            } finally {
+                // TODO: Don't eat original exception when close() throws.
+                in.close();
+            }
+            return;
+        }
+
+        String systemId = input.getSystemId();
+        if (systemId == null) {
+            throw new SAXException("No input specified.");
+        }
+
+        // Try the system id.
+        in = ExpatParser.openUrl(systemId);
+        try {
+            parse(in, encoding, input.getPublicId(), systemId);
+        } finally {
+            in.close();
+        }
+    }
+
+    private void parse(Reader in, String publicId, String systemId)
+            throws IOException, SAXException {
+        ExpatParser parser = new ExpatParser(
+                ExpatParser.CHARACTER_ENCODING,
+                this,
+                processNamespaces,
+                publicId,
+                systemId
+        );
+        parser.parseDocument(in);
+    }
+
+    private void parse(InputStream in, String encoding, String publicId,
+            String systemId) throws IOException, SAXException {
+        ExpatParser parser = new ExpatParser(
+                encoding,
+                this,
+                processNamespaces,
+                publicId,
+                systemId
+        );
+        parser.parseDocument(in);
+    }
+
+    public void parse(String systemId) throws IOException, SAXException {
+        parse(new InputSource(systemId));
+    }
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java
new file mode 100644
index 0000000..a39e0c4
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml.dom;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * Provides a straightforward implementation of the corresponding W3C DOM
+ * interface. The class is used internally only, thus only notable members that
+ * are not in the original interface are documented (the W3C docs are quite
+ * extensive). Hope that's ok.
+ * <p>
+ * Some of the fields may have package visibility, so other classes belonging to
+ * the DOM implementation can easily access them while maintaining the DOM tree
+ * structure.
+ */
+public class AttrImpl extends NodeImpl implements Attr {
+
+    // Maintained by ElementImpl.
+    ElementImpl ownerElement;
+
+    private boolean namespaceAware;
+    
+    private String namespaceURI;
+
+    private String localName;
+
+    private String prefix;
+    
+    private String value;
+
+    AttrImpl(DocumentImpl document, String namespaceURI, String qualifiedName) {
+        super(document);
+
+        namespaceAware = true;
+        this.namespaceURI = namespaceURI;
+
+        if (qualifiedName == null || "".equals(qualifiedName)) {
+            throw new DOMException(DOMException.NAMESPACE_ERR, qualifiedName);
+        }
+        
+        int prefixSeparator = qualifiedName.lastIndexOf(":");
+        if (prefixSeparator != -1) {
+            setPrefix(qualifiedName.substring(0, prefixSeparator));
+            qualifiedName = qualifiedName.substring(prefixSeparator + 1);
+        }
+
+        localName = qualifiedName;
+        
+        if ("".equals(localName)) {
+            throw new DOMException(DOMException.NAMESPACE_ERR, localName);
+        }
+        
+        if ("xmlns".equals(localName) && !"http://www.w3.org/2000/xmlns/".equals(namespaceURI)) {
+            throw new DOMException(DOMException.NAMESPACE_ERR, localName);
+        }
+            
+        if (!document.isXMLIdentifier(localName)) {
+            throw new DOMException(DOMException.INVALID_CHARACTER_ERR, localName);
+        }
+            
+        value = "";
+    }
+
+    AttrImpl(DocumentImpl document, String name) {
+        super(document);
+
+        this.namespaceAware = false;
+        
+        int prefixSeparator = name.lastIndexOf(":");
+        if (prefixSeparator != -1) {
+            String prefix = name.substring(0, prefixSeparator);
+            String localName = name.substring(prefixSeparator + 1);
+            
+            if (!document.isXMLIdentifier(prefix) || !document.isXMLIdentifier(localName)) {
+                throw new DOMException(DOMException.INVALID_CHARACTER_ERR, name);
+            }
+        } else {
+            if (!document.isXMLIdentifier(name)) {
+                throw new DOMException(DOMException.INVALID_CHARACTER_ERR, name);
+            }
+        }
+        
+        this.localName = name;
+    }
+    
+    @Override
+    public String getLocalName() {
+        return namespaceAware ? localName : null;
+    }
+
+    public String getName() {
+        return (prefix != null ? prefix + ":" : "") + localName;
+    }
+
+    @Override
+    public String getNamespaceURI() {
+        return namespaceURI;
+    }
+
+    @Override
+    public String getNodeName() {
+        return getName();
+    }
+
+    public short getNodeType() {
+        return Node.ATTRIBUTE_NODE;
+    }
+
+    @Override
+    public String getNodeValue() {
+        return getValue();
+    }
+
+    public Element getOwnerElement() {
+        return ownerElement;
+    }
+
+    @Override
+    public String getPrefix() {
+        return prefix;
+    }
+
+    public boolean getSpecified() {
+        return value != null;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    @Override
+    public void setNodeValue(String value) throws DOMException {
+        setValue(value);
+    }
+    
+    @Override
+    public void setPrefix(String prefix) {
+        if (!namespaceAware) {
+            throw new DOMException(DOMException.NAMESPACE_ERR, prefix);
+        }
+        
+        if (prefix != null) {
+            if (namespaceURI == null || !document.isXMLIdentifier(prefix) || "xmlns".equals(prefix)) {
+                throw new DOMException(DOMException.NAMESPACE_ERR, prefix);
+            }
+
+            if ("xml".equals(prefix) && !"http://www.w3.org/XML/1998/namespace".equals(namespaceURI)) {
+                throw new DOMException(DOMException.NAMESPACE_ERR, prefix);
+            }
+        }
+
+        this.prefix = prefix;
+    }
+    
+    public void setValue(String value) throws DOMException {
+        this.value = value;
+    }
+    
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/CDATASectionImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/CDATASectionImpl.java
new file mode 100644
index 0000000..f54e5f4
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/dom/CDATASectionImpl.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml.dom;
+
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/**
+ * Provides a straightforward implementation of the corresponding W3C DOM
+ * interface. The class is used internally only, thus only notable members that
+ * are not in the original interface are documented (the W3C docs are quite
+ * extensive). Hope that's ok.
+ * <p>
+ * Some of the fields may have package visibility, so other classes belonging to
+ * the DOM implementation can easily access them while maintaining the DOM tree
+ * structure.
+ */
+public class CDATASectionImpl extends TextImpl implements CDATASection {
+
+    CDATASectionImpl(DocumentImpl document, String data) {
+        super(document, data);
+    }
+
+    @Override
+    public String getNodeName() {
+        return "#cdata-section";
+    }
+
+    @Override
+    public short getNodeType() {
+        return Node.CDATA_SECTION_NODE;
+    }
+
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/CharacterDataImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/CharacterDataImpl.java
new file mode 100644
index 0000000..010cb22
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/dom/CharacterDataImpl.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml.dom;
+
+import org.w3c.dom.CharacterData;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+
+/**
+ * Provides a straightforward implementation of the corresponding W3C DOM
+ * interface. The class is used internally only, thus only notable members that
+ * are not in the original interface are documented (the W3C docs are quite
+ * extensive). Hope that's ok.
+ * <p>
+ * Some of the fields may have package visibility, so other classes belonging to
+ * the DOM implementation can easily access them while maintaining the DOM tree
+ * structure.
+ */
+public abstract class CharacterDataImpl extends LeafNodeImpl implements
+        CharacterData {
+
+    private StringBuffer buffer;
+
+    CharacterDataImpl(DocumentImpl document, String data) {
+        super(document);
+        setData(data);
+    }
+
+    public void appendData(String arg) throws DOMException {
+        buffer.append(arg);
+    }
+
+    public void deleteData(int offset, int count) throws DOMException {
+        buffer.delete(offset, offset + count);
+    }
+
+    public String getData() throws DOMException {
+        return buffer.toString();
+    }
+
+    public int getLength() {
+        return buffer.length();
+    }
+
+    @Override
+    public String getNodeValue() {
+        return getData();
+    }
+
+    public void insertData(int offset, String arg) throws DOMException {
+        try {
+            buffer.insert(offset, arg);
+        } catch (ArrayIndexOutOfBoundsException ex) {
+            throw new DOMException(DOMException.INDEX_SIZE_ERR, null);
+        }
+    }
+
+    public void replaceData(int offset, int count, String arg)
+            throws DOMException {
+        try {
+            buffer.replace(offset, offset + count, arg);
+        } catch (ArrayIndexOutOfBoundsException ex) {
+            throw new DOMException(DOMException.INDEX_SIZE_ERR, null);
+        }
+    }
+
+    public void setData(String data) throws DOMException {
+        buffer = new StringBuffer(data);
+    }
+
+    public String substringData(int offset, int count) throws DOMException {
+        try {
+            return buffer.substring(offset, offset + count);
+        } catch (ArrayIndexOutOfBoundsException ex) {
+            throw new DOMException(DOMException.INDEX_SIZE_ERR, null);
+        }
+    }
+
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/CommentImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/CommentImpl.java
new file mode 100644
index 0000000..6c1f446
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/dom/CommentImpl.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml.dom;
+
+import org.w3c.dom.Comment;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/**
+ * Provides a straightforward implementation of the corresponding W3C DOM
+ * interface. The class is used internally only, thus only notable members that
+ * are not in the original interface are documented (the W3C docs are quite
+ * extensive). Hope that's ok.
+ * <p>
+ * Some of the fields may have package visibility, so other classes belonging to
+ * the DOM implementation can easily access them while maintaining the DOM tree
+ * structure.
+ */
+public class CommentImpl extends CharacterDataImpl implements Comment {
+
+    CommentImpl(DocumentImpl document, String data) {
+        super(document, data);
+    }
+
+    @Override
+    public String getNodeName() {
+        return "#comment";
+    }
+
+    @Override
+    public short getNodeType() {
+        return Node.COMMENT_NODE;
+    }
+
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/DOMImplementationImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/DOMImplementationImpl.java
new file mode 100644
index 0000000..4e13d19
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/dom/DOMImplementationImpl.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml.dom;
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+
+/**
+ * Provides a straightforward implementation of the corresponding W3C DOM
+ * interface. The class is used internally only, thus only notable members that
+ * are not in the original interface are documented (the W3C docs are quite
+ * extensive). Hope that's ok.
+ * <p>
+ * Some of the fields may have package visibility, so other classes belonging to
+ * the DOM implementation can easily access them while maintaining the DOM tree
+ * structure.
+ */
+public class DOMImplementationImpl implements DOMImplementation {
+
+    // Singleton instance.
+    private static DOMImplementationImpl instance;
+
+    DOMImplementationImpl() {
+    }
+
+    public Document createDocument(String namespaceURI, String qualifiedName,
+            DocumentType doctype) throws DOMException {
+        return new DocumentImpl(this, namespaceURI, qualifiedName, doctype);
+    }
+
+    public DocumentType createDocumentType(String qualifiedName,
+            String publicId, String systemId) throws DOMException {
+        return new DocumentTypeImpl(this, qualifiedName, publicId, systemId);
+    }
+
+    public boolean hasFeature(String feature, String version) {
+        // We claim to support DOM Core Level 1 & 2, nothing else.
+
+        if ("Core".equalsIgnoreCase(feature) || "XML".equalsIgnoreCase(feature)) {
+            if (version == null || "".equals(version) || "1.0".equals(version) || "2.0".equals(version)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Requests the singleton instance of the class. Creates it first, if
+     * necessary.
+     * 
+     * @return The singleton Android DOMImplementationImpl instance.
+     */
+    public static DOMImplementationImpl getInstance() {
+        if (instance == null) {
+            instance = new DOMImplementationImpl();
+        }
+
+        return instance;
+    }
+
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/DocumentFragmentImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/DocumentFragmentImpl.java
new file mode 100644
index 0000000..88e6175
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/dom/DocumentFragmentImpl.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml.dom;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.Node;
+
+/**
+ * Provides a straightforward implementation of the corresponding W3C DOM
+ * interface. The class is used internally only, thus only notable members that
+ * are not in the original interface are documented (the W3C docs are quite
+ * extensive). Hope that's ok.
+ * <p>
+ * Some of the fields may have package visibility, so other classes belonging to
+ * the DOM implementation can easily access them while maintaining the DOM tree
+ * structure.
+ */
+public class DocumentFragmentImpl extends InnerNodeImpl implements
+        DocumentFragment {
+
+    DocumentFragmentImpl(DocumentImpl document) {
+        super(document);
+    }
+
+    @Override
+    public String getNodeName() {
+        return "#document-fragment";
+    }
+
+    @Override
+    public short getNodeType() {
+        return Node.DOCUMENT_FRAGMENT_NODE;
+    }
+
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java
new file mode 100644
index 0000000..fbb1cac
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml.dom;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.CharacterData;
+import org.w3c.dom.Comment;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+
+/**
+ * Provides a straightforward implementation of the corresponding W3C DOM
+ * interface. The class is used internally only, thus only notable members that
+ * are not in the original interface are documented (the W3C docs are quite
+ * extensive). Hope that's ok.
+ * <p>
+ * Some of the fields may have package visibility, so other classes belonging to
+ * the DOM implementation can easily access them while maintaining the DOM tree
+ * structure.
+ */
+public class DocumentImpl extends InnerNodeImpl implements Document {
+
+    private DOMImplementation domImplementation;
+
+    DocumentImpl(DOMImplementationImpl impl, String namespaceURI,
+            String qualifiedName, DocumentType doctype) {
+        super(null);
+
+        this.domImplementation = impl;
+        // this.document = this;
+        
+        if (doctype != null) {
+            appendChild(doctype);
+        }
+
+        if (qualifiedName != null) {
+            appendChild(createElementNS(namespaceURI, qualifiedName));
+        }
+    }
+
+    private static boolean isXMLIdentifierStart(char c) {
+        return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c == '_');
+    }
+
+    private static boolean isXMLIdentifierPart(char c) {
+        return isXMLIdentifierStart(c) || (c >= '0' && c <= '9') || (c == '-') || (c == '.');
+    }
+
+    static boolean isXMLIdentifier(String s) {
+        if (s.length() == 0) {
+            return false;
+        }
+        
+        if (!isXMLIdentifierStart(s.charAt(0))) {
+            return false;
+        }
+        
+        for (int i = 1; i < s.length(); i++) {
+            if (!isXMLIdentifierPart(s.charAt(i))) {
+                return false;
+            }
+        }
+        
+        return true;
+    }
+    
+    /**
+     * Clones a node and (if requested) its children. The source node(s) may
+     * have been created by a different DocumentImpl or even DOM implementation.
+     * 
+     * @param node The node to clone.
+     * @param deep If true, a deep copy is created (including all child nodes).
+     * 
+     * @return The new node.
+     */
+    Node cloneNode(Node node, boolean deep) throws DOMException {
+        Node target;
+        
+        switch (node.getNodeType()) {
+            case Node.ATTRIBUTE_NODE: {
+                Attr source = (Attr)node;
+                target = createAttributeNS(source.getNamespaceURI(), source.getLocalName());
+                target.setPrefix(source.getPrefix());
+                target.setNodeValue(source.getNodeValue());
+                break;
+            }
+            case Node.CDATA_SECTION_NODE: {
+                CharacterData source = (CharacterData)node;
+                target = createCDATASection(source.getData());
+                break;
+            }
+            case Node.COMMENT_NODE: {
+                Comment source = (Comment)node;
+                target = createComment(source.getData());
+                break;
+            }
+            case Node.DOCUMENT_FRAGMENT_NODE: {
+                // Source is irrelevant in this case.
+                target = createDocumentFragment();
+                break;
+            }
+            case Node.DOCUMENT_NODE: {
+                throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Cannot clone a Document node");
+            }
+            case Node.DOCUMENT_TYPE_NODE: {
+                throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Cannot clone a DocumentType node");
+            }
+            case Node.ELEMENT_NODE: {
+                Element source = (Element)node;
+                target = createElementNS(source.getNamespaceURI(), source.getLocalName());
+                target.setPrefix(source.getPrefix());
+
+                NamedNodeMap map = source.getAttributes();
+                for (int i = 0; i < map.getLength(); i++) {
+                    Attr attr = (Attr)map.item(i);
+                    ((Element)target).setAttributeNodeNS((Attr)cloneNode(attr, deep));
+                }
+                break;
+            }
+            case Node.ENTITY_NODE: {
+                throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Cannot clone an Entity node");
+            }
+            case Node.ENTITY_REFERENCE_NODE: {
+                EntityReference source = (EntityReference)node;
+                target = createEntityReference(source.getNodeName());
+                break;
+            }
+            case Node.NOTATION_NODE: {
+                throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Cannot clone a Notation node");
+            }
+            case Node.PROCESSING_INSTRUCTION_NODE: {
+                ProcessingInstruction source = (ProcessingInstruction)node;
+                target = createProcessingInstruction(source.getTarget(), source.getData());
+                break;
+            }
+            case Node.TEXT_NODE: {
+                Text source = (Text)node;
+                target = createTextNode(source.getData());
+                break;
+            }
+            default: {
+                throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Cannot clone unknown node type " + node.getNodeType() + " (" + node.getClass().getSimpleName() + ")");
+            }
+        }
+
+        if (deep) {
+            NodeList list = node.getChildNodes();
+            for (int i = 0; i < list.getLength(); i++) {
+                Node child = cloneNode(list.item(i), deep);
+                target.appendChild(child);
+            }
+        }
+        
+        return target;
+    }
+    
+    public AttrImpl createAttribute(String name) throws DOMException {
+        return new AttrImpl(this, name);
+    }
+
+    public Attr createAttributeNS(String namespaceURI, String qualifiedName)
+            throws DOMException {
+        return new AttrImpl(this, namespaceURI, qualifiedName);
+    }
+
+    public CDATASection createCDATASection(String data) throws DOMException {
+        return new CDATASectionImpl(this, data);
+    }
+
+    public Comment createComment(String data) {
+        return new CommentImpl(this, data);
+    }
+
+    public DocumentFragment createDocumentFragment() {
+        return new DocumentFragmentImpl(this);
+    }
+
+    public Element createElement(String tagName) throws DOMException {
+        return new ElementImpl(this, tagName);
+    }
+
+    public Element createElementNS(String namespaceURI, String qualifiedName)
+            throws DOMException {
+        return new ElementImpl(this, namespaceURI, qualifiedName);
+    }
+
+    public EntityReference createEntityReference(String name)
+            throws DOMException {
+        return new EntityReferenceImpl(this, name);
+    }
+
+    public ProcessingInstruction createProcessingInstruction(String target,
+            String data) throws DOMException {
+        return new ProcessingInstructionImpl(this, target, data);
+    }
+
+    public Text createTextNode(String data) {
+        return new TextImpl(this, data);
+    }
+
+    public DocumentType getDoctype() {
+        for (int i = 0; i < children.size(); i++) {
+            if (children.get(i) instanceof DocumentType) {
+                return (DocumentType) children.get(i);
+            }
+        }
+
+        return null;
+    }
+
+    public Element getDocumentElement() {
+        for (int i = 0; i < children.size(); i++) {
+            if (children.get(i) instanceof Element) {
+                return (Element) children.get(i);
+            }
+        }
+
+        return null;
+    }
+
+    public Element getElementById(String elementId) {
+        ElementImpl root = (ElementImpl) getDocumentElement();
+
+        return (root == null ? null : root.getElementById(elementId));
+    }
+
+    public NodeList getElementsByTagName(String tagname) {
+        ElementImpl root = (ElementImpl) getDocumentElement();
+
+        return (root == null ? new NodeListImpl()
+                : root.getElementsByTagName(tagname));
+    }
+
+    public NodeList getElementsByTagNameNS(String namespaceURI, String localName) {
+        ElementImpl root = (ElementImpl) getDocumentElement();
+
+        return (root == null ? new NodeListImpl() : root.getElementsByTagNameNS(
+                namespaceURI, localName));
+    }
+
+    public DOMImplementation getImplementation() {
+        return domImplementation;
+    }
+
+    @Override
+    public String getNodeName() {
+        return "#document";
+    }
+
+    @Override
+    public short getNodeType() {
+        return Node.DOCUMENT_NODE;
+    }
+
+    public Node importNode(Node importedNode, boolean deep) throws DOMException {
+        return cloneNode(importedNode, deep);
+    }
+
+    @Override
+    public Node insertChildAt(Node newChild, int index) throws DOMException {
+        // Make sure we have at most one root element and one DTD element.
+        if (newChild instanceof Element && getDocumentElement() != null) {
+            throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
+                    "Only one root element allowed");
+        } else if (newChild instanceof DocumentType && getDoctype() != null) {
+            throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
+                    "Only one DOCTYPE element allowed");
+        }
+
+        return super.insertChildAt(newChild, index);
+    }
+
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/DocumentTypeImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/DocumentTypeImpl.java
new file mode 100644
index 0000000..df40d4b
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/dom/DocumentTypeImpl.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml.dom;
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+/**
+ * Provides a straightforward implementation of the corresponding W3C DOM
+ * interface. The class is used internally only, thus only notable members that
+ * are not in the original interface are documented (the W3C docs are quite
+ * extensive). Hope that's ok.
+ * <p>
+ * Some of the fields may have package visibility, so other classes belonging to
+ * the DOM implementation can easily access them while maintaining the DOM tree
+ * structure.
+ */
+public class DocumentTypeImpl extends LeafNodeImpl implements DocumentType {
+
+    private String qualifiedName;
+
+    private String publicId;
+
+    private String systemId;
+
+    DocumentTypeImpl(DOMImplementationImpl impl, String qualifiedName,
+            String publicId, String systemId) {
+        super(null);
+
+        if (qualifiedName == null || "".equals(qualifiedName)) {
+            throw new DOMException(DOMException.NAMESPACE_ERR, qualifiedName);
+        }
+        
+        int prefixSeparator = qualifiedName.lastIndexOf(":");
+        if (prefixSeparator != -1) {
+            String prefix = qualifiedName.substring(0, prefixSeparator);
+            String localName = qualifiedName.substring(prefixSeparator + 1);
+            
+            if (!DocumentImpl.isXMLIdentifier(prefix)) {
+                throw new DOMException(DOMException.NAMESPACE_ERR, qualifiedName);
+            }
+
+            if (!DocumentImpl.isXMLIdentifier(localName)) {
+                throw new DOMException(DOMException.INVALID_CHARACTER_ERR, qualifiedName);
+            }
+        } else {
+            if (!DocumentImpl.isXMLIdentifier(qualifiedName)) {
+                throw new DOMException(DOMException.INVALID_CHARACTER_ERR, qualifiedName);
+            }
+        }
+        
+        this.qualifiedName = qualifiedName;
+        this.publicId = publicId;
+        this.systemId = systemId;
+    }
+
+    @Override
+    public String getNodeName() {
+        return qualifiedName;
+    }
+
+    @Override
+    public short getNodeType() {
+        return Node.DOCUMENT_TYPE_NODE;
+    }
+
+    public NamedNodeMap getEntities() {
+        // TODO Dummy. Implement this later, if at all (we're DOM level 2 only).
+        return null;
+    }
+
+    public String getInternalSubset() {
+        // TODO Dummy. Implement this later, if at all (we're DOM level 2 only).
+        return null;
+    }
+
+    public String getName() {
+        return qualifiedName;
+    }
+
+    public NamedNodeMap getNotations() {
+        // TODO Dummy. Implement this later, if at all (we're DOM level 2 only).
+        return null;
+    }
+
+    public String getPublicId() {
+        return publicId;
+    }
+
+    public String getSystemId() {
+        return systemId;
+    }
+
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/ElementImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/ElementImpl.java
new file mode 100644
index 0000000..3b44ff3
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/dom/ElementImpl.java
@@ -0,0 +1,446 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Provides a straightforward implementation of the corresponding W3C DOM
+ * interface. The class is used internally only, thus only notable members that
+ * are not in the original interface are documented (the W3C docs are quite
+ * extensive). Hope that's ok.
+ * <p>
+ * Some of the fields may have package visibility, so other classes belonging to
+ * the DOM implementation can easily access them while maintaining the DOM tree
+ * structure.
+ */
+public class ElementImpl extends InnerNodeImpl implements Element {
+
+    private boolean namespaceAware;
+    
+    private String namespaceURI;
+
+    private String prefix;
+    
+    private String localName;
+
+    private List<AttrImpl> attributes = new ArrayList<AttrImpl>();
+
+    ElementImpl(DocumentImpl document, String namespaceURI, String qualifiedName) {
+        super(document);
+
+        this.namespaceAware = true;
+        this.namespaceURI = namespaceURI;
+
+        if (qualifiedName == null || "".equals(qualifiedName)) {
+            throw new DOMException(DOMException.NAMESPACE_ERR, qualifiedName);
+        }
+        
+        int p = qualifiedName.lastIndexOf(":");
+        if (p != -1) {
+            setPrefix(qualifiedName.substring(0, p));
+            qualifiedName = qualifiedName.substring(p + 1);
+        }
+        
+        if (!document.isXMLIdentifier(qualifiedName)) {
+            throw new DOMException(DOMException.INVALID_CHARACTER_ERR, qualifiedName);
+        }
+            
+        this.localName = qualifiedName;
+    }
+
+    ElementImpl(DocumentImpl document, String name) {
+        super(document);
+
+        this.namespaceAware = false;
+        
+        int p = name.lastIndexOf(":");
+        if (p != -1) {
+            String prefix = name.substring(0, p);
+            String localName = name.substring(p + 1);
+            
+            if (!document.isXMLIdentifier(prefix) || !document.isXMLIdentifier(localName)) {
+                throw new DOMException(DOMException.INVALID_CHARACTER_ERR, name);
+            }
+        } else {
+            if (!document.isXMLIdentifier(name)) {
+                throw new DOMException(DOMException.INVALID_CHARACTER_ERR, name);
+            }
+        }
+        
+        this.localName = name;
+    }
+
+    private int indexOfAttribute(String name) {
+        for (int i = 0; i < attributes.size(); i++) {
+            AttrImpl attr = attributes.get(i);
+            if (attr.matchesName(name, false)) {
+                return i;
+            }
+        }
+        
+        return -1;
+    }
+    
+    private int indexOfAttributeNS(String namespaceURI, String localName) {
+        for (int i = 0; i < attributes.size(); i++) {
+            AttrImpl attr = attributes.get(i);
+            if (attr.matchesNameNS(namespaceURI, localName, false)) {
+                return i;
+            }
+        }
+        
+        return -1;
+    }
+    
+    public String getAttribute(String name) {
+        Attr attr = getAttributeNode(name);
+
+        if (attr == null) {
+            return "";
+        }
+
+        return attr.getValue();
+    }
+
+    public String getAttributeNS(String namespaceURI, String localName) {
+        Attr attr = getAttributeNodeNS(namespaceURI, localName);
+
+        if (attr == null) {
+            return "";
+        }
+
+        return attr.getValue();
+    }
+
+    public Attr getAttributeNode(String name) {
+        int i = indexOfAttribute(name);
+        
+        if (i == -1) {
+            return null;
+        }
+        
+        return attributes.get(i);
+    }
+
+    public Attr getAttributeNodeNS(String namespaceURI, String localName) {
+        int i = indexOfAttributeNS(namespaceURI, localName);
+        
+        if (i == -1) {
+            return null;
+        }
+        
+        return attributes.get(i);
+    }
+
+    @Override
+    public NamedNodeMap getAttributes() {
+        return new ElementAttrNamedNodeMapImpl();
+    }
+    
+    Element getElementById(String name) {
+        if (name.equals(getAttribute("id"))) {
+            return this;
+        }
+
+        for (NodeImpl node : children) {
+            if (node.getNodeType() == Node.ELEMENT_NODE) {
+                Element element = ((ElementImpl) node).getElementById(name);
+                if (element != null) {
+                    return element;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    public NodeList getElementsByTagName(String name) {
+        NodeListImpl list = new NodeListImpl();
+        getElementsByTagName(list, name);
+        return list;
+    }
+
+    void getElementsByTagName(NodeListImpl list, String name) {
+        if (matchesName(name, true)) {
+            list.add(this);
+        }
+
+        for (NodeImpl node : children) {
+            if (node.getNodeType() == Node.ELEMENT_NODE) {
+                ((ElementImpl) node).getElementsByTagName(list, name);
+            }
+        }
+    }
+
+    public NodeList getElementsByTagNameNS(String namespaceURI, String localName) {
+        NodeListImpl list = new NodeListImpl();
+        getElementsByTagNameNS(list, namespaceURI, localName);
+        return list;
+    }
+
+    void getElementsByTagNameNS(NodeListImpl list, String namespaceURI,
+            String localName) {
+        if (matchesNameNS(namespaceURI, localName, true)) {
+            list.add(this);
+        }
+        
+        for (NodeImpl node : children) {
+            if (node.getNodeType() == Node.ELEMENT_NODE) {
+                ((ElementImpl) node).getElementsByTagNameNS(list, namespaceURI,
+                        localName);
+            }
+        }
+    }
+
+    @Override
+    public String getLocalName() {
+        return namespaceAware ? localName : null;
+    }
+
+    @Override
+    public String getNamespaceURI() {
+        return namespaceURI;
+    }
+
+    @Override
+    public String getNodeName() {
+        return getTagName();
+    }
+
+    public short getNodeType() {
+        return Node.ELEMENT_NODE;
+    }
+
+    @Override
+    public String getPrefix() {
+        return prefix;
+    }
+
+    public String getTagName() {
+        return (prefix != null ? prefix + ":" : "") + localName;
+    }
+
+    public boolean hasAttribute(String name) {
+        return indexOfAttribute(name) != -1;
+    }
+
+    public boolean hasAttributeNS(String namespaceURI, String localName) {
+        return indexOfAttributeNS(namespaceURI, localName) != -1;
+    }
+
+    @Override
+    public boolean hasAttributes() {
+        return !attributes.isEmpty();
+    }
+
+    public void removeAttribute(String name) throws DOMException {
+        int i = indexOfAttribute(name);
+        
+        if (i != -1) {
+            attributes.remove(i);
+        }
+    }
+
+    public void removeAttributeNS(String namespaceURI, String localName)
+            throws DOMException {
+        int i = indexOfAttributeNS(namespaceURI, localName);
+        
+        if (i != -1) {
+            attributes.remove(i);
+        }
+    }
+
+    public Attr removeAttributeNode(Attr oldAttr) throws DOMException {
+        AttrImpl oldAttrImpl = (AttrImpl) oldAttr;
+
+        if (oldAttrImpl.getOwnerElement() != this) {
+            throw new DOMException(DOMException.NOT_FOUND_ERR, null);
+        }
+
+        attributes.remove(oldAttr);
+        oldAttrImpl.ownerElement = null;
+
+        return oldAttrImpl;
+    }
+
+    public void setAttribute(String name, String value) throws DOMException {
+        Attr attr = getAttributeNode(name);
+
+        if (attr == null) {
+            attr = document.createAttribute(name);
+            setAttributeNode(attr);
+        }
+
+        attr.setValue(value);
+    }
+
+    public void setAttributeNS(String namespaceURI, String qualifiedName,
+            String value) throws DOMException {
+        Attr attr = getAttributeNodeNS(namespaceURI, qualifiedName);
+
+        if (attr == null) {
+            attr = document.createAttributeNS(namespaceURI, qualifiedName);
+            setAttributeNodeNS(attr);
+        }
+
+        attr.setValue(value);
+    }
+
+    public Attr setAttributeNode(Attr newAttr) throws DOMException {
+        AttrImpl newAttrImpl = (AttrImpl) newAttr;
+        
+        if (newAttrImpl.document != this.getOwnerDocument()) {
+            throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, null);
+        }
+
+        if (newAttrImpl.getOwnerElement() != null) {
+            throw new DOMException(DOMException.INUSE_ATTRIBUTE_ERR, null);
+        }
+
+        AttrImpl oldAttrImpl = null;
+        
+        int i = indexOfAttribute(newAttr.getName());
+        if (i != -1) {
+            oldAttrImpl = attributes.get(i);
+            attributes.remove(i);
+        }
+        
+        attributes.add(newAttrImpl);
+        newAttrImpl.ownerElement = this;
+
+        return oldAttrImpl;
+    }
+
+    public Attr setAttributeNodeNS(Attr newAttr) throws DOMException {
+        AttrImpl newAttrImpl = (AttrImpl) newAttr;
+
+        if (newAttrImpl.document != this.getOwnerDocument()) {
+            throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, null);
+        }
+
+        if (newAttrImpl.getOwnerElement() != null) {
+            throw new DOMException(DOMException.INUSE_ATTRIBUTE_ERR, null);
+        }
+
+        AttrImpl oldAttrImpl = null;
+        
+        int i = indexOfAttributeNS(newAttr.getNamespaceURI(), newAttr.getLocalName());
+        if (i != -1) {
+            oldAttrImpl = attributes.get(i);
+            attributes.remove(i);
+        }
+        
+        attributes.add(newAttrImpl);
+        newAttrImpl.ownerElement = this;
+
+        return oldAttrImpl;
+    }
+
+    @Override
+    public void setPrefix(String prefix) {
+        if (!namespaceAware) {
+            throw new DOMException(DOMException.NAMESPACE_ERR, prefix);
+        }
+        
+        if (prefix != null) {
+            if (namespaceURI == null || !document.isXMLIdentifier(prefix)) {
+                throw new DOMException(DOMException.NAMESPACE_ERR, prefix);
+            }
+            
+            if ("xml".equals(prefix) && !"http://www.w3.org/XML/1998/namespace".equals(namespaceURI)) {
+                throw new DOMException(DOMException.NAMESPACE_ERR, prefix);
+            }
+        }
+        
+        this.prefix = prefix;
+    }
+    
+    public class ElementAttrNamedNodeMapImpl implements NamedNodeMap {
+
+        public int getLength() {
+            return ElementImpl.this.attributes.size();
+        }
+
+        private int indexOfItem(String name) {
+            return ElementImpl.this.indexOfAttribute(name);
+        }
+        
+        private int indexOfItemNS(String namespaceURI, String localName) {
+            return ElementImpl.this.indexOfAttributeNS(namespaceURI, localName);
+        }
+
+        public Node getNamedItem(String name) {
+            return ElementImpl.this.getAttributeNode(name);
+        }
+
+        public Node getNamedItemNS(String namespaceURI, String localName) {
+            return ElementImpl.this.getAttributeNodeNS(namespaceURI, localName);
+        }
+
+        public Node item(int index) {
+            return ElementImpl.this.attributes.get(index);
+        }
+
+        public Node removeNamedItem(String name) throws DOMException {
+            int i = indexOfItem(name);
+            
+            if (i == -1) {
+                throw new DOMException(DOMException.NOT_FOUND_ERR, null);
+            }
+
+            return ElementImpl.this.attributes.remove(i);
+        }
+
+        public Node removeNamedItemNS(String namespaceURI, String localName)
+                throws DOMException {
+            int i = indexOfItemNS(namespaceURI, localName);
+            
+            if (i == -1) {
+                throw new DOMException(DOMException.NOT_FOUND_ERR, null);
+            }
+
+            return ElementImpl.this.attributes.remove(i);
+        }
+
+        public Node setNamedItem(Node arg) throws DOMException {
+            if (!(arg instanceof Attr)) {
+                throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null);
+            }
+
+            return ElementImpl.this.setAttributeNode((Attr)arg);
+        }
+
+        public Node setNamedItemNS(Node arg) throws DOMException {
+            if (!(arg instanceof Attr)) {
+                throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null);
+            }
+            
+            return ElementImpl.this.setAttributeNodeNS((Attr)arg);
+        }
+    }
+    
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/EntityImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/EntityImpl.java
new file mode 100644
index 0000000..463e863
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/dom/EntityImpl.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml.dom;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Entity;
+import org.w3c.dom.Node;
+
+/**
+ * Provides a straightforward implementation of the corresponding W3C DOM
+ * interface. The class is used internally only, thus only notable members that
+ * are not in the original interface are documented (the W3C docs are quite
+ * extensive). Hope that's ok.
+ * <p>
+ * Some of the fields may have package visibility, so other classes belonging to
+ * the DOM implementation can easily access them while maintaining the DOM tree
+ * structure.
+ */
+public class EntityImpl extends NodeImpl implements Entity {
+
+    private String notationName;
+
+    private String publicID;
+
+    private String systemID;
+
+    EntityImpl(DocumentImpl document, String notationName, String publicID,
+            String systemID) {
+        super(document);
+        this.notationName = notationName;
+        this.publicID = publicID;
+        this.systemID = systemID;
+    }
+
+    @Override
+    public String getNodeName() {
+        return getNotationName();
+    }
+
+    @Override
+    public short getNodeType() {
+        return Node.ENTITY_NODE;
+    }
+
+    public String getNotationName() {
+        return notationName;
+    }
+
+    public String getPublicId() {
+        return publicID;
+    }
+
+    public String getSystemId() {
+        return systemID;
+    }
+
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/EntityReferenceImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/EntityReferenceImpl.java
new file mode 100644
index 0000000..f612a15
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/dom/EntityReferenceImpl.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml.dom;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.Node;
+
+/**
+ * Provides a straightforward implementation of the corresponding W3C DOM
+ * interface. The class is used internally only, thus only notable members that
+ * are not in the original interface are documented (the W3C docs are quite
+ * extensive). Hope that's ok.
+ * <p>
+ * Some of the fields may have package visibility, so other classes belonging to
+ * the DOM implementation can easily access them while maintaining the DOM tree
+ * structure.
+ */
+public class EntityReferenceImpl extends LeafNodeImpl implements EntityReference {
+
+    private String name;
+
+    EntityReferenceImpl(DocumentImpl document, String name) {
+        super(document);
+        this.name = name;
+    }
+
+    @Override
+    public String getNodeName() {
+        return name;
+    }
+
+    @Override
+    public short getNodeType() {
+        return Node.ENTITY_REFERENCE_NODE;
+    }
+
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java
new file mode 100644
index 0000000..f71d289
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+/**
+ * Provides a straightforward implementation of the corresponding W3C DOM
+ * interface. The class is used internally only, thus only notable members that
+ * are not in the original interface are documented (the W3C docs are quite
+ * extensive). Hope that's ok.
+ * <p>
+ * Some of the fields may have package visibility, so other classes belonging to
+ * the DOM implementation can easily access them while maintaining the DOM tree
+ * structure.
+ * <p>
+ * This class represents a Node that has a parent Node as well as (potentially)
+ * a number of children.
+ */
+public abstract class InnerNodeImpl extends LeafNodeImpl {
+
+    // Maintained by LeafNodeImpl and ElementImpl.
+    List<LeafNodeImpl> children = new ArrayList<LeafNodeImpl>();
+
+    public InnerNodeImpl(DocumentImpl document) {
+        super(document);
+    }
+
+    public Node appendChild(Node newChild) throws DOMException {
+        return insertChildAt(newChild, children.size());
+    }
+
+    public NodeList getChildNodes() {
+        NodeListImpl list = new NodeListImpl();
+
+        for (NodeImpl node : children) {
+            list.add(node);
+        }
+
+        return list;
+    }
+
+    public Node getFirstChild() {
+        return (!children.isEmpty() ? children.get(0) : null);
+    }
+
+    public Node getLastChild() {
+        return (!children.isEmpty() ? children.get(children.size() - 1) : null);
+    }
+
+    public Node getNextSibling() {
+        if (parent == null || index >= parent.children.size()) {
+            return null;
+        }
+
+        return parent.children.get(index + 1);
+    }
+
+    public boolean hasChildNodes() {
+        return children.size() != 0;
+    }
+
+    public Node insertBefore(Node newChild, Node refChild) throws DOMException {
+        LeafNodeImpl refChildImpl = (LeafNodeImpl) refChild;
+
+        if (refChildImpl.document != document) {
+            throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, null);
+        }
+
+        if (refChildImpl.parent != this) {
+            throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null);
+        }
+
+        return insertChildAt(newChild, refChildImpl.index);
+    }
+
+    /**
+     * Inserts a new child node into this node at a given position. If the new
+     * node is already child of another node, it is first removed from there.
+     * This method is the generalization of the appendChild() and insertBefore()
+     * methods.
+     * 
+     * @param newChild The new child node to add.
+     * @param index The index at which to insert the new child node.
+     * 
+     * @return The node added.
+     * 
+     * @throws DOMException If the attempted operation violates the XML/DOM
+     *         well-formedness rules.
+     */
+    public Node insertChildAt(Node newChild, int index) throws DOMException {
+        LeafNodeImpl newChildImpl = (LeafNodeImpl) newChild;
+
+        if (document != null && newChildImpl.document != null && newChildImpl.document != document) {
+            throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, null);
+        }
+
+        if (newChildImpl.isParentOf(this)) {
+            throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null);
+        }
+
+        if (newChildImpl.parent != null) {
+            int oldIndex = newChildImpl.index;
+            newChildImpl.parent.children.remove(oldIndex);
+            newChildImpl.parent.refreshIndices(oldIndex);
+        }
+
+        children.add(index, newChildImpl);
+        newChildImpl.parent = this;
+        refreshIndices(index);
+
+        return newChild;
+    }
+
+    public boolean isParentOf(Node node) {
+        LeafNodeImpl nodeImpl = (LeafNodeImpl) node;
+
+        while (nodeImpl != null) {
+            if (nodeImpl == this) {
+                return true;
+            }
+
+            nodeImpl = nodeImpl.parent;
+        }
+
+        return false;
+    }
+
+    @Override
+    public void normalize() {
+        Node nextNode = null;
+        
+        for (int i = children.size() - 1; i >= 0; i--) {
+            Node thisNode = children.get(i);
+
+            thisNode.normalize();
+            
+            if (thisNode.getNodeType() == Node.TEXT_NODE) {
+                if (nextNode != null && nextNode.getNodeType() == Node.TEXT_NODE) {
+                    ((Text)thisNode).setData(thisNode.getNodeValue() + nextNode.getNodeValue());
+                    removeChild(nextNode);
+                }
+                
+                if ("".equals(thisNode.getNodeValue())) {
+                    removeChild(thisNode);
+                    nextNode = null;
+                } else {
+                    nextNode = thisNode;
+                }
+            }
+        }
+    }
+
+    private void refreshIndices(int fromIndex) {
+        for (int i = fromIndex; i < children.size(); i++) {
+            children.get(i).index = i;
+        }
+    }
+
+    public Node removeChild(Node oldChild) throws DOMException {
+        LeafNodeImpl oldChildImpl = (LeafNodeImpl) oldChild;
+
+        if (oldChildImpl.document != document) {
+            throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, null);
+        }
+
+        if (oldChildImpl.parent != this) {
+            throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null);
+        }
+
+        int index = oldChildImpl.index;
+        children.remove(index);
+        oldChildImpl.parent = null;
+        refreshIndices(index);
+
+        return oldChild;
+    }
+
+    public Node replaceChild(Node newChild, Node oldChild) throws DOMException {
+        LeafNodeImpl oldChildImpl = (LeafNodeImpl) oldChild;
+        LeafNodeImpl newChildImpl = (LeafNodeImpl) newChild;
+
+        if (oldChildImpl.document != document
+                || newChildImpl.document != document) {
+            throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, null);
+        }
+
+        if (oldChildImpl.parent != this || newChildImpl.isParentOf(this)) {
+            throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null);
+        }
+
+        int index = oldChildImpl.index;
+        children.set(index, newChildImpl);
+        oldChildImpl.parent = null;
+        newChildImpl.parent = this;
+        refreshIndices(index);
+
+        return oldChildImpl;
+    }
+
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/LeafNodeImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/LeafNodeImpl.java
new file mode 100644
index 0000000..5f9698e
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/dom/LeafNodeImpl.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml.dom;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/**
+ * Provides a straightforward implementation of the corresponding W3C DOM
+ * interface. The class is used internally only, thus only notable members that
+ * are not in the original interface are documented (the W3C docs are quite
+ * extensive). Hope that's ok.
+ * <p>
+ * Some of the fields may have package visibility, so other classes belonging to
+ * the DOM implementation can easily access them while maintaining the DOM tree
+ * structure.
+ * <p>
+ * This class represents a Node that has a parent Node, but no children.
+ */
+public abstract class LeafNodeImpl extends NodeImpl {
+
+    // Maintained by InnerNodeImpl.
+    InnerNodeImpl parent;
+
+    // Maintained by InnerNodeImpl.
+    int index;
+
+    LeafNodeImpl(DocumentImpl document) {
+        super(document);
+    }
+
+    public Node getNextSibling() {
+        if (parent == null || index + 1 >= parent.children.size()) {
+            return null;
+        }
+
+        return parent.children.get(index + 1);
+    }
+
+    public Node getParentNode() {
+        return parent;
+    }
+
+    public Node getPreviousSibling() {
+        if (parent == null || index == 0) {
+            return null;
+        }
+
+        return parent.children.get(index - 1);
+    }
+
+    boolean isParentOf(Node node) {
+        return false;
+    }
+
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/NamedNodeMapImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/NamedNodeMapImpl.java
new file mode 100644
index 0000000..0952d83
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/dom/NamedNodeMapImpl.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml.dom;
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Provides a straightforward implementation of the corresponding W3C DOM
+ * interface. The class is used internally only, thus only notable members that
+ * are not in the original interface are documented (the W3C docs are quite
+ * extensive). Hope that's ok.
+ * <p>
+ * Some of the fields may have package visibility, so other classes belonging to
+ * the DOM implementation can easily access them while maintaining the DOM tree
+ * structure.
+ */
+public class NamedNodeMapImpl implements NamedNodeMap {
+
+    private Class<?> type;
+    
+    private List<NodeImpl> list;
+
+    NamedNodeMapImpl(Class<?> type) {
+        list = new ArrayList<NodeImpl>();
+        this.type = type;
+    }
+
+    NamedNodeMapImpl(List<NodeImpl> list, Class<?> type) {
+        this.list = list;
+        this.type = type;
+    }
+
+    public int getLength() {
+        return list.size();
+    }
+
+    private int indexOfItem(String name) {
+        for (int i = 0; i < list.size(); i++) {
+            NodeImpl node = list.get(i);
+            if (node.matchesName(name, false)) {
+                return i;
+            }
+        }
+        
+        return -1;
+    }
+    
+    private int indexOfItemNS(String namespaceURI, String localName) {
+        for (int i = 0; i < list.size(); i++) {
+            NodeImpl node = list.get(i);
+            if (node.matchesNameNS(namespaceURI, localName, false)) {
+                return i;
+            }
+        }
+        
+        return -1;
+    }
+
+    public Node getNamedItem(String name) {
+        int i = indexOfItem(name);
+        
+        return (i == -1 ? null : item(i));
+    }
+
+    public Node getNamedItemNS(String namespaceURI, String localName) {
+        int i = indexOfItemNS(namespaceURI, localName);
+        
+        return (i == -1 ? null : item(i));
+    }
+
+    public Node item(int index) {
+        return list.get(index);
+    }
+
+    public Node removeNamedItem(String name) throws DOMException {
+        int i = indexOfItem(name);
+        
+        if (i == -1) {
+            throw new DOMException(DOMException.NOT_FOUND_ERR, null);
+        }
+
+        return list.remove(i);
+    }
+
+    public Node removeNamedItemNS(String namespaceURI, String localName)
+            throws DOMException {
+        int i = indexOfItemNS(namespaceURI, localName);
+        
+        if (i == -1) {
+            throw new DOMException(DOMException.NOT_FOUND_ERR, null);
+        }
+
+        return list.remove(i);
+    }
+
+    public Node setNamedItem(Node arg) throws DOMException {
+        // Ensure we only accept nodes of the correct type.
+        if (!type.isAssignableFrom(arg.getClass())) {
+            throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null);
+        }
+        
+        // All nodes in the map must belong to the same document.
+        if (list.size() != 0) {
+            Document document = list.get(0).getOwnerDocument();
+
+            if (document != null && arg.getOwnerDocument() != document) {
+                throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null);
+            }
+        }
+
+// TODO Theoretically we should ensure that the nodes don't have a parent.
+//        if (newAttrImpl.getOwnerElement() != null) {
+//            throw new DOMException(DOMException.INUSE_ATTRIBUTE_ERR, null);
+//        }
+
+        int i = indexOfItem(arg.getNodeName());
+        
+        if (i != -1) {
+            list.remove(i);
+        }
+        
+        list.add((NodeImpl)arg);
+        return arg;
+    }
+
+    public Node setNamedItemNS(Node arg) throws DOMException {
+        // Ensure we only accept nodes of the correct type.
+        if (!type.isAssignableFrom(arg.getClass())) {
+            throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null);
+        }
+        
+        // All nodes in the map must belong to the same document.
+        if (list.size() != 0) {
+            Document document = list.get(0).getOwnerDocument();
+
+            if (document != null && arg.getOwnerDocument() != document) {
+                throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null);
+            }
+        }
+
+// TODO Theoretically we should ensure that the nodes don't have a parent.
+//        if (newAttrImpl.getOwnerElement() != null) {
+//            throw new DOMException(DOMException.INUSE_ATTRIBUTE_ERR, null);
+//        }
+
+        int i = indexOfItemNS(arg.getNamespaceURI(), arg.getLocalName());
+        
+        if (i != -1) {
+            list.remove(i);
+        }
+        
+        list.add((NodeImpl)arg);
+        return arg;
+    }
+
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java
new file mode 100644
index 0000000..ca6fb8f
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml.dom;
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Provides a straightforward implementation of the corresponding W3C DOM
+ * interface. The class is used internally only, thus only notable members that
+ * are not in the original interface are documented (the W3C docs are quite
+ * extensive). Hope that's ok.
+ * <p>
+ * Some of the fields may have package visibility, so other classes belonging to
+ * the DOM implementation can easily access them while maintaining the DOM tree
+ * structure.
+ * <p>
+ * This class represents a Node that has neither a parent nor children.
+ */
+public abstract class NodeImpl implements Node {
+
+    private static final NodeList EMPTY_LIST = new NodeListImpl();
+    
+    // Maintained by InnerNodeImpl and ElementImpl.
+    DocumentImpl document;
+
+    NodeImpl(DocumentImpl document) {
+        this.document = document;
+    }
+
+    public Node appendChild(Node newChild) throws DOMException {
+        throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null);
+    }
+
+    public Node cloneNode(boolean deep) {
+        return document.cloneNode(this, deep);
+    }
+
+    public NamedNodeMap getAttributes() {
+        return null;
+    }
+
+    public NodeList getChildNodes() {
+        return EMPTY_LIST;
+    }
+
+    public Node getFirstChild() {
+        return null;
+    }
+
+    public Node getLastChild() {
+        return null;
+    }
+
+    public String getLocalName() {
+        return null;
+    }
+
+    public String getNamespaceURI() {
+        return null;
+    }
+
+    public Node getNextSibling() {
+        return null;
+    }
+
+    public String getNodeName() {
+        return null;
+    }
+
+    public abstract short getNodeType();
+
+    public String getNodeValue() throws DOMException {
+        return null;
+    }
+
+    public Document getOwnerDocument() {
+        return document;
+    }
+
+    public Node getParentNode() {
+        return null;
+    }
+
+    public String getPrefix() {
+        return null;
+    }
+
+    public Node getPreviousSibling() {
+        return null;
+    }
+
+    public boolean hasAttributes() {
+        return false;
+    }
+
+    public boolean hasChildNodes() {
+        return false;
+    }
+
+    public Node insertBefore(Node newChild, Node refChild) throws DOMException {
+        throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null);
+    }
+
+    public boolean isSupported(String feature, String version) {
+        return DOMImplementationImpl.getInstance().hasFeature(feature, version);
+    }
+
+    public void normalize() {
+    }
+
+    public Node removeChild(Node oldChild) throws DOMException {
+        throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null);
+    }
+
+    public Node replaceChild(Node newChild, Node oldChild) throws DOMException {
+        throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null);
+    }
+
+    public void setNodeValue(String nodeValue) throws DOMException {
+    }
+
+    public void setPrefix(String prefix) throws DOMException {
+    }
+
+    /**
+     * Checks whether a required string matches an actual string. This utility
+     * method is used for comparing namespaces and such. It takes into account
+     * null arguments and the "*" special case.
+     * 
+     * @param required The required string.
+     * @param actual The actual string.
+     * @return True if and only if the actual string matches the required one.
+     */
+    private static boolean matchesName(String required, String actual, boolean wildcard) {
+        if (wildcard && "*".equals(required)) {
+            return true;
+        }
+        
+        if (required == null) {
+            return (actual == null);
+        }
+        
+        return required.equals(actual);
+    }
+
+    /**
+     * Checks whether this node's name matches a required name. It takes into
+     * account null arguments and the "*" special case.
+     * 
+     * @param name The required name.
+     * @param wildcard TODO
+     * @return True if and only if the actual name matches the required one.
+     */
+    public boolean matchesName(String name, boolean wildcard) {
+        return matchesName(name, getNodeName(), wildcard);
+    }
+
+    /**
+     * Checks whether this node's namespace and local name match a required
+     * pair of namespace and local name. It takes into account null arguments
+     * and the "*" special case.
+     *
+     * @param namespaceURI The required namespace.
+     * @param localName The required local name.
+     * @param wildcard TODO
+     * @return True if and only if the actual namespace and local name match
+     *         the required pair of namespace and local name.
+     */
+    public boolean matchesNameNS(String namespaceURI, String localName, boolean wildcard) {
+        return matchesName(namespaceURI, getNamespaceURI(), wildcard) && matchesName(localName, getLocalName(), wildcard);
+    }
+    
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/NodeListImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/NodeListImpl.java
new file mode 100644
index 0000000..caa56af
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/dom/NodeListImpl.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml.dom;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Provides a straightforward implementation of the corresponding W3C DOM
+ * interface. The class is used internally only, thus only notable members that
+ * are not in the original interface are documented (the W3C docs are quite
+ * extensive). Hope that's ok.
+ * <p>
+ * Some of the fields may have package visibility, so other classes belonging to
+ * the DOM implementation can easily access them while maintaining the DOM tree
+ * structure.
+ */
+public class NodeListImpl implements NodeList {
+
+    private List<NodeImpl> children;
+
+    NodeListImpl() {
+        children = new ArrayList<NodeImpl>();
+    }
+
+    NodeListImpl(List<NodeImpl> list) {
+        children = list;
+    }
+
+    void add(NodeImpl node) {
+        children.add(node);
+    }
+
+    public int getLength() {
+        return children.size();
+    }
+
+    public Node item(int index) {
+        if (index >= children.size()) {
+            return null;
+        } else {
+            return children.get(index);
+        }
+    }
+
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/NotationImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/NotationImpl.java
new file mode 100644
index 0000000..4d91d75
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/dom/NotationImpl.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml.dom;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.Notation;
+
+/**
+ * Provides a straightforward implementation of the corresponding W3C DOM
+ * interface. The class is used internally only, thus only notable members that
+ * are not in the original interface are documented (the W3C docs are quite
+ * extensive). Hope that's ok.
+ * <p>
+ * Some of the fields may have package visibility, so other classes belonging to
+ * the DOM implementation can easily access them while maintaining the DOM tree
+ * structure.
+ */
+public class NotationImpl extends LeafNodeImpl implements Notation {
+
+    private String notationName;
+
+    private String publicID;
+
+    private String systemID;
+
+    NotationImpl(DocumentImpl document, String notationName, String publicID,
+            String systemID) {
+        super(document);
+    }
+
+    @Override
+    public String getNodeName() {
+        return notationName;
+    }
+
+    @Override
+    public short getNodeType() {
+        return Node.NOTATION_NODE;
+    }
+
+    public String getPublicId() {
+        return publicID;
+    }
+
+    public String getSystemId() {
+        return systemID;
+    }
+
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/ProcessingInstructionImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/ProcessingInstructionImpl.java
new file mode 100644
index 0000000..c3610d5
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/dom/ProcessingInstructionImpl.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml.dom;
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+
+/**
+ * Provides a straightforward implementation of the corresponding W3C DOM
+ * interface. The class is used internally only, thus only notable members that
+ * are not in the original interface are documented (the W3C docs are quite
+ * extensive). Hope that's ok.
+ * <p>
+ * Some of the fields may have package visibility, so other classes belonging to
+ * the DOM implementation can easily access them while maintaining the DOM tree
+ * structure.
+ */
+public class ProcessingInstructionImpl extends LeafNodeImpl implements
+        ProcessingInstruction {
+
+    private String target;
+
+    private String data;
+
+    ProcessingInstructionImpl(DocumentImpl document, String target, String data) {
+        super(document);
+        this.target = target;
+        this.data = data;
+    }
+
+    public String getData() {
+        return data;
+    }
+
+    @Override
+    public String getNodeName() {
+        return target;
+    }
+
+    @Override
+    public short getNodeType() {
+        return Node.PROCESSING_INSTRUCTION_NODE;
+    }
+
+    @Override
+    public String getNodeValue() {
+        return data;
+    }
+
+    public String getTarget() {
+        return target;
+    }
+
+    public void setData(String data) throws DOMException {
+        this.data = data;
+    }
+
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/TextImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/TextImpl.java
new file mode 100644
index 0000000..3553546
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/dom/TextImpl.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml.dom;
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+/**
+ * Provides a straightforward implementation of the corresponding W3C DOM
+ * interface. The class is used internally only, thus only notable members that
+ * are not in the original interface are documented (the W3C docs are quite
+ * extensive). Hope that's ok.
+ * <p>
+ * Some of the fields may have package visibility, so other classes belonging to
+ * the DOM implementation can easily access them while maintaining the DOM tree
+ * structure.
+ */
+public class TextImpl extends CharacterDataImpl implements Text {
+
+    TextImpl(DocumentImpl document, String data) {
+        super(document, data);
+    }
+
+    @Override
+    public String getNodeName() {
+        return "#text";
+    }
+
+    @Override
+    public short getNodeType() {
+        return Node.TEXT_NODE;
+    }
+
+    @Override
+    public String getNodeValue() {
+        return getData();
+    }
+
+    public Text splitText(int offset) throws DOMException {
+        Text newText = getOwnerDocument().createTextNode(
+                substringData(offset, getLength() - offset));
+        deleteData(0, offset);
+
+        Node refNode = getNextSibling();
+        if (refNode == null) {
+            getParentNode().appendChild(newText);
+        } else {
+            getParentNode().insertBefore(newText, refNode);
+        }
+
+        return this;
+    }
+
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderFactoryImpl.java b/xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderFactoryImpl.java
new file mode 100644
index 0000000..4b8eef3
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderFactoryImpl.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml.parsers;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+/**
+ * Provides a straightforward DocumentBuilderFactory implementation based on
+ * XMLPull/KXML. The class is used internally only, thus only notable members
+ * that are not already in the abstract superclass are documented. Hope that's
+ * ok.
+ */
+public class DocumentBuilderFactoryImpl extends DocumentBuilderFactory {
+
+    private static final String NAMESPACES =
+            "http://xml.org/sax/features/namespaces";
+
+    private static final String VALIDATION =
+            "http://xml.org/sax/features/validation";
+    
+    @Override
+    public Object getAttribute(String name) throws IllegalArgumentException {
+        throw new IllegalArgumentException(name);
+    }
+
+    @Override
+    public boolean getFeature(String name) throws ParserConfigurationException {
+        if (name == null) {
+            throw new NullPointerException();
+        }
+        
+        if (NAMESPACES.equals(name)) {
+            return isNamespaceAware();
+        } else if (VALIDATION.equals(name)) {
+            return isValidating();
+        } else {
+            throw new ParserConfigurationException(name);
+        }
+    }
+
+    @Override
+    public DocumentBuilder newDocumentBuilder()
+            throws ParserConfigurationException {
+        if (isValidating()) {
+            throw new ParserConfigurationException(
+                    "No validating DocumentBuilder implementation available");
+        }
+        
+        /**
+         * TODO If Android is going to support a different DocumentBuilder
+         * implementations, this should be wired here. If we wanted to
+         * allow different implementations, these could be distinguished by
+         * a special feature (like http://www.org.apache.harmony.com/xml/expat)
+         * or by throwing the full SPI monty at it.  
+         */
+        DocumentBuilderImpl builder = new DocumentBuilderImpl();
+        
+        builder.setIgnoreComments(isIgnoringComments());
+        builder.setIgnoreElementContentWhitespace(
+                isIgnoringElementContentWhitespace());
+        builder.setNamespaceAware(isNamespaceAware());
+
+        // TODO What about expandEntityReferences?
+        
+        return builder;
+    }
+    
+    @Override
+    public void setAttribute(String name, Object value)
+            throws IllegalArgumentException {
+        throw new IllegalArgumentException(name);
+    }
+
+    @Override
+    public void setFeature(String name, boolean value)
+            throws ParserConfigurationException {
+        if (name == null) {
+            throw new NullPointerException();
+        }
+
+        if (NAMESPACES.equals(name)) {
+            setNamespaceAware(value);
+        } else if (VALIDATION.equals(name)) {
+            setValidating(value);
+        } else {
+            throw new ParserConfigurationException(name);
+        }
+    }
+
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java b/xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java
new file mode 100644
index 0000000..f831c8b
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java
@@ -0,0 +1,436 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml.parsers;
+
+import java.io.IOException;
+import java.util.StringTokenizer;
+
+import javax.xml.parsers.DocumentBuilder;
+
+import org.kxml2.io.KXmlParser;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.LocatorImpl;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import org.apache.harmony.xml.dom.DOMImplementationImpl;
+
+/**
+ * Provides a straightforward DocumentBuilder implementation based on
+ * XMLPull/KXML. The class is used internally only, thus only notable members
+ * that are not already in the abstract superclass are documented. Hope that's
+ * ok.
+ */
+class DocumentBuilderImpl extends DocumentBuilder {
+
+    private static DOMImplementation dom = DOMImplementationImpl.getInstance();
+
+    private EntityResolver entityResolver;
+
+    private ErrorHandler errorHandler;
+
+    private boolean ignoreComments;
+
+    private boolean ignoreElementContentWhitespace;
+
+    private boolean namespaceAware;
+
+    DocumentBuilderImpl() {
+        // Do nothing.
+    }
+
+    @Override
+    public DOMImplementation getDOMImplementation() {
+        return dom;
+    }
+
+    /**
+     * Reflects whether this DocumentBuilder is configured to ignore comments.
+     * 
+     * @return True if and only if comments are ignored.
+     */
+    public boolean isIgnoringComments() {
+        return ignoreComments;
+    }
+
+    /**
+     * Reflects whether this DocumentBuilder is configured to ignore element
+     * content whitespace.
+     * 
+     * @return True if and only if whitespace element content is ignored.
+     */
+    public boolean isIgnoringElementContentWhitespace() {
+        return ignoreElementContentWhitespace;
+    }
+
+    @Override
+    public boolean isNamespaceAware() {
+        return namespaceAware;
+    }
+
+    @Override
+    public boolean isValidating() {
+        return false;
+    }
+
+    @Override
+    public Document newDocument() {
+        return dom.createDocument(null, null, null);
+    }
+
+    @Override
+    public Document parse(InputSource source) throws SAXException, IOException {
+        if (source == null) {
+            throw new IllegalArgumentException();
+        }
+        
+        Document document = newDocument();
+
+        try {
+            XmlPullParser parser = new KXmlParser();
+
+            parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES,
+                    namespaceAware);
+            
+            if (source.getByteStream() != null) {
+                parser.setInput(source.getByteStream(), source.getEncoding());
+            } else if (source.getCharacterStream() != null) {
+                parser.setInput(source.getCharacterStream());
+            } else {
+                // TODO Accept other sources as well?
+                throw new SAXParseException(
+                        "InputSource needs either stream or reader", null);
+            }
+
+            if(parser.nextToken() == XmlPullParser.END_DOCUMENT) {
+                throw new SAXParseException(
+                        "Unexpected end of document", null);
+            }
+
+            parse(parser, document, document, XmlPullParser.END_DOCUMENT);
+
+            parser.require(XmlPullParser.END_DOCUMENT, null, null);
+        } catch (XmlPullParserException ex) {
+            if(ex.getDetail() instanceof IOException) {
+                throw (IOException)ex.getDetail();
+            }
+            if(ex.getDetail() instanceof RuntimeException) {
+                throw (RuntimeException)ex.getDetail();
+            }
+            
+            LocatorImpl locator = new LocatorImpl();
+
+            locator.setPublicId(source.getPublicId());
+            locator.setSystemId(source.getSystemId());
+            locator.setLineNumber(ex.getLineNumber());
+            locator.setColumnNumber(ex.getColumnNumber());
+
+            SAXParseException newEx = new SAXParseException(ex.getMessage(),
+                    locator);
+
+            if (errorHandler != null) {
+                errorHandler.error(newEx);
+            }
+
+            throw newEx;
+        }
+
+        return document;
+    }
+
+    /**
+     * Implements the whole parsing of the XML document. The XML pull parser is
+     * actually more of a tokenizer, and we are doing a classical recursive
+     * descent parsing (the method invokes itself for XML elements). Our
+     * approach to parsing does accept some illegal documents (more than one
+     * root element, for example). The assumption is that the DOM implementation
+     * throws the proper exceptions in these cases.
+     * 
+     * @param parser The XML pull parser we're reading from.
+     * @param document The document we're building.
+     * @param node The node we're currently on (initially the document itself).
+     * @param endToken The token that will end this recursive call. Either
+     *        XmlPullParser.END_DOCUMENT or XmlPullParser.END_TAG.
+     * 
+     * @throws XmlPullParserException If a parsing error occurs.
+     * @throws IOException If a general IO error occurs.
+     */
+    private void parse(XmlPullParser parser, Document document, Node node,
+            int endToken) throws XmlPullParserException, IOException {
+
+        int token = parser.getEventType();
+
+        /*
+         * The main parsing loop. The precondition is that we are already on the
+         * token to be processed. This holds for each iteration of the loop, so
+         * the inner statements have to ensure that (in particular the recursive
+         * call).
+         */
+        while (token != endToken && token != XmlPullParser.END_DOCUMENT) {
+            if (token == XmlPullParser.PROCESSING_INSTRUCTION) {
+                /*
+                 * Found a processing instructions. We need to split the token
+                 * text at the first whitespace character.
+                 */
+                String text = parser.getText();
+
+                int dot = text.indexOf(' ');
+
+                String target = (dot != -1 ? text.substring(0, dot) : text);
+                String data = (dot != -1 ? text.substring(dot + 1) : "");
+
+                node.appendChild(document.createProcessingInstruction(target,
+                        data));
+            } else if (token == XmlPullParser.DOCDECL) {
+                /*
+                 * Found a document type declaration. Unfortunately KXML doesn't
+                 * have the necessary details. Do we parse it ourselves, or do
+                 * we silently ignore it, since it isn't mandatory in DOM 2
+                 * anyway?
+                 */
+                StringTokenizer tokenizer = new StringTokenizer(parser.getText());
+                if (tokenizer.hasMoreTokens()) {
+                    String name = tokenizer.nextToken();
+                    String pubid = null;
+                    String sysid = null;
+                    
+                    if (tokenizer.hasMoreTokens()) {
+                        String text = tokenizer.nextToken();
+                        
+                        if ("SYSTEM".equals(text)) {
+                            if (tokenizer.hasMoreTokens()) {
+                                sysid = tokenizer.nextToken();
+                            }
+                        } else if ("PUBLIC".equals(text)) {
+                            if (tokenizer.hasMoreTokens()) {
+                                pubid = tokenizer.nextToken();
+                            }
+                            if (tokenizer.hasMoreTokens()) {
+                                sysid = tokenizer.nextToken();
+                            }
+                        }
+                    }
+                    
+                    if (pubid != null && pubid.length() >= 2 && pubid.startsWith("\"") && pubid.endsWith("\"")) {
+                        pubid = pubid.substring(1, pubid.length() - 1);
+                    }
+                    
+                    if (sysid != null && sysid.length() >= 2 && sysid.startsWith("\"") && sysid.endsWith("\"")) {
+                        sysid = sysid.substring(1, sysid.length() - 1);
+                    }
+                    
+                    document.appendChild(dom.createDocumentType(name, pubid, sysid));
+                }
+                
+            } else if (token == XmlPullParser.COMMENT) {
+                /*
+                 * Found a comment. We simply take the token text, but we only
+                 * create a node if the client wants to see comments at all.
+                 */
+                if (!ignoreComments) {
+                    node.appendChild(document.createComment(parser.getText()));
+                }
+            } else if (token == XmlPullParser.IGNORABLE_WHITESPACE) {
+                /*
+                 * Found some ignorable whitespace. We simply take the token
+                 * text, but we only create a node if the client wants to see
+                 * whitespace at all.
+                 */
+                if (!ignoreElementContentWhitespace) {
+                    node.appendChild(document.createTextNode(parser.getText()));
+                }
+            } else if (token == XmlPullParser.TEXT) {
+                /*
+                 * Found a piece of text. That's the easiest case. We simply
+                 * take it and create a corresponding node.
+                 */
+                node.appendChild(document.createTextNode(parser.getText()));
+            } else if (token == XmlPullParser.CDSECT) {
+                /*
+                 * Found a CDATA section. That's also trivial. We simply
+                 * take it and create a corresponding node.
+                 */
+                node.appendChild(document.createCDATASection(parser.getText()));
+            } else if (token == XmlPullParser.ENTITY_REF) {
+                /*
+                 * Found an entity reference. If an entity resolver is
+                 * installed, we replace it by text (if possible). Otherwise we
+                 * add an entity reference node.
+                 */
+                String entity = parser.getName();
+
+                if (entityResolver != null) {
+                    // TODO Implement this...
+                }
+
+                String replacement = resolveStandardEntity(entity);
+                if (replacement != null) {
+                    node.appendChild(document.createTextNode(replacement));
+                } else {
+                    node.appendChild(document.createEntityReference(entity));
+                }
+            } else if (token == XmlPullParser.START_TAG) {
+                /*
+                 * Found an element start tag. We create an element node with
+                 * the proper info and attributes. We then invoke parse()
+                 * recursively to handle the next level of nesting. When we
+                 * return from this call, we check that we are on the proper
+                 * element end tag. The whole handling differs somewhat
+                 * depending on whether the parser is namespace-aware or not.
+                 */
+                if (namespaceAware) {
+                    // Collect info for element node
+                    String namespace = parser.getNamespace();
+                    String name = parser.getName();
+                    String prefix = parser.getPrefix();
+
+                    if ("".equals(namespace)) {
+                        namespace = null;
+                    }
+                    
+                    // Create element node and wire it correctly
+                    Element element = document.createElementNS(namespace, name);
+                    element.setPrefix(prefix);
+                    node.appendChild(element);
+
+                    for (int i = 0; i < parser.getAttributeCount(); i++) {
+                        // Collect info for a single attribute node
+                        String attrNamespace = parser.getAttributeNamespace(i);
+                        String attrPrefix = parser.getAttributePrefix(i);
+                        String attrName = parser.getAttributeName(i);
+                        String attrValue = parser.getAttributeValue(i);
+
+                        if ("".equals(attrNamespace)) {
+                            attrNamespace = null;
+                        }
+                        
+                        // Create attribute node and wire it correctly
+                        Attr attr = document.createAttributeNS(attrNamespace, attrName);
+                        attr.setPrefix(attrPrefix);
+                        attr.setValue(attrValue);
+                        element.setAttributeNodeNS(attr);
+                    }
+                    
+                    // Recursive descent
+                    token = parser.nextToken();
+                    parse(parser, document, element, XmlPullParser.END_TAG);
+
+                    // Expect the element's end tag here
+                    parser.require(XmlPullParser.END_TAG, namespace, name);
+                    
+                } else {
+                    // Collect info for element node
+                    String name = parser.getName();
+
+                    // Create element node and wire it correctly
+                    Element element = document.createElement(name);
+                    node.appendChild(element);
+
+                    for (int i = 0; i < parser.getAttributeCount(); i++) {
+                        // Collect info for a single attribute node
+                        String attrName = parser.getAttributeName(i);
+                        String attrValue = parser.getAttributeValue(i);
+
+                        // Create attribute node and wire it correctly
+                        Attr attr = document.createAttribute(attrName);
+                        attr.setValue(attrValue);
+                        element.setAttributeNode(attr);
+                    }
+
+                    // Recursive descent
+                    token = parser.nextToken();
+                    parse(parser, document, element, XmlPullParser.END_TAG);
+
+                    // Expect the element's end tag here
+                    parser.require(XmlPullParser.END_TAG, "", name);
+                }
+            }
+
+            token = parser.nextToken();
+        }
+    }
+
+    @Override
+    public void setEntityResolver(EntityResolver resolver) {
+        entityResolver = resolver;
+    }
+
+    @Override
+    public void setErrorHandler(ErrorHandler handler) {
+        errorHandler = handler;
+    }
+
+    /**
+     * Controls whether this DocumentBuilder ignores comments.
+     * 
+     * @param value Turns comment ignorance on or off.
+     */
+    public void setIgnoreComments(boolean value) {
+        ignoreComments = value;
+    }
+
+    /**
+     * Controls whether this DocumentBuilder ignores element content whitespace.
+     * 
+     * @param value Turns element whitespace content ignorance on or off.
+     */
+    public void setIgnoreElementContentWhitespace(boolean value) {
+        ignoreElementContentWhitespace = value;
+    }
+
+    /**
+     * Controls whether this DocumentBuilder is namespace-aware.
+     * 
+     * @param value Turns namespace awareness on or off.
+     */
+    public void setNamespaceAware(boolean value) {
+        namespaceAware = value;
+    }
+
+    /**
+     * Resolves one of the five standard XML entities.
+     * 
+     * @param entity The name of the entity to resolve, not including
+     *               the ampersand or the semicolon.
+     * 
+     * @return The proper replacement, or null, if the entity is unknown.
+     */
+    private String resolveStandardEntity(String entity) {
+        if ("lt".equals(entity)) {
+            return "<";
+        } else if ("gt".equals(entity)) {
+            return ">";
+        } else if ("amp".equals(entity)) {
+            return "&";
+        } else if ("apos".equals(entity)) {
+            return "'";
+        } else if ("quot".equals(entity)) {
+            return "\"";
+        } else {
+            return null;
+        }
+    }
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/parsers/SAXParserFactoryImpl.java b/xml/src/main/java/org/apache/harmony/xml/parsers/SAXParserFactoryImpl.java
new file mode 100644
index 0000000..6846216
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/parsers/SAXParserFactoryImpl.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml.parsers;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.SAXNotRecognizedException;
+
+/**
+ * Provides a straightforward SAXParserFactory implementation based on
+ * Expat. The class is used internally only, thus only notable members
+ * that are not already in the abstract superclass are documented.
+ */
+public class SAXParserFactoryImpl extends SAXParserFactory {
+
+    private static final String NAMESPACES
+            = "http://xml.org/sax/features/namespaces";
+    
+    private static final String VALIDATION
+            = "http://xml.org/sax/features/validation";
+    
+    private Map<String, Boolean> features = new HashMap<String, Boolean>();
+
+    @Override
+    public boolean getFeature(String name) throws SAXNotRecognizedException {
+        if (name == null) {
+            throw new NullPointerException();
+        }
+        
+        if (!name.startsWith("http://xml.org/sax/features/")) {
+            throw new SAXNotRecognizedException(name);
+        }
+        
+        return Boolean.TRUE.equals(features.get(name));
+    }
+
+    @Override
+    public boolean isNamespaceAware() {
+        try {
+            return getFeature(NAMESPACES);
+        } catch (SAXNotRecognizedException ex) {
+            throw new AssertionError(ex);
+        }
+    }
+
+    @Override
+    public boolean isValidating() {
+        try {
+            return getFeature(VALIDATION);
+        } catch (SAXNotRecognizedException ex) {
+            throw new AssertionError(ex);
+        }
+    }
+
+    @Override
+    public SAXParser newSAXParser() throws ParserConfigurationException {
+        if (isValidating()) {
+            throw new ParserConfigurationException(
+                    "No validating SAXParser implementation available");
+        }
+        
+        try {
+            return new SAXParserImpl(features);
+        } catch (Exception ex) {
+            throw new ParserConfigurationException(ex.toString());
+        }
+    }
+
+    @Override
+    public void setFeature(String name, boolean value) throws SAXNotRecognizedException {
+        if (name == null) {
+            throw new NullPointerException();
+        }
+        
+        if (!name.startsWith("http://xml.org/sax/features/")) {
+            throw new SAXNotRecognizedException(name);
+        }
+        
+        if (value) {
+            features.put(name, Boolean.TRUE);
+        } else {
+            // This is needed to disable features that are enabled by default.
+            features.put(name, Boolean.FALSE);
+        }
+    }
+
+    @Override
+    public void setNamespaceAware(boolean value) {
+        try {
+            setFeature(NAMESPACES, value);
+        } catch (SAXNotRecognizedException ex) {
+            throw new AssertionError(ex);
+        }
+    }
+
+    @Override
+    public void setValidating(boolean value) {
+        try {
+            setFeature(VALIDATION, value);
+        } catch (SAXNotRecognizedException ex) {
+            throw new AssertionError(ex);
+        }
+    }
+}
diff --git a/xml/src/main/java/org/apache/harmony/xml/parsers/SAXParserImpl.java b/xml/src/main/java/org/apache/harmony/xml/parsers/SAXParserImpl.java
new file mode 100644
index 0000000..b3af61f
--- /dev/null
+++ b/xml/src/main/java/org/apache/harmony/xml/parsers/SAXParserImpl.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml.parsers;
+
+import org.apache.harmony.xml.ExpatReader;
+
+import java.util.Map;
+
+import javax.xml.parsers.SAXParser;
+
+import org.xml.sax.Parser;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLReaderAdapter;
+
+/**
+ * Provides a straightforward SAXParser implementation based on ExpatReader.
+ * The class is used internally only, thus only notable members that are not
+ * already in the abstract superclass are documented. Hope that's ok.
+ */
+class SAXParserImpl extends SAXParser {
+
+    private XMLReader reader;
+
+    private Parser parser;
+
+    SAXParserImpl(Map<String, Boolean> features)
+            throws SAXNotRecognizedException, SAXNotSupportedException {
+        reader = new ExpatReader();
+
+        for (Map.Entry<String,Boolean> entry : features.entrySet()) {
+            reader.setFeature(entry.getKey(), entry.getValue());
+        }
+    }
+
+    @Override
+    public Parser getParser() {
+        if (parser == null) {
+            parser = new XMLReaderAdapter(reader);
+        }
+
+        return parser;
+    }
+
+    @Override
+    public Object getProperty(String name) throws SAXNotRecognizedException,
+            SAXNotSupportedException {
+        return reader.getProperty(name);
+    }
+
+    @Override
+    public XMLReader getXMLReader() {
+        return reader;
+    }
+
+    @Override
+    public boolean isNamespaceAware() {
+        try {
+            return reader.getFeature("http://xml.org/sax/features/namespaces");
+        } catch (SAXException ex) {
+            return false;
+        }
+    }
+
+    @Override
+    public boolean isValidating() {
+        return false;
+    }
+
+    @Override
+    public void setProperty(String name, Object value)
+            throws SAXNotRecognizedException, SAXNotSupportedException {
+        reader.setProperty(name, value);
+    }
+}
diff --git a/xml/src/main/java/org/kxml2/io/KXmlParser.java b/xml/src/main/java/org/kxml2/io/KXmlParser.java
new file mode 100644
index 0000000..0727bc7
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/io/KXmlParser.java
@@ -0,0 +1,1440 @@
+/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The  above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE. */
+
+// Contributors: Paul Hackenberger (unterminated entity handling in relaxed mode)
+
+package org.kxml2.io;
+
+import java.io.*;
+import java.util.*;
+
+import org.xmlpull.v1.*;
+
+/** A simple, pull based XML parser. This classe replaces the kXML 1
+    XmlParser class and the corresponding event classes. */
+
+public class KXmlParser implements XmlPullParser {
+
+    private Object location;
+    static final private String UNEXPECTED_EOF = "Unexpected EOF";
+    static final private String ILLEGAL_TYPE = "Wrong event type";
+    static final private int LEGACY = 999;
+    static final private int XML_DECL = 998;
+
+    // general
+
+    private String version;
+    private Boolean standalone;
+
+    private boolean processNsp;
+    private boolean relaxed;
+    private Hashtable entityMap;
+    private int depth;
+    private String[] elementStack = new String[16];
+    private String[] nspStack = new String[8];
+    private int[] nspCounts = new int[4];
+
+    // source
+
+    private Reader reader;
+    private String encoding;
+    private char[] srcBuf;
+
+    private int srcPos;
+    private int srcCount;
+
+    private int line;
+    private int column;
+
+    // txtbuffer
+
+    private char[] txtBuf = new char[128];
+    private int txtPos;
+
+    // Event-related
+
+    private int type;
+    //private String text;
+    private boolean isWhitespace;
+    private String namespace;
+    private String prefix;
+    private String name;
+
+    private boolean degenerated;
+    private int attributeCount;
+    private String[] attributes = new String[16];
+    private int stackMismatch = 0;
+    private String error;
+
+    /** 
+     * A separate peek buffer seems simpler than managing
+     * wrap around in the first level read buffer */
+
+    private int[] peek = new int[2];
+    private int peekCount;
+    private boolean wasCR;
+
+    private boolean unresolved;
+    private boolean token;
+
+    public KXmlParser() {
+        // BEGIN android-changed
+        // We don't have a Runtime class at this time.
+        // srcBuf =
+        //         new char[Runtime.getRuntime().freeMemory() >= 1048576 ? 8192 : 128];
+        srcBuf = new char[8192];
+        // END android-changed
+    }
+
+    private final boolean isProp(String n1, boolean prop, String n2) {
+        if (!n1.startsWith("http://xmlpull.org/v1/doc/"))
+            return false;
+        if (prop)
+            return n1.substring(42).equals(n2);
+        else
+            return n1.substring(40).equals(n2);
+    }
+
+    private final boolean adjustNsp() throws XmlPullParserException {
+
+        boolean any = false;
+
+        for (int i = 0; i < attributeCount << 2; i += 4) {
+            // * 4 - 4; i >= 0; i -= 4) {
+
+            String attrName = attributes[i + 2];
+            int cut = attrName.indexOf(':');
+            String prefix;
+
+            if (cut != -1) {
+                prefix = attrName.substring(0, cut);
+                attrName = attrName.substring(cut + 1);
+            }
+            else if (attrName.equals("xmlns")) {
+                prefix = attrName;
+                attrName = null;
+            }
+            else
+                continue;
+
+            if (!prefix.equals("xmlns")) {
+                any = true;
+            }
+            else {
+                int j = (nspCounts[depth]++) << 1;
+
+                nspStack = ensureCapacity(nspStack, j + 2);
+                nspStack[j] = attrName;
+                nspStack[j + 1] = attributes[i + 3];
+
+                if (attrName != null && attributes[i + 3].equals(""))
+                    error("illegal empty namespace");
+
+                //  prefixMap = new PrefixMap (prefixMap, attrName, attr.getValue ());
+
+                //System.out.println (prefixMap);
+
+                System.arraycopy(
+                    attributes,
+                    i + 4,
+                    attributes,
+                    i,
+                    ((--attributeCount) << 2) - i);
+
+                i -= 4;
+            }
+        }
+
+        if (any) {
+            for (int i = (attributeCount << 2) - 4; i >= 0; i -= 4) {
+
+                String attrName = attributes[i + 2];
+                int cut = attrName.indexOf(':');
+
+                if (cut == 0 && !relaxed)
+                    throw new RuntimeException(
+                        "illegal attribute name: " + attrName + " at " + this);
+
+                else if (cut != -1) {
+                    String attrPrefix = attrName.substring(0, cut);
+
+                    attrName = attrName.substring(cut + 1);
+
+                    String attrNs = getNamespace(attrPrefix);
+
+                    if (attrNs == null && !relaxed)
+                        throw new RuntimeException(
+                            "Undefined Prefix: " + attrPrefix + " in " + this);
+
+                    attributes[i] = attrNs;
+                    attributes[i + 1] = attrPrefix;
+                    attributes[i + 2] = attrName;
+
+                    /*
+                                        if (!relaxed) {
+                                            for (int j = (attributeCount << 2) - 4; j > i; j -= 4)
+                                                if (attrName.equals(attributes[j + 2])
+                                                    && attrNs.equals(attributes[j]))
+                                                    exception(
+                                                        "Duplicate Attribute: {"
+                                                            + attrNs
+                                                            + "}"
+                                                            + attrName);
+                                        }
+                        */
+                }
+            }
+        }
+
+        int cut = name.indexOf(':');
+
+        if (cut == 0)
+            error("illegal tag name: " + name);
+
+        if (cut != -1) {
+            prefix = name.substring(0, cut);
+            name = name.substring(cut + 1);
+        }
+
+        this.namespace = getNamespace(prefix);
+
+        if (this.namespace == null) {
+            if (prefix != null)
+                error("undefined prefix: " + prefix);
+            this.namespace = NO_NAMESPACE;
+        }
+
+        return any;
+    }
+
+    private final String[] ensureCapacity(String[] arr, int required) {
+        if (arr.length >= required)
+            return arr;
+        String[] bigger = new String[required + 16];
+        System.arraycopy(arr, 0, bigger, 0, arr.length);
+        return bigger;
+    }
+
+    private final void error(String desc) throws XmlPullParserException {
+        if (relaxed) {
+            if (error == null)
+                error = "ERR: " + desc;
+        }
+        else
+            exception(desc);
+    }
+
+    private final void exception(String desc) throws XmlPullParserException {
+        throw new XmlPullParserException(
+            desc.length() < 100 ? desc : desc.substring(0, 100) + "\n",
+            this,
+            null);
+    }
+
+    /** 
+     * common base for next and nextToken. Clears the state, except from 
+     * txtPos and whitespace. Does not set the type variable */
+
+    private final void nextImpl() throws IOException, XmlPullParserException {
+
+        if (reader == null)
+            exception("No Input specified");
+
+        if (type == END_TAG)
+            depth--;
+
+        while (true) {
+            attributeCount = -1;
+
+            // degenerated needs to be handled before error because of possible
+            // processor expectations(!)
+
+            if (degenerated) {
+                degenerated = false;
+                type = END_TAG;
+                return;
+            }
+
+
+            if (error != null) {
+                for (int i = 0; i < error.length(); i++)
+                    push(error.charAt(i));
+                //                text = error;
+                error = null;
+                type = COMMENT;
+                return;
+            }
+
+
+            if (relaxed
+                && (stackMismatch > 0 || (peek(0) == -1 && depth > 0))) {
+                int sp = (depth - 1) << 2;
+                type = END_TAG;
+                namespace = elementStack[sp];
+                prefix = elementStack[sp + 1];
+                name = elementStack[sp + 2];
+                if (stackMismatch != 1)
+                    error = "missing end tag /" + name + " inserted";
+                if (stackMismatch > 0)
+                    stackMismatch--;
+                return;
+            }
+
+            prefix = null;
+            name = null;
+            namespace = null;
+            //            text = null;
+
+            type = peekType();
+
+            switch (type) {
+
+                case ENTITY_REF :
+                    pushEntity();
+                    return;
+
+                case START_TAG :
+                    parseStartTag(false);
+                    return;
+
+                case END_TAG :
+                    parseEndTag();
+                    return;
+
+                case END_DOCUMENT :
+                    return;
+
+                case TEXT :
+                    pushText('<', !token);
+                    if (depth == 0) {
+                        if (isWhitespace)
+                            type = IGNORABLE_WHITESPACE;
+                        // make exception switchable for instances.chg... !!!!
+                        //    else 
+                        //    exception ("text '"+getText ()+"' not allowed outside root element");
+                    }
+                    return;
+
+                default :
+                    type = parseLegacy(token);
+                    if (type != XML_DECL)
+                        return;
+            }
+        }
+    }
+
+    private final int parseLegacy(boolean push)
+        throws IOException, XmlPullParserException {
+
+        String req = "";
+        int term;
+        int result;
+        int prev = 0;
+
+        read(); // <
+        int c = read();
+
+        if (c == '?') {
+            if ((peek(0) == 'x' || peek(0) == 'X')
+                && (peek(1) == 'm' || peek(1) == 'M')) {
+
+                if (push) {
+                    push(peek(0));
+                    push(peek(1));
+                }
+                read();
+                read();
+
+                if ((peek(0) == 'l' || peek(0) == 'L') && peek(1) <= ' ') {
+
+                    if (line != 1 || column > 4)
+                        error("PI must not start with xml");
+
+                    parseStartTag(true);
+
+                    if (attributeCount < 1 || !"version".equals(attributes[2]))
+                        error("version expected");
+
+                    version = attributes[3];
+
+                    int pos = 1;
+
+                    if (pos < attributeCount
+                        && "encoding".equals(attributes[2 + 4])) {
+                        encoding = attributes[3 + 4];
+                        pos++;
+                    }
+
+                    if (pos < attributeCount
+                        && "standalone".equals(attributes[4 * pos + 2])) {
+                        String st = attributes[3 + 4 * pos];
+                        if ("yes".equals(st))
+                            standalone = new Boolean(true);
+                        else if ("no".equals(st))
+                            standalone = new Boolean(false);
+                        else
+                            error("illegal standalone value: " + st);
+                        pos++;
+                    }
+
+                    if (pos != attributeCount)
+                        error("illegal xmldecl");
+
+                    isWhitespace = true;
+                    txtPos = 0;
+
+                    return XML_DECL;
+                }
+            }
+
+            /*            int c0 = read ();
+                        int c1 = read ();
+                        int */
+
+            term = '?';
+            result = PROCESSING_INSTRUCTION;
+        }
+        else if (c == '!') {
+            if (peek(0) == '-') {
+                result = COMMENT;
+                req = "--";
+                term = '-';
+            }
+            else if (peek(0) == '[') {
+                result = CDSECT;
+                req = "[CDATA[";
+                term = ']';
+                push = true;
+            }
+            else {
+                result = DOCDECL;
+                req = "DOCTYPE";
+                term = -1;
+            }
+        }
+        else {
+            error("illegal: <" + c);
+            return COMMENT;
+        }
+
+        for (int i = 0; i < req.length(); i++)
+            read(req.charAt(i));
+
+        if (result == DOCDECL)
+            parseDoctype(push);
+        else {
+            while (true) {
+                c = read();
+                if (c == -1){
+                    error(UNEXPECTED_EOF);
+                    return COMMENT;
+                }
+
+                if (push)
+                    push(c);
+
+                if ((term == '?' || c == term)
+                    && peek(0) == term
+                    && peek(1) == '>')
+                    break;
+
+                prev = c;
+            }
+
+            if (term == '-' && prev == '-')
+                error("illegal comment delimiter: --->");
+
+            read();
+            read();
+
+            if (push && term != '?')
+                txtPos--;
+
+        }
+        return result;
+    }
+
+    /** precondition: &lt! consumed */
+
+    private final void parseDoctype(boolean push)
+        throws IOException, XmlPullParserException {
+
+        int nesting = 1;
+        boolean quoted = false;
+
+        // read();
+
+        while (true) {
+            int i = read();
+            switch (i) {
+
+                case -1 :
+                    error(UNEXPECTED_EOF);
+                    return;
+
+                case '\'' :
+                    quoted = !quoted;
+                    break;
+
+                case '<' :
+                    if (!quoted)
+                        nesting++;
+                    break;
+
+                case '>' :
+                    if (!quoted) {
+                        if ((--nesting) == 0)
+                            return;
+                    }
+                    break;
+            }
+            if (push)
+                push(i);
+        }
+    }
+
+    /* precondition: &lt;/ consumed */
+
+    private final void parseEndTag()
+        throws IOException, XmlPullParserException {
+
+        read(); // '<'
+        read(); // '/'
+        name = readName();
+        skip();
+        read('>');
+
+        int sp = (depth - 1) << 2;
+
+        if (depth == 0) {
+            error("element stack empty");
+            type = COMMENT;
+            return;
+        }
+
+        if (!name.equals(elementStack[sp + 3])) {
+            error("expected: /" + elementStack[sp + 3] + " read: " + name);
+
+            // become case insensitive in relaxed mode
+
+            int probe = sp;
+            while (probe >= 0 && !name.toLowerCase().equals(elementStack[probe + 3].toLowerCase())) {
+                stackMismatch++;
+                probe -= 4;
+            }
+
+            if (probe < 0) {
+                stackMismatch = 0;
+                //            text = "unexpected end tag ignored";
+                type = COMMENT;
+                return;
+            }
+        }
+
+        namespace = elementStack[sp];
+        prefix = elementStack[sp + 1];
+        name = elementStack[sp + 2];
+    }
+
+    private final int peekType() throws IOException {
+        switch (peek(0)) {
+            case -1 :
+                return END_DOCUMENT;
+            case '&' :
+                return ENTITY_REF;
+            case '<' :
+                switch (peek(1)) {
+                    case '/' :
+                        return END_TAG;
+                    case '?' :
+                    case '!' :
+                        return LEGACY;
+                    default :
+                        return START_TAG;
+                }
+            default :
+                return TEXT;
+        }
+    }
+
+    private final String get(int pos) {
+        return new String(txtBuf, pos, txtPos - pos);
+    }
+
+    /*
+    private final String pop (int pos) {
+    String result = new String (txtBuf, pos, txtPos - pos);
+    txtPos = pos;
+    return result;
+    }
+    */
+
+    private final void push(int c) {
+
+        isWhitespace &= c <= ' ';
+
+        if (txtPos == txtBuf.length) {
+            char[] bigger = new char[txtPos * 4 / 3 + 4];
+            System.arraycopy(txtBuf, 0, bigger, 0, txtPos);
+            txtBuf = bigger;
+        }
+
+        txtBuf[txtPos++] = (char) c;
+    }
+
+    /** Sets name and attributes */
+
+    private final void parseStartTag(boolean xmldecl)
+        throws IOException, XmlPullParserException {
+
+        if (!xmldecl)
+            read();
+        name = readName();
+        attributeCount = 0;
+
+        while (true) {
+            skip();
+
+            int c = peek(0);
+
+            if (xmldecl) {
+                if (c == '?') {
+                    read();
+                    read('>');
+                    return;
+                }
+            }
+            else {
+                if (c == '/') {
+                    degenerated = true;
+                    read();
+                    skip();
+                    read('>');
+                    break;
+                }
+
+                if (c == '>' && !xmldecl) {
+                    read();
+                    break;
+                }
+            }
+
+            if (c == -1) {
+                error(UNEXPECTED_EOF);
+                //type = COMMENT;
+                return;
+            }
+
+            String attrName = readName();
+
+            if (attrName.length() == 0) {
+                error("attr name expected");
+               //type = COMMENT;
+                break;
+            }
+
+            int i = (attributeCount++) << 2;
+
+            attributes = ensureCapacity(attributes, i + 4);
+
+            attributes[i++] = "";
+            attributes[i++] = null;
+            attributes[i++] = attrName;
+
+            skip();
+
+            if (peek(0) != '=') {
+                error("Attr.value missing f. "+attrName);
+                attributes[i] = "1";
+            }
+            else {
+                read('=');
+                skip();
+                int delimiter = peek(0);
+
+                if (delimiter != '\'' && delimiter != '"') {
+                    error("attr value delimiter missing!");
+                    delimiter = ' ';
+                }
+                else 
+                    read();
+                
+                int p = txtPos;
+                pushText(delimiter, true);
+
+                attributes[i] = get(p);
+                txtPos = p;
+
+                if (delimiter != ' ')
+                    read(); // skip endquote
+            }
+        }
+
+        int sp = depth++ << 2;
+
+        elementStack = ensureCapacity(elementStack, sp + 4);
+        elementStack[sp + 3] = name;
+
+        if (depth >= nspCounts.length) {
+            int[] bigger = new int[depth + 4];
+            System.arraycopy(nspCounts, 0, bigger, 0, nspCounts.length);
+            nspCounts = bigger;
+        }
+
+        nspCounts[depth] = nspCounts[depth - 1];
+
+        /*
+                if(!relaxed){
+                for (int i = attributeCount - 1; i > 0; i--) {
+                    for (int j = 0; j < i; j++) {
+                        if (getAttributeName(i).equals(getAttributeName(j)))
+                            exception("Duplicate Attribute: " + getAttributeName(i));
+                    }
+                }
+                }
+        */
+        if (processNsp)
+            adjustNsp();
+        else
+            namespace = "";
+
+        elementStack[sp] = namespace;
+        elementStack[sp + 1] = prefix;
+        elementStack[sp + 2] = name;
+    }
+
+    /** 
+     * result: isWhitespace; if the setName parameter is set,
+     * the name of the entity is stored in "name" */
+
+    private final void pushEntity()
+        throws IOException, XmlPullParserException {
+
+        push(read()); // &
+        
+        
+        int pos = txtPos;
+
+        while (true) {
+            int c = read();
+            if (c == ';')
+                break;
+            if (c < 128
+                && (c < '0' || c > '9')
+                && (c < 'a' || c > 'z')
+                && (c < 'A' || c > 'Z')
+                && c != '_'
+                && c != '-'
+                && c != '#') {
+                if(!relaxed){
+                    error("unterminated entity ref");
+                }
+                //; ends with:"+(char)c);           
+                if (c != -1)
+                    push(c);
+                return;
+            }
+
+            push(c);
+        }
+
+        String code = get(pos);
+        txtPos = pos - 1;
+        if (token && type == ENTITY_REF){
+            name = code;
+        }
+
+        if (code.charAt(0) == '#') {
+            int c =
+                (code.charAt(1) == 'x'
+                    ? Integer.parseInt(code.substring(2), 16)
+                    : Integer.parseInt(code.substring(1)));
+            push(c);
+            return;
+        }
+
+        String result = (String) entityMap.get(code);
+
+        unresolved = result == null;
+
+        if (unresolved) {
+            if (!token)
+                error("unresolved: &" + code + ";");
+        }
+        else {
+            for (int i = 0; i < result.length(); i++)
+                push(result.charAt(i));
+        }
+    }
+
+    /** types:
+    '<': parse to any token (for nextToken ())
+    '"': parse to quote
+    ' ': parse to whitespace or '>'
+    */
+
+    private final void pushText(int delimiter, boolean resolveEntities)
+        throws IOException, XmlPullParserException {
+
+        int next = peek(0);
+        int cbrCount = 0;
+
+        while (next != -1 && next != delimiter) { // covers eof, '<', '"'
+
+            if (delimiter == ' ')
+                if (next <= ' ' || next == '>')
+                    break;
+
+            if (next == '&') {
+                if (!resolveEntities)
+                    break;
+
+                pushEntity();
+            }
+            else if (next == '\n' && type == START_TAG) {
+                read();
+                push(' ');
+            }
+            else
+                push(read());
+
+            if (next == '>' && cbrCount >= 2 && delimiter != ']')
+                error("Illegal: ]]>");
+
+            if (next == ']')
+                cbrCount++;
+            else
+                cbrCount = 0;
+
+            next = peek(0);
+        }
+    }
+
+    private final void read(char c)
+        throws IOException, XmlPullParserException {
+        int a = read();
+        if (a != c)
+            error("expected: '" + c + "' actual: '" + ((char) a) + "'");
+    }
+
+    private final int read() throws IOException {
+        int result;
+
+        if (peekCount == 0)
+            result = peek(0);
+        else {
+            result = peek[0];
+            peek[0] = peek[1];
+        }
+        //        else {
+        //            result = peek[0]; 
+        //            System.arraycopy (peek, 1, peek, 0, peekCount-1);
+        //        }
+        peekCount--;
+
+        column++;
+
+        if (result == '\n') {
+
+            line++;
+            column = 1;
+        }
+
+        return result;
+    }
+
+    /** Does never read more than needed */
+
+    private final int peek(int pos) throws IOException {
+
+        while (pos >= peekCount) {
+
+            int nw;
+
+            if (srcBuf.length <= 1)
+                nw = reader.read();
+            else if (srcPos < srcCount)
+                nw = srcBuf[srcPos++];
+            else {
+                srcCount = reader.read(srcBuf, 0, srcBuf.length);
+                if (srcCount <= 0)
+                    nw = -1;
+                else
+                    nw = srcBuf[0];
+
+                srcPos = 1;
+            }
+
+            if (nw == '\r') {
+                wasCR = true;
+                peek[peekCount++] = '\n';
+            }
+            else {
+                if (nw == '\n') {
+                    if (!wasCR)
+                        peek[peekCount++] = '\n';
+                }
+                else
+                    peek[peekCount++] = nw;
+
+                wasCR = false;
+            }
+        }
+
+        return peek[pos];
+    }
+
+    private final String readName()
+        throws IOException, XmlPullParserException {
+
+        int pos = txtPos;
+        int c = peek(0);
+        if ((c < 'a' || c > 'z')
+            && (c < 'A' || c > 'Z')
+            && c != '_'
+            && c != ':'
+            && c < 0x0c0
+            && !relaxed)
+            error("name expected");
+
+        do {
+            push(read());
+            c = peek(0);
+        }
+        while ((c >= 'a' && c <= 'z')
+            || (c >= 'A' && c <= 'Z')
+            || (c >= '0' && c <= '9')
+            || c == '_'
+            || c == '-'
+            || c == ':'
+            || c == '.'
+            || c >= 0x0b7);
+
+        String result = get(pos);
+        txtPos = pos;
+        return result;
+    }
+
+    private final void skip() throws IOException {
+
+        while (true) {
+            int c = peek(0);
+            if (c > ' ' || c == -1)
+                break;
+            read();
+        }
+    }
+
+    //  public part starts here...
+
+    public void setInput(Reader reader) throws XmlPullParserException {
+        this.reader = reader;
+
+        line = 1;
+        column = 0;
+        type = START_DOCUMENT;
+        name = null;
+        namespace = null;
+        degenerated = false;
+        attributeCount = -1;
+        encoding = null;
+        version = null;
+        standalone = null;
+
+        if (reader == null)
+            return;
+
+        srcPos = 0;
+        srcCount = 0;
+        peekCount = 0;
+        depth = 0;
+
+        entityMap = new Hashtable();
+        entityMap.put("amp", "&");
+        entityMap.put("apos", "'");
+        entityMap.put("gt", ">");
+        entityMap.put("lt", "<");
+        entityMap.put("quot", "\"");
+    }
+
+    public void setInput(InputStream is, String _enc)
+        throws XmlPullParserException {
+
+        srcPos = 0;
+        srcCount = 0;
+        String enc = _enc;
+
+        if (is == null)
+            throw new IllegalArgumentException();
+
+        try {
+
+            if (enc == null) {
+                // read four bytes 
+
+                int chk = 0;
+
+                while (srcCount < 4) {
+                    int i = is.read();
+                    if (i == -1)
+                        break;
+                    chk = (chk << 8) | i;
+                    srcBuf[srcCount++] = (char) i;
+                }
+
+                if (srcCount == 4) {
+                    switch (chk) {
+                        case 0x00000FEFF :
+                            enc = "UTF-32BE";
+                            srcCount = 0;
+                            break;
+
+                        case 0x0FFFE0000 :
+                            enc = "UTF-32LE";
+                            srcCount = 0;
+                            break;
+
+                        case 0x03c :
+                            enc = "UTF-32BE";
+                            srcBuf[0] = '<';
+                            srcCount = 1;
+                            break;
+
+                        case 0x03c000000 :
+                            enc = "UTF-32LE";
+                            srcBuf[0] = '<';
+                            srcCount = 1;
+                            break;
+
+                        case 0x0003c003f :
+                            enc = "UTF-16BE";
+                            srcBuf[0] = '<';
+                            srcBuf[1] = '?';
+                            srcCount = 2;
+                            break;
+
+                        case 0x03c003f00 :
+                            enc = "UTF-16LE";
+                            srcBuf[0] = '<';
+                            srcBuf[1] = '?';
+                            srcCount = 2;
+                            break;
+
+                        case 0x03c3f786d :
+                            while (true) {
+                                int i = is.read();
+                                if (i == -1)
+                                    break;
+                                srcBuf[srcCount++] = (char) i;
+                                if (i == '>') {
+                                    String s = new String(srcBuf, 0, srcCount);
+                                    int i0 = s.indexOf("encoding");
+                                    if (i0 != -1) {
+                                        while (s.charAt(i0) != '"'
+                                            && s.charAt(i0) != '\'')
+                                            i0++;
+                                        char deli = s.charAt(i0++);
+                                        int i1 = s.indexOf(deli, i0);
+                                        enc = s.substring(i0, i1);
+                                    }
+                                    break;
+                                }
+                            }
+
+                        default :
+                            if ((chk & 0x0ffff0000) == 0x0FEFF0000) {
+                                enc = "UTF-16BE";
+                                srcBuf[0] =
+                                    (char) ((srcBuf[2] << 8) | srcBuf[3]);
+                                srcCount = 1;
+                            }
+                            else if ((chk & 0x0ffff0000) == 0x0fffe0000) {
+                                enc = "UTF-16LE";
+                                srcBuf[0] =
+                                    (char) ((srcBuf[3] << 8) | srcBuf[2]);
+                                srcCount = 1;
+                            }
+                            else if ((chk & 0x0ffffff00) == 0x0EFBBBF00) {
+                                enc = "UTF-8";
+                                srcBuf[0] = srcBuf[3];
+                                srcCount = 1;
+                            }
+                    }
+                }
+            }
+
+            if (enc == null)
+                enc = "UTF-8";
+
+            int sc = srcCount;
+            setInput(new InputStreamReader(is, enc));
+            encoding = _enc;
+            srcCount = sc;
+        }
+        catch (Exception e) {
+            throw new XmlPullParserException(
+                "Invalid stream or encoding: " + e.toString(),
+                this,
+                e);
+        }
+    }
+
+    public boolean getFeature(String feature) {
+        if (XmlPullParser.FEATURE_PROCESS_NAMESPACES.equals(feature))
+            return processNsp;
+        else if (isProp(feature, false, "relaxed"))
+            return relaxed;
+        else
+            return false;
+    }
+
+    public String getInputEncoding() {
+        return encoding;
+    }
+
+    public void defineEntityReplacementText(String entity, String value)
+        throws XmlPullParserException {
+        if (entityMap == null)
+            throw new RuntimeException("entity replacement text must be defined after setInput!");
+        entityMap.put(entity, value);
+    }
+
+    public Object getProperty(String property) {
+        if (isProp(property, true, "xmldecl-version"))
+            return version;
+        if (isProp(property, true, "xmldecl-standalone"))
+            return standalone;
+        if (isProp(property, true, "location"))            
+            return location != null ? location : reader.toString();
+        return null;
+    }
+
+    public int getNamespaceCount(int depth) {
+        if (depth > this.depth)
+            throw new IndexOutOfBoundsException();
+        return nspCounts[depth];
+    }
+
+    public String getNamespacePrefix(int pos) {
+        return nspStack[pos << 1];
+    }
+
+    public String getNamespaceUri(int pos) {
+        return nspStack[(pos << 1) + 1];
+    }
+
+    public String getNamespace(String prefix) {
+
+        if ("xml".equals(prefix))
+            return "http://www.w3.org/XML/1998/namespace";
+        if ("xmlns".equals(prefix))
+            return "http://www.w3.org/2000/xmlns/";
+
+        for (int i = (getNamespaceCount(depth) << 1) - 2; i >= 0; i -= 2) {
+            if (prefix == null) {
+                if (nspStack[i] == null)
+                    return nspStack[i + 1];
+            }
+            else if (prefix.equals(nspStack[i]))
+                return nspStack[i + 1];
+        }
+        return null;
+    }
+
+    public int getDepth() {
+        return depth;
+    }
+
+    public String getPositionDescription() {
+
+        StringBuffer buf =
+            new StringBuffer(type < TYPES.length ? TYPES[type] : "unknown");
+        buf.append(' ');
+
+        if (type == START_TAG || type == END_TAG) {
+            if (degenerated)
+                buf.append("(empty) ");
+            buf.append('<');
+            if (type == END_TAG)
+                buf.append('/');
+
+            if (prefix != null)
+                buf.append("{" + namespace + "}" + prefix + ":");
+            buf.append(name);
+
+            int cnt = attributeCount << 2;
+            for (int i = 0; i < cnt; i += 4) {
+                buf.append(' ');
+                if (attributes[i + 1] != null)
+                    buf.append(
+                        "{" + attributes[i] + "}" + attributes[i + 1] + ":");
+                buf.append(attributes[i + 2] + "='" + attributes[i + 3] + "'");
+            }
+
+            buf.append('>');
+        }
+        else if (type == IGNORABLE_WHITESPACE);
+        else if (type != TEXT)
+            buf.append(getText());
+        else if (isWhitespace)
+            buf.append("(whitespace)");
+        else {
+            String text = getText();
+            if (text.length() > 16)
+                text = text.substring(0, 16) + "...";
+            buf.append(text);
+        }
+
+        buf.append("@"+line + ":" + column);
+        if(location != null){
+            buf.append(" in ");
+            buf.append(location);
+        }
+        else if(reader != null){
+            buf.append(" in ");
+            buf.append(reader.toString());
+        }
+        return buf.toString();
+    }
+
+    public int getLineNumber() {
+        return line;
+    }
+
+    public int getColumnNumber() {
+        return column;
+    }
+
+    public boolean isWhitespace() throws XmlPullParserException {
+        if (type != TEXT && type != IGNORABLE_WHITESPACE && type != CDSECT)
+            exception(ILLEGAL_TYPE);
+        return isWhitespace;
+    }
+
+    public String getText() {
+        return type < TEXT
+            || (type == ENTITY_REF && unresolved) ? null : get(0);
+    }
+
+    public char[] getTextCharacters(int[] poslen) {
+        if (type >= TEXT) {
+            if (type == ENTITY_REF) {
+                poslen[0] = 0;
+                poslen[1] = name.length();
+                return name.toCharArray();
+            }
+            poslen[0] = 0;
+            poslen[1] = txtPos;
+            return txtBuf;
+        }
+
+        poslen[0] = -1;
+        poslen[1] = -1;
+        return null;
+    }
+
+    public String getNamespace() {
+        return namespace;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getPrefix() {
+        return prefix;
+    }
+
+    public boolean isEmptyElementTag() throws XmlPullParserException {
+        if (type != START_TAG)
+            exception(ILLEGAL_TYPE);
+        return degenerated;
+    }
+
+    public int getAttributeCount() {
+        return attributeCount;
+    }
+
+    public String getAttributeType(int index) {
+        return "CDATA";
+    }
+
+    public boolean isAttributeDefault(int index) {
+        return false;
+    }
+
+    public String getAttributeNamespace(int index) {
+        if (index >= attributeCount)
+            throw new IndexOutOfBoundsException();
+        return attributes[index << 2];
+    }
+
+    public String getAttributeName(int index) {
+        if (index >= attributeCount)
+            throw new IndexOutOfBoundsException();
+        return attributes[(index << 2) + 2];
+    }
+
+    public String getAttributePrefix(int index) {
+        if (index >= attributeCount)
+            throw new IndexOutOfBoundsException();
+        return attributes[(index << 2) + 1];
+    }
+
+    public String getAttributeValue(int index) {
+        if (index >= attributeCount)
+            throw new IndexOutOfBoundsException();
+        return attributes[(index << 2) + 3];
+    }
+
+    public String getAttributeValue(String namespace, String name) {
+
+        for (int i = (attributeCount << 2) - 4; i >= 0; i -= 4) {
+            if (attributes[i + 2].equals(name)
+                && (namespace == null || attributes[i].equals(namespace)))
+                return attributes[i + 3];
+        }
+
+        return null;
+    }
+
+    public int getEventType() throws XmlPullParserException {
+        return type;
+    }
+
+    public int next() throws XmlPullParserException, IOException {
+
+        txtPos = 0;
+        isWhitespace = true;
+        int minType = 9999;
+        token = false;
+
+        do {
+            nextImpl();
+            if (type < minType)
+                minType = type;
+            //        if (curr <= TEXT) type = curr; 
+        }
+        while (minType > ENTITY_REF // ignorable
+            || (minType >= TEXT && peekType() >= TEXT));
+
+        type = minType;
+        if (type > TEXT)
+            type = TEXT;
+
+        return type;
+    }
+
+    public int nextToken() throws XmlPullParserException, IOException {
+
+        isWhitespace = true;
+        txtPos = 0;
+
+        token = true;
+        nextImpl();
+        return type;
+    }
+
+    //
+    // utility methods to make XML parsing easier ...
+
+    public int nextTag() throws XmlPullParserException, IOException {
+
+        next();
+        if (type == TEXT && isWhitespace)
+            next();
+
+        if (type != END_TAG && type != START_TAG)
+            exception("unexpected type");
+
+        return type;
+    }
+
+    public void require(int type, String namespace, String name)
+        throws XmlPullParserException, IOException {
+
+        if (type != this.type
+            || (namespace != null && !namespace.equals(getNamespace()))
+            || (name != null && !name.equals(getName())))
+            exception(
+                "expected: " + TYPES[type] + " {" + namespace + "}" + name);
+    }
+
+    public String nextText() throws XmlPullParserException, IOException {
+        if (type != START_TAG)
+            exception("precondition: START_TAG");
+
+        next();
+
+        String result;
+
+        if (type == TEXT) {
+            result = getText();
+            next();
+        }
+        else
+            result = "";
+
+        if (type != END_TAG)
+            exception("END_TAG expected");
+
+        return result;
+    }
+
+    public void setFeature(String feature, boolean value)
+        throws XmlPullParserException {
+        if (XmlPullParser.FEATURE_PROCESS_NAMESPACES.equals(feature))
+            processNsp = value;
+        else if (isProp(feature, false, "relaxed"))
+            relaxed = value;
+        else
+            exception("unsupported feature: " + feature);
+    }
+
+    public void setProperty(String property, Object value)
+        throws XmlPullParserException {
+        if(isProp(property, true, "location"))
+            location = value;
+        else
+            throw new XmlPullParserException("unsupported property: " + property);
+    }
+
+    /**
+      * Skip sub tree that is currently porser positioned on.
+      * <br>NOTE: parser must be on START_TAG and when funtion returns
+      * parser will be positioned on corresponding END_TAG. 
+      */
+
+    //    Implementation copied from Alek's mail... 
+
+    public void skipSubTree() throws XmlPullParserException, IOException {
+        require(START_TAG, null, null);
+        int level = 1;
+        while (level > 0) {
+            int eventType = next();
+            if (eventType == END_TAG) {
+                --level;
+            }
+            else if (eventType == START_TAG) {
+                ++level;
+            }
+        }
+    }
+}
diff --git a/xml/src/main/java/org/kxml2/io/KXmlSerializer.java b/xml/src/main/java/org/kxml2/io/KXmlSerializer.java
new file mode 100644
index 0000000..d63ed04
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/io/KXmlSerializer.java
@@ -0,0 +1,562 @@
+/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The  above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE. */
+ 
+
+package org.kxml2.io;
+
+import java.io.*;
+import org.xmlpull.v1.*;
+
+public class KXmlSerializer implements XmlSerializer {
+
+    //    static final String UNDEFINED = ":";
+
+    // BEGIN android-added
+    /** size (in characters) for the write buffer */
+    private static final int WRITE_BUFFER_SIZE = 500;
+    // END android-added   
+
+    // BEGIN android-changed
+    // (Guarantee that the writer is always buffered.)
+    private BufferedWriter writer;
+    // END android-changed
+
+    private boolean pending;
+    private int auto;
+    private int depth;
+
+    private String[] elementStack = new String[12];
+    //nsp/prefix/name
+    private int[] nspCounts = new int[4];
+    private String[] nspStack = new String[8];
+    //prefix/nsp; both empty are ""
+    private boolean[] indent = new boolean[4];
+    private boolean unicode;
+    private String encoding;
+
+    private final void check(boolean close) throws IOException {
+        if (!pending)
+            return;
+
+        depth++;
+        pending = false;
+
+        if (indent.length <= depth) {
+            boolean[] hlp = new boolean[depth + 4];
+            System.arraycopy(indent, 0, hlp, 0, depth);
+            indent = hlp;
+        }
+        indent[depth] = indent[depth - 1];
+
+        for (int i = nspCounts[depth - 1];
+            i < nspCounts[depth];
+            i++) {
+            writer.write(' ');
+            writer.write("xmlns");
+            if (!"".equals(nspStack[i * 2])) {
+                writer.write(':');
+                writer.write(nspStack[i * 2]);
+            }
+            else if ("".equals(getNamespace()) && !"".equals(nspStack[i * 2 + 1]))
+                throw new IllegalStateException("Cannot set default namespace for elements in no namespace");
+            writer.write("=\"");
+            writeEscaped(nspStack[i * 2 + 1], '"');
+            writer.write('"');
+        }
+
+        if (nspCounts.length <= depth + 1) {
+            int[] hlp = new int[depth + 8];
+            System.arraycopy(nspCounts, 0, hlp, 0, depth + 1);
+            nspCounts = hlp;
+        }
+
+        nspCounts[depth + 1] = nspCounts[depth];
+        //   nspCounts[depth + 2] = nspCounts[depth];
+
+        writer.write(close ? " />" : ">");
+    }
+
+    private final void writeEscaped(String s, int quot)
+        throws IOException {
+
+        for (int i = 0; i < s.length(); i++) {
+            char c = s.charAt(i);
+            switch (c) {
+                case '\n':
+                case '\r':
+                case '\t':
+                    if(quot == -1) 
+                        writer.write(c);
+                    else 
+                        writer.write("&#"+((int) c)+';');
+                    break;
+                case '&' :
+                    writer.write("&amp;");
+                    break;
+                case '>' :
+                    writer.write("&gt;");
+                    break;
+                case '<' :
+                    writer.write("&lt;");
+                    break;
+                case '"' :
+                case '\'' :
+                    if (c == quot) {
+                        writer.write(
+                            c == '"' ? "&quot;" : "&apos;");
+                        break;
+                    }
+                default :
+                    //if(c < ' ')
+                    //    throw new IllegalArgumentException("Illegal control code:"+((int) c));
+
+                    if (c >= ' ' && c !='@' && (c < 127 || unicode))
+                        writer.write(c);
+                    else
+                        writer.write("&#" + ((int) c) + ";");
+
+            }
+        }
+    }
+
+    /*
+        private final void writeIndent() throws IOException {
+            writer.write("\r\n");
+            for (int i = 0; i < depth; i++)
+                writer.write(' ');
+        }*/
+
+    public void docdecl(String dd) throws IOException {
+        writer.write("<!DOCTYPE");
+        writer.write(dd);
+        writer.write(">");
+    }
+
+    public void endDocument() throws IOException {
+        while (depth > 0) {
+            endTag(
+                elementStack[depth * 3 - 3],
+                elementStack[depth * 3 - 1]);
+        }
+        flush();
+    }
+
+    public void entityRef(String name) throws IOException {
+        check(false);
+        writer.write('&');
+        writer.write(name);
+        writer.write(';');
+    }
+
+    public boolean getFeature(String name) {
+        //return false;
+        return (
+            "http://xmlpull.org/v1/doc/features.html#indent-output"
+                .equals(
+                name))
+            ? indent[depth]
+            : false;
+    }
+
+    public String getPrefix(String namespace, boolean create) {
+        try {
+            return getPrefix(namespace, false, create);
+        }
+        catch (IOException e) {
+            throw new RuntimeException(e.toString());
+        }
+    }
+
+    private final String getPrefix(
+        String namespace,
+        boolean includeDefault,
+        boolean create)
+        throws IOException {
+
+        for (int i = nspCounts[depth + 1] * 2 - 2;
+            i >= 0;
+            i -= 2) {
+            if (nspStack[i + 1].equals(namespace)
+                && (includeDefault || !nspStack[i].equals(""))) {
+                String cand = nspStack[i];
+                for (int j = i + 2;
+                    j < nspCounts[depth + 1] * 2;
+                    j++) {
+                    if (nspStack[j].equals(cand)) {
+                        cand = null;
+                        break;
+                    }
+                }
+                if (cand != null)
+                    return cand;
+            }
+        }
+
+        if (!create)
+            return null;
+
+        String prefix;
+
+        if ("".equals(namespace))
+            prefix = "";
+        else {
+            do {
+                prefix = "n" + (auto++);
+                for (int i = nspCounts[depth + 1] * 2 - 2;
+                    i >= 0;
+                    i -= 2) {
+                    if (prefix.equals(nspStack[i])) {
+                        prefix = null;
+                        break;
+                    }
+                }
+            }
+            while (prefix == null);
+        }
+
+        boolean p = pending;
+        pending = false;
+        setPrefix(prefix, namespace);
+        pending = p;
+        return prefix;
+    }
+
+    public Object getProperty(String name) {
+        throw new RuntimeException("Unsupported property");
+    }
+
+    public void ignorableWhitespace(String s)
+        throws IOException {
+        text(s);
+    }
+
+    public void setFeature(String name, boolean value) {
+        if ("http://xmlpull.org/v1/doc/features.html#indent-output"
+            .equals(name)) {
+            indent[depth] = value;
+        }
+        else
+            throw new RuntimeException("Unsupported Feature");
+    }
+
+    public void setProperty(String name, Object value) {
+        throw new RuntimeException(
+            "Unsupported Property:" + value);
+    }
+
+    public void setPrefix(String prefix, String namespace)
+        throws IOException {
+
+        check(false);
+        if (prefix == null)
+            prefix = "";
+        if (namespace == null)
+            namespace = "";
+
+        String defined = getPrefix(namespace, true, false);
+
+        // boil out if already defined
+
+        if (prefix.equals(defined))
+            return;
+
+        int pos = (nspCounts[depth + 1]++) << 1;
+
+        if (nspStack.length < pos + 1) {
+            String[] hlp = new String[nspStack.length + 16];
+            System.arraycopy(nspStack, 0, hlp, 0, pos);
+            nspStack = hlp;
+        }
+
+        nspStack[pos++] = prefix;
+        nspStack[pos] = namespace;
+    }
+
+    public void setOutput(Writer writer) {
+        // BEGIN android-changed
+        // Guarantee that the writer is always buffered.
+        if (writer instanceof BufferedWriter) {
+            this.writer = (BufferedWriter) writer;
+        } else {
+            this.writer = new BufferedWriter(writer, WRITE_BUFFER_SIZE);
+        }
+        // END android-changed
+
+        // elementStack = new String[12]; //nsp/prefix/name
+        //nspCounts = new int[4];
+        //nspStack = new String[8]; //prefix/nsp
+        //indent = new boolean[4];
+
+        nspCounts[0] = 2;
+        nspCounts[1] = 2;
+        nspStack[0] = "";
+        nspStack[1] = "";
+        nspStack[2] = "xml";
+        nspStack[3] = "http://www.w3.org/XML/1998/namespace";
+        pending = false;
+        auto = 0;
+        depth = 0;
+
+        unicode = false;
+    }
+
+    public void setOutput(OutputStream os, String encoding)
+        throws IOException {
+        if (os == null)
+            throw new IllegalArgumentException();
+        setOutput(
+            encoding == null
+                ? new OutputStreamWriter(os)
+                : new OutputStreamWriter(os, encoding));
+        this.encoding = encoding;
+        if (encoding != null
+            && encoding.toLowerCase().startsWith("utf"))
+            unicode = true;
+    }
+
+    public void startDocument(
+        String encoding,
+        Boolean standalone)
+        throws IOException {
+        writer.write("<?xml version='1.0' ");
+
+        if (encoding != null) {
+            this.encoding = encoding;
+            if (encoding.toLowerCase().startsWith("utf"))
+                unicode = true;
+        }
+
+        if (this.encoding != null) {
+            writer.write("encoding='");
+            writer.write(this.encoding);
+            writer.write("' ");
+        }
+
+        if (standalone != null) {
+            writer.write("standalone='");
+            writer.write(
+                standalone.booleanValue() ? "yes" : "no");
+            writer.write("' ");
+        }
+        writer.write("?>");
+    }
+
+    public XmlSerializer startTag(String namespace, String name)
+        throws IOException {
+        check(false);
+
+        //        if (namespace == null)
+        //            namespace = "";
+
+        if (indent[depth]) {
+            writer.write("\r\n");
+            for (int i = 0; i < depth; i++)
+                writer.write("  ");
+        }
+
+        int esp = depth * 3;
+
+        if (elementStack.length < esp + 3) {
+            String[] hlp = new String[elementStack.length + 12];
+            System.arraycopy(elementStack, 0, hlp, 0, esp);
+            elementStack = hlp;
+        }
+
+        String prefix =
+            namespace == null
+                ? ""
+                : getPrefix(namespace, true, true);
+
+        if ("".equals(namespace)) {
+            for (int i = nspCounts[depth];
+                i < nspCounts[depth + 1];
+                i++) {
+                if ("".equals(nspStack[i * 2]) && !"".equals(nspStack[i * 2 + 1])) {
+                    throw new IllegalStateException("Cannot set default namespace for elements in no namespace");
+                }
+            }
+        }
+
+        elementStack[esp++] = namespace;
+        elementStack[esp++] = prefix;
+        elementStack[esp] = name;
+
+        writer.write('<');
+        if (!"".equals(prefix)) {
+            writer.write(prefix);
+            writer.write(':');
+        }
+
+        writer.write(name);
+
+        pending = true;
+
+        return this;
+    }
+
+    public XmlSerializer attribute(
+        String namespace,
+        String name,
+        String value)
+        throws IOException {
+        if (!pending)
+            throw new IllegalStateException("illegal position for attribute");
+
+        //        int cnt = nspCounts[depth];
+
+        if (namespace == null)
+            namespace = "";
+
+        //        depth--;
+        //        pending = false;
+
+        String prefix =
+            "".equals(namespace)
+                ? ""
+                : getPrefix(namespace, false, true);
+
+        //        pending = true;
+        //        depth++;
+
+        /*        if (cnt != nspCounts[depth]) {
+                    writer.write(' ');
+                    writer.write("xmlns");
+                    if (nspStack[cnt * 2] != null) {
+                        writer.write(':');
+                        writer.write(nspStack[cnt * 2]);
+                    }
+                    writer.write("=\"");
+                    writeEscaped(nspStack[cnt * 2 + 1], '"');
+                    writer.write('"');
+                }
+                */
+
+        writer.write(' ');
+        if (!"".equals(prefix)) {
+            writer.write(prefix);
+            writer.write(':');
+        }
+        writer.write(name);
+        writer.write('=');
+        char q = value.indexOf('"') == -1 ? '"' : '\'';
+        writer.write(q);
+        writeEscaped(value, q);
+        writer.write(q);
+
+        return this;
+    }
+
+    public void flush() throws IOException {
+        check(false);
+        writer.flush();
+    }
+    /*
+        public void close() throws IOException {
+            check();
+            writer.close();
+        }
+    */
+    public XmlSerializer endTag(String namespace, String name)
+        throws IOException {
+
+        if (!pending)
+            depth--;
+        //        if (namespace == null)
+        //          namespace = "";
+
+        if ((namespace == null
+            && elementStack[depth * 3] != null)
+            || (namespace != null
+                && !namespace.equals(elementStack[depth * 3]))
+            || !elementStack[depth * 3 + 2].equals(name))
+            throw new IllegalArgumentException("</{"+namespace+"}"+name+"> does not match start");
+
+        if (pending) {
+            check(true);
+            depth--;
+        }
+        else {
+            if (indent[depth + 1]) {
+                writer.write("\r\n");
+                for (int i = 0; i < depth; i++)
+                    writer.write("  ");
+            }
+
+            writer.write("</");
+            String prefix = elementStack[depth * 3 + 1];
+            if (!"".equals(prefix)) {
+                writer.write(prefix);
+                writer.write(':');
+            }
+            writer.write(name);
+            writer.write('>');
+        }
+
+        nspCounts[depth + 1] = nspCounts[depth];
+        return this;
+    }
+
+    public String getNamespace() {
+        return getDepth() == 0 ? null : elementStack[getDepth() * 3 - 3];
+    }
+
+    public String getName() {
+        return getDepth() == 0 ? null : elementStack[getDepth() * 3 - 1];
+    }
+
+    public int getDepth() {
+        return pending ? depth + 1 : depth;
+    }
+
+    public XmlSerializer text(String text) throws IOException {
+        check(false);
+        indent[depth] = false;
+        writeEscaped(text, -1);
+        return this;
+    }
+
+    public XmlSerializer text(char[] text, int start, int len)
+        throws IOException {
+        text(new String(text, start, len));
+        return this;
+    }
+
+    public void cdsect(String data) throws IOException {
+        check(false);
+        writer.write("<![CDATA[");
+        writer.write(data);
+        writer.write("]]>");
+    }
+
+    public void comment(String comment) throws IOException {
+        check(false);
+        writer.write("<!--");
+        writer.write(comment);
+        writer.write("-->");
+    }
+
+    public void processingInstruction(String pi)
+        throws IOException {
+        check(false);
+        writer.write("<?");
+        writer.write(pi);
+        writer.write("?>");
+    }
+}
diff --git a/xml/src/main/java/org/kxml2/kdom/Document.java b/xml/src/main/java/org/kxml2/kdom/Document.java
new file mode 100644
index 0000000..859334c
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/kdom/Document.java
@@ -0,0 +1,129 @@
+/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The  above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE. */
+ 
+
+package org.kxml2.kdom;
+
+import java.io.*;
+
+import org.xmlpull.v1.*;
+/** The document consists of some legacy events and a single root
+    element. This class basically adds some consistency checks to
+    Node. */
+
+public class Document extends Node {
+
+    protected int rootIndex = -1;
+    String encoding;
+    Boolean standalone;
+
+    /** returns "#document" */
+
+    public String getEncoding () {
+        return encoding;
+    }
+    
+    public void setEncoding(String enc) {
+        this.encoding = enc;
+    }
+    
+    public void setStandalone (Boolean standalone) {
+        this.standalone = standalone;
+    }
+    
+    public Boolean getStandalone() {
+        return standalone;
+    }
+
+
+    public String getName() {
+        return "#document";
+    }
+
+    /** Adds a child at the given index position. Throws
+    an exception when a second root element is added */
+
+    public void addChild(int index, int type, Object child) {
+        if (type == ELEMENT) {
+         //   if (rootIndex != -1)
+           //     throw new RuntimeException("Only one document root element allowed");
+
+            rootIndex = index;
+        }
+        else if (rootIndex >= index)
+            rootIndex++;
+
+        super.addChild(index, type, child);
+    }
+
+    /** reads the document and checks if the last event
+    is END_DOCUMENT. If not, an exception is thrown.
+    The end event is consumed. For parsing partial
+        XML structures, consider using Node.parse (). */
+
+    public void parse(XmlPullParser parser)
+        throws IOException, XmlPullParserException {
+
+        parser.require(XmlPullParser.START_DOCUMENT, null, null);
+        parser.nextToken ();            
+
+        encoding = parser.getInputEncoding();
+        standalone = (Boolean)parser.getProperty ("http://xmlpull.org/v1/doc/properties.html#xmldecl-standalone");
+        
+        super.parse(parser);
+
+        if (parser.getEventType() != XmlPullParser.END_DOCUMENT)
+            throw new RuntimeException("Document end expected!");
+
+    }
+
+    public void removeChild(int index) {
+        if (index == rootIndex)
+            rootIndex = -1;
+        else if (index < rootIndex)
+            rootIndex--;
+
+        super.removeChild(index);
+    }
+
+    /** returns the root element of this document. */
+
+    public Element getRootElement() {
+        if (rootIndex == -1)
+            throw new RuntimeException("Document has no root element!");
+
+        return (Element) getChild(rootIndex);
+    }
+    
+    
+    /** Writes this node to the given XmlWriter. For node and document,
+        this method is identical to writeChildren, except that the
+        stream is flushed automatically. */
+
+    public void write(XmlSerializer writer)
+        throws IOException {
+        
+        writer.startDocument(encoding, standalone);
+        writeChildren(writer);
+        writer.endDocument();
+    }
+    
+    
+}
\ No newline at end of file
diff --git a/xml/src/main/java/org/kxml2/kdom/Element.java b/xml/src/main/java/org/kxml2/kdom/Element.java
new file mode 100644
index 0000000..6a5777b
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/kdom/Element.java
@@ -0,0 +1,335 @@
+/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The  above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE. */
+
+package org.kxml2.kdom;
+
+import java.io.*;
+import java.util.*;
+
+import org.xmlpull.v1.*;
+
+/** 
+ * In order to create an element, please use the createElement method
+ * instead of invoking the constructor directly. The right place to
+ * add user defined initialization code is the init method. */
+
+public class Element extends Node {
+
+    protected String namespace;
+    protected String name;
+    protected Vector attributes;
+    protected Node parent;
+    protected Vector prefixes;
+
+    public Element() {
+    }
+
+    /** 
+     * called when all properties are set, but before children
+     * are parsed. Please do not use setParent for initialization
+     * code any longer. */
+
+    public void init() {
+    }
+
+
+
+
+    /** 
+     * removes all children and attributes */
+
+    public void clear() {
+        attributes = null;
+        children = null;
+    }
+
+    /** 
+     * Forwards creation request to parent if any, otherwise
+     * calls super.createElement. */
+
+    public Element createElement(
+        String namespace,
+        String name) { 
+
+        return (this.parent == null)
+            ? super.createElement(namespace, name)
+            : this.parent.createElement(namespace, name);
+    }
+
+    /** 
+     * Returns the number of attributes of this element. */
+
+    public int getAttributeCount() {
+        return attributes == null ? 0 : attributes.size();
+    }
+
+    public String getAttributeNamespace (int index) {
+        return ((String []) attributes.elementAt (index)) [0];
+    }
+
+/*    public String getAttributePrefix (int index) {
+        return ((String []) attributes.elementAt (index)) [1];
+    }*/
+
+    public String getAttributeName (int index) {
+        return ((String []) attributes.elementAt (index)) [1];
+    }
+    
+
+    public String getAttributeValue (int index) {
+        return ((String []) attributes.elementAt (index)) [2];
+    }
+    
+    
+    public String getAttributeValue (String namespace, String name) {
+        for (int i = 0; i < getAttributeCount (); i++) {
+            if (name.equals (getAttributeName (i)) 
+                && (namespace == null || namespace.equals (getAttributeNamespace(i)))) {
+                return getAttributeValue (i);
+            }
+        }                        
+        return null;            
+    }
+
+    /** 
+     * Returns the root node, determined by ascending to the 
+     * all parents un of the root element. */
+
+    public Node getRoot() {
+
+        Element current = this;
+        
+        while (current.parent != null) {
+            if (!(current.parent instanceof Element)) return current.parent;
+            current = (Element) current.parent;
+        }
+        
+        return current;
+    }
+
+    /** 
+     * returns the (local) name of the element */
+
+    public String getName() {
+        return name;
+    }
+
+    /** 
+     * returns the namespace of the element */
+
+    public String getNamespace() {
+        return namespace;
+    }
+
+
+    /** 
+     * returns the namespace for the given prefix */
+    
+    public String getNamespaceUri (String prefix) {
+        int cnt = getNamespaceCount ();
+        for (int i = 0; i < cnt; i++) {
+            if (prefix == getNamespacePrefix (i) ||
+                (prefix != null && prefix.equals (getNamespacePrefix (i))))
+                return getNamespaceUri (i);    
+        }
+        return parent instanceof Element ? ((Element) parent).getNamespaceUri (prefix) : null;
+    }
+
+
+    /** 
+     * returns the number of declared namespaces, NOT including
+     * parent elements */
+
+    public int getNamespaceCount () {
+        return (prefixes == null ? 0 : prefixes.size ());
+    }
+
+
+    public String getNamespacePrefix (int i) {
+        return ((String []) prefixes.elementAt (i)) [0];
+    }
+
+    public String getNamespaceUri (int i) {
+        return ((String []) prefixes.elementAt (i)) [1];
+    }
+
+
+    /** 
+     * Returns the parent node of this element */
+
+    public Node getParent() {
+        return parent;
+    }
+
+    /* 
+     * Returns the parent element if available, null otherwise 
+
+    public Element getParentElement() {
+        return (parent instanceof Element)
+            ? ((Element) parent)
+            : null;
+    }
+*/
+
+    /** 
+     * Builds the child elements from the given Parser. By overwriting 
+     * parse, an element can take complete control over parsing its 
+     * subtree. */
+
+    public void parse(XmlPullParser parser)
+        throws IOException, XmlPullParserException {
+
+        for (int i = parser.getNamespaceCount (parser.getDepth () - 1);
+            i < parser.getNamespaceCount (parser.getDepth ()); i++) {
+            setPrefix (parser.getNamespacePrefix (i), parser.getNamespaceUri(i));
+        }
+        
+        
+        for (int i = 0; i < parser.getAttributeCount (); i++) 
+            setAttribute (parser.getAttributeNamespace (i),
+//                          parser.getAttributePrefix (i),
+                          parser.getAttributeName (i),
+                          parser.getAttributeValue (i));
+
+
+        //        if (prefixMap == null) throw new RuntimeException ("!!");
+
+        init();
+
+
+        if (parser.isEmptyElementTag()) 
+            parser.nextToken ();
+        else {
+            parser.nextToken ();
+            super.parse(parser);
+
+            if (getChildCount() == 0)
+                addChild(IGNORABLE_WHITESPACE, "");
+        }
+        
+        parser.require(
+            XmlPullParser.END_TAG,
+            getNamespace(),
+            getName());
+            
+        parser.nextToken ();
+    }
+
+
+    /** 
+     * Sets the given attribute; a value of null removes the attribute */
+
+    public void setAttribute (String namespace, String name, String value) {
+        if (attributes == null) 
+            attributes = new Vector ();
+
+        if (namespace == null) 
+            namespace = "";
+        
+        for (int i = attributes.size()-1; i >=0; i--){
+            String[] attribut = (String[]) attributes.elementAt(i);
+            if (attribut[0].equals(namespace) &&
+                attribut[1].equals(name)){
+                    
+                if (value == null) {
+                    attributes.removeElementAt(i);
+                }
+                else {
+                    attribut[2] = value;
+                }
+                return; 
+            }
+        }
+
+        attributes.addElement 
+            (new String [] {namespace, name, value});
+    }
+
+
+    /** 
+     * Sets the given prefix; a namespace value of null removess the 
+     * prefix */
+
+    public void setPrefix (String prefix, String namespace) {
+        if (prefixes == null) prefixes = new Vector ();
+        prefixes.addElement (new String [] {prefix, namespace});        
+    }
+
+
+    /** 
+     * sets the name of the element */
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /** 
+     * sets the namespace of the element. Please note: For no
+     * namespace, please use Xml.NO_NAMESPACE, null is not a legal
+     * value. Currently, null is converted to Xml.NO_NAMESPACE, but
+     * future versions may throw an exception. */
+
+    public void setNamespace(String namespace) {
+        if (namespace == null) 
+            throw new NullPointerException ("Use \"\" for empty namespace");
+        this.namespace = namespace;
+    }
+
+    /** 
+     * Sets the Parent of this element. Automatically called from the
+     * add method.  Please use with care, you can simply
+     * create inconsitencies in the document tree structure using
+     * this method!  */
+
+    protected void setParent(Node parent) {
+        this.parent = parent;
+    }
+
+
+    /** 
+     * Writes this element and all children to the given XmlWriter. */
+
+    public void write(XmlSerializer writer)
+        throws IOException {
+
+        if (prefixes != null) {
+            for (int i = 0; i < prefixes.size(); i++) {
+                writer.setPrefix (getNamespacePrefix (i), getNamespaceUri (i));
+            }
+        }
+
+        writer.startTag(
+            getNamespace(),
+            getName());
+
+        int len = getAttributeCount();
+
+        for (int i = 0; i < len; i++) {
+            writer.attribute(
+                getAttributeNamespace(i),
+                getAttributeName(i),
+                getAttributeValue(i));
+        }
+
+        writeChildren(writer);
+
+        writer.endTag(getNamespace (), getName ());
+    }
+}
diff --git a/xml/src/main/java/org/kxml2/kdom/Node.java b/xml/src/main/java/org/kxml2/kdom/Node.java
new file mode 100644
index 0000000..a3cc78d
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/kdom/Node.java
@@ -0,0 +1,366 @@
+/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The  above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE. */
+
+package org.kxml2.kdom;
+
+import java.util.*;
+import java.io.*;
+import org.xmlpull.v1.*;
+/** A common base class for Document and Element, also used for
+    storing XML fragments. */
+
+public class Node { //implements XmlIO{
+
+    public static final int DOCUMENT = 0;
+    public static final int ELEMENT = 2;
+    public static final int TEXT = 4;
+    public static final int CDSECT = 5;
+    public static final int ENTITY_REF = 6;
+    public static final int IGNORABLE_WHITESPACE = 7;
+    public static final int PROCESSING_INSTRUCTION = 8;
+    public static final int COMMENT = 9;
+    public static final int DOCDECL = 10;
+
+    protected Vector children;
+    protected StringBuffer types;
+
+    /** inserts the given child object of the given type at the
+    given index. */
+
+    public void addChild(int index, int type, Object child) {
+
+        if (child == null)
+            throw new NullPointerException();
+
+        if (children == null) {
+            children = new Vector();
+            types = new StringBuffer();
+        }
+
+        if (type == ELEMENT) {
+            if (!(child instanceof Element))
+                throw new RuntimeException("Element obj expected)");
+
+            ((Element) child).setParent(this);
+        }
+        else if (!(child instanceof String))
+            throw new RuntimeException("String expected");
+
+        children.insertElementAt(child, index);
+        types.insert(index, (char) type);
+    }
+
+    /** convenience method for addChild (getChildCount (), child) */
+
+    public void addChild(int type, Object child) {
+        addChild(getChildCount(), type, child);
+    }
+
+    /** Builds a default element with the given properties. Elements
+    should always be created using this method instead of the
+    constructor in order to enable construction of specialized
+    subclasses by deriving custom Document classes. Please note:
+    For no namespace, please use Xml.NO_NAMESPACE, null is not a
+    legal value. Currently, null is converted to Xml.NO_NAMESPACE,
+    but future versions may throw an exception. */
+
+    public Element createElement(String namespace, String name) {
+
+        Element e = new Element();
+        e.namespace = namespace == null ? "" : namespace;
+        e.name = name;
+        return e;
+    }
+
+    /** Returns the child object at the given index.  For child
+        elements, an Element object is returned. For all other child
+        types, a String is returned. */
+
+    public Object getChild(int index) {
+        return children.elementAt(index);
+    }
+
+    /** Returns the number of child objects */
+
+    public int getChildCount() {
+        return children == null ? 0 : children.size();
+    }
+
+    /** returns the element at the given index. If the node at the
+    given index is a text node, null is returned */
+
+    public Element getElement(int index) {
+        Object child = getChild(index);
+        return (child instanceof Element) ? (Element) child : null;
+    }
+
+    /** Returns the element with the given namespace and name. If the
+        element is not found, or more than one matching elements are
+        found, an exception is thrown. */
+
+    public Element getElement(String namespace, String name) {
+
+        int i = indexOf(namespace, name, 0);
+        int j = indexOf(namespace, name, i + 1);
+
+        if (i == -1 || j != -1)
+            throw new RuntimeException(
+                "Element {"
+                    + namespace
+                    + "}"
+                    + name
+                    + (i == -1 ? " not found in " : " more than once in ")
+                    + this);
+
+        return getElement(i);
+    }
+
+    /* returns "#document-fragment". For elements, the element name is returned 
+    
+    public String getName() {
+        return "#document-fragment";
+    }
+    
+    /** Returns the namespace of the current element. For Node
+        and Document, Xml.NO_NAMESPACE is returned. 
+    
+    public String getNamespace() {
+        return "";
+    }
+    
+    public int getNamespaceCount () {
+        return 0;
+    }
+    
+    /** returns the text content if the element has text-only
+    content. Throws an exception for mixed content
+    
+    public String getText() {
+    
+        StringBuffer buf = new StringBuffer();
+        int len = getChildCount();
+    
+        for (int i = 0; i < len; i++) {
+            if (isText(i))
+                buf.append(getText(i));
+            else if (getType(i) == ELEMENT)
+                throw new RuntimeException("not text-only content!");
+        }
+    
+        return buf.toString();
+    }
+    */
+
+    /** Returns the text node with the given index or null if the node
+        with the given index is not a text node. */
+
+    public String getText(int index) {
+        return (isText(index)) ? (String) getChild(index) : null;
+    }
+
+    /** Returns the type of the child at the given index. Possible 
+    types are ELEMENT, TEXT, COMMENT, and PROCESSING_INSTRUCTION */
+
+    public int getType(int index) {
+        return types.charAt(index);
+    }
+
+    /** Convenience method for indexOf (getNamespace (), name,
+        startIndex). 
+    
+    public int indexOf(String name, int startIndex) {
+        return indexOf(getNamespace(), name, startIndex);
+    }
+    */
+
+    /** Performs search for an element with the given namespace and
+    name, starting at the given start index. A null namespace
+    matches any namespace, please use Xml.NO_NAMESPACE for no
+    namespace).  returns -1 if no matching element was found. */
+
+    public int indexOf(String namespace, String name, int startIndex) {
+
+        int len = getChildCount();
+
+        for (int i = startIndex; i < len; i++) {
+
+            Element child = getElement(i);
+
+            if (child != null
+                && name.equals(child.getName())
+                && (namespace == null || namespace.equals(child.getNamespace())))
+                return i;
+        }
+        return -1;
+    }
+
+    public boolean isText(int i) {
+        int t = getType(i);
+        return t == TEXT || t == IGNORABLE_WHITESPACE || t == CDSECT;
+    }
+
+    /** Recursively builds the child elements from the given parser
+    until an end tag or end document is found. 
+        The end tag is not consumed. */
+
+    public void parse(XmlPullParser parser)
+        throws IOException, XmlPullParserException {
+
+        boolean leave = false;
+
+        do {
+            int type = parser.getEventType();
+            
+   //         System.out.println(parser.getPositionDescription());
+            
+            switch (type) {
+
+                case XmlPullParser.START_TAG :
+                    {
+                        Element child =
+                            createElement(
+                                parser.getNamespace(),
+                                parser.getName());
+                        //    child.setAttributes (event.getAttributes ());
+                        addChild(ELEMENT, child);
+
+                        // order is important here since 
+                        // setparent may perform some init code!
+
+                        child.parse(parser);
+                        break;
+                    }
+
+                case XmlPullParser.END_DOCUMENT :
+                case XmlPullParser.END_TAG :
+                    leave = true;
+                    break;
+
+                default :
+                    if (parser.getText() != null)
+                        addChild(
+                            type == XmlPullParser.ENTITY_REF ? TEXT : type,
+                            parser.getText());
+                    else if (
+                        type == XmlPullParser.ENTITY_REF
+                            && parser.getName() != null) {
+                        addChild(ENTITY_REF, parser.getName());
+                    }
+                    parser.nextToken();
+            }
+        }
+        while (!leave);
+    }
+
+    /** Removes the child object at the given index */
+
+    public void removeChild(int idx) {
+        children.removeElementAt(idx);
+
+        /***  Modification by HHS - start ***/
+        //      types.deleteCharAt (index);
+        /***/
+        int n = types.length() - 1;
+
+        for (int i = idx; i < n; i++)
+            types.setCharAt(i, types.charAt(i + 1));
+
+        types.setLength(n);
+
+        /***  Modification by HHS - end   ***/
+    }
+
+    /* returns a valid XML representation of this Element including
+        attributes and children. 
+    public String toString() {
+        try {
+            ByteArrayOutputStream bos =
+                new ByteArrayOutputStream();
+            XmlWriter xw =
+                new XmlWriter(new OutputStreamWriter(bos));
+            write(xw);
+            xw.close();
+            return new String(bos.toByteArray());
+        }
+        catch (IOException e) {
+            throw new RuntimeException(e.toString());
+        }
+    }
+    */
+
+    /** Writes this node to the given XmlWriter. For node and document,
+        this method is identical to writeChildren, except that the
+        stream is flushed automatically. */
+
+    public void write(XmlSerializer writer) throws IOException {
+        writeChildren(writer);
+        writer.flush();
+    }
+
+    /** Writes the children of this node to the given XmlWriter. */
+
+    public void writeChildren(XmlSerializer writer) throws IOException {
+        if (children == null)
+            return;
+
+        int len = children.size();
+
+        for (int i = 0; i < len; i++) {
+            int type = getType(i);
+            Object child = children.elementAt(i);
+            switch (type) {
+                case ELEMENT :
+                     ((Element) child).write(writer);
+                    break;
+
+                case TEXT :
+                    writer.text((String) child);
+                    break;
+
+                case IGNORABLE_WHITESPACE :
+                    writer.ignorableWhitespace((String) child);
+                    break;
+
+                case CDSECT :
+                    writer.cdsect((String) child);
+                    break;
+
+                case COMMENT :
+                    writer.comment((String) child);
+                    break;
+
+                case ENTITY_REF :
+                    writer.entityRef((String) child);
+                    break;
+
+                case PROCESSING_INSTRUCTION :
+                    writer.processingInstruction((String) child);
+                    break;
+
+                case DOCDECL :
+                    writer.docdecl((String) child);
+                    break;
+
+                default :
+                    throw new RuntimeException("Illegal type: " + type);
+            }
+        }
+    }
+}
diff --git a/xml/src/main/java/org/kxml2/wap/Wbxml.java b/xml/src/main/java/org/kxml2/wap/Wbxml.java
new file mode 100644
index 0000000..5b0c2d3
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/wap/Wbxml.java
@@ -0,0 +1,49 @@
+/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The  above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE. */
+
+package org.kxml2.wap;
+
+
+/** contains the WBXML constants  */
+
+
+public interface Wbxml {
+
+    static public final int SWITCH_PAGE = 0;
+    static public final int END = 1;
+    static public final int ENTITY = 2;
+    static public final int STR_I = 3;
+    static public final int LITERAL = 4;
+    static public final int EXT_I_0 = 0x40;
+    static public final int EXT_I_1 = 0x41;
+    static public final int EXT_I_2 = 0x42;
+    static public final int PI = 0x43;
+    static public final int LITERAL_C = 0x44;
+    static public final int EXT_T_0 = 0x80;
+    static public final int EXT_T_1 = 0x81;
+    static public final int EXT_T_2 = 0x82;
+    static public final int STR_T = 0x83;
+    static public final int LITERAL_A = 0x084;
+    static public final int EXT_0 = 0x0c0;
+    static public final int EXT_1 = 0x0c1;
+    static public final int EXT_2 = 0x0c2;
+    static public final int OPAQUE = 0x0c3; 
+    static public final int LITERAL_AC = 0x0c4;
+}
diff --git a/xml/src/main/java/org/kxml2/wap/WbxmlParser.java b/xml/src/main/java/org/kxml2/wap/WbxmlParser.java
new file mode 100644
index 0000000..617e1d4
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/wap/WbxmlParser.java
@@ -0,0 +1,1075 @@
+/* Copyright (c) 2002,2003,2004 Stefan Haustein, Oberhausen, Rhld., Germany
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The  above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE. */
+
+// Contributors: Bjorn Aadland, Chris Bartley, Nicola Fankhauser,
+//               Victor Havin,  Christian Kurzke, Bogdan Onoiu,
+//                Elias Ross, Jain Sanjay, David Santoro.
+
+package org.kxml2.wap;
+
+import java.io.*;
+import java.util.Vector;
+import java.util.Hashtable;
+
+import org.xmlpull.v1.*;
+
+
+public class WbxmlParser implements XmlPullParser {
+
+    static final String HEX_DIGITS = "0123456789abcdef";
+    
+    /** Parser event type for Wbxml-specific events. The Wbxml event code can be 
+     * accessed with getWapCode() */
+    
+    public static final int WAP_EXTENSION = 64;
+    
+    static final private String UNEXPECTED_EOF =
+    "Unexpected EOF";
+    static final private String ILLEGAL_TYPE =
+    "Wrong event type";
+    
+    private InputStream in;
+    
+    private int TAG_TABLE = 0;
+    private int ATTR_START_TABLE = 1;
+    private int ATTR_VALUE_TABLE = 2;
+    
+    private String[] attrStartTable;
+    private String[] attrValueTable;
+    private String[] tagTable;
+    private byte[] stringTable;
+    private Hashtable cacheStringTable = null;
+    private boolean processNsp;
+    
+    private int depth;
+    private String[] elementStack = new String[16];
+    private String[] nspStack = new String[8];
+    private int[] nspCounts = new int[4];
+    
+    private int attributeCount;
+    private String[] attributes = new String[16];
+    private int nextId = -2;
+    
+    private Vector tables = new Vector();
+    
+    private int version;
+    private int publicIdentifierId;
+    
+    //    StartTag current;
+    //    ParseEvent next;
+    
+    private String prefix;
+    private String namespace;
+    private String name;
+    private String text;
+
+    private Object wapExtensionData;
+    private int wapCode;
+    
+    private int type;
+    
+    private boolean degenerated;
+    private boolean isWhitespace;
+    private String encoding;
+    
+    public boolean getFeature(String feature) {
+        if (XmlPullParser
+        .FEATURE_PROCESS_NAMESPACES
+        .equals(feature))
+            return processNsp;
+        else
+            return false;
+    }
+    
+    public String getInputEncoding() {
+        return encoding;
+    }
+    
+    public void defineEntityReplacementText(
+    String entity,
+    String value)
+    throws XmlPullParserException {
+        
+        // just ignore, has no effect
+    }
+    
+    public Object getProperty(String property) {
+        return null;
+    }
+    
+    public int getNamespaceCount(int depth) {
+        if (depth > this.depth)
+            throw new IndexOutOfBoundsException();
+        return nspCounts[depth];
+    }
+    
+    public String getNamespacePrefix(int pos) {
+        return nspStack[pos << 1];
+    }
+    
+    public String getNamespaceUri(int pos) {
+        return nspStack[(pos << 1) + 1];
+    }
+    
+    public String getNamespace(String prefix) {
+        
+        if ("xml".equals(prefix))
+            return "http://www.w3.org/XML/1998/namespace";
+        if ("xmlns".equals(prefix))
+            return "http://www.w3.org/2000/xmlns/";
+        
+        for (int i = (getNamespaceCount(depth) << 1) - 2;
+        i >= 0;
+        i -= 2) {
+            if (prefix == null) {
+                if (nspStack[i] == null)
+                    return nspStack[i + 1];
+            }
+            else if (prefix.equals(nspStack[i]))
+                return nspStack[i + 1];
+        }
+        return null;
+    }
+    
+    public int getDepth() {
+        return depth;
+    }
+    
+    public String getPositionDescription() {
+        
+        StringBuffer buf =
+        new StringBuffer(
+        type < TYPES.length ? TYPES[type] : "unknown");
+        buf.append(' ');
+        
+        if (type == START_TAG || type == END_TAG) {
+            if (degenerated)
+                buf.append("(empty) ");
+            buf.append('<');
+            if (type == END_TAG)
+                buf.append('/');
+            
+            if (prefix != null)
+                buf.append("{" + namespace + "}" + prefix + ":");
+            buf.append(name);
+            
+            int cnt = attributeCount << 2;
+            for (int i = 0; i < cnt; i += 4) {
+                buf.append(' ');
+                if (attributes[i + 1] != null)
+                    buf.append(
+                    "{"
+                    + attributes[i]
+                    + "}"
+                    + attributes[i
+                    + 1]
+                    + ":");
+                buf.append(
+                attributes[i
+                + 2]
+                + "='"
+                + attributes[i
+                + 3]
+                + "'");
+            }
+            
+            buf.append('>');
+        }
+        else if (type == IGNORABLE_WHITESPACE);
+        else if (type != TEXT)
+            buf.append(getText());
+        else if (isWhitespace)
+            buf.append("(whitespace)");
+        else {
+            String text = getText();
+            if (text.length() > 16)
+                text = text.substring(0, 16) + "...";
+            buf.append(text);
+        }
+        
+        return buf.toString();
+    }
+    
+    public int getLineNumber() {
+        return -1;
+    }
+    
+    public int getColumnNumber() {
+        return -1;
+    }
+    
+    public boolean isWhitespace()
+    throws XmlPullParserException {
+        if (type != TEXT
+        && type != IGNORABLE_WHITESPACE
+        && type != CDSECT)
+            exception(ILLEGAL_TYPE);
+        return isWhitespace;
+    }
+    
+    public String getText() {
+        return text;
+    }
+    
+    public char[] getTextCharacters(int[] poslen) {
+        if (type >= TEXT) {
+            poslen[0] = 0;
+            poslen[1] = text.length();
+            char[] buf = new char[text.length()];
+            text.getChars(0, text.length(), buf, 0);
+            return buf;
+        }
+        
+        poslen[0] = -1;
+        poslen[1] = -1;
+        return null;
+    }
+    
+    public String getNamespace() {
+        return namespace;
+    }
+    
+    public String getName() {
+        return name;
+    }
+    
+    public String getPrefix() {
+        return prefix;
+    }
+    
+    public boolean isEmptyElementTag()
+    throws XmlPullParserException {
+        if (type != START_TAG)
+            exception(ILLEGAL_TYPE);
+        return degenerated;
+    }
+    
+    public int getAttributeCount() {
+        return attributeCount;
+    }
+    
+    public String getAttributeType(int index) {
+        return "CDATA";
+    }
+    
+    public boolean isAttributeDefault(int index) {
+        return false;
+    }
+    
+    public String getAttributeNamespace(int index) {
+        if (index >= attributeCount)
+            throw new IndexOutOfBoundsException();
+        return attributes[index << 2];
+    }
+    
+    public String getAttributeName(int index) {
+        if (index >= attributeCount)
+            throw new IndexOutOfBoundsException();
+        return attributes[(index << 2) + 2];
+    }
+    
+    public String getAttributePrefix(int index) {
+        if (index >= attributeCount)
+            throw new IndexOutOfBoundsException();
+        return attributes[(index << 2) + 1];
+    }
+    
+    public String getAttributeValue(int index) {
+        if (index >= attributeCount)
+            throw new IndexOutOfBoundsException();
+        return attributes[(index << 2) + 3];
+    }
+    
+    public String getAttributeValue(
+    String namespace,
+    String name) {
+        
+        for (int i = (attributeCount << 2) - 4;
+        i >= 0;
+        i -= 4) {
+            if (attributes[i + 2].equals(name)
+            && (namespace == null
+            || attributes[i].equals(namespace)))
+                return attributes[i + 3];
+        }
+        
+        return null;
+    }
+    
+    public int getEventType() throws XmlPullParserException {
+        return type;
+    }
+    
+    
+    // TODO: Reuse resolveWapExtension here? Raw Wap extensions would still be accessible
+    // via nextToken();  ....?
+    
+    public int next() throws XmlPullParserException, IOException {
+        
+        isWhitespace = true;
+        int minType = 9999;
+        
+        while (true) {
+            
+            String save = text;
+            
+            nextImpl();
+            
+            if (type < minType)
+                minType = type;
+            
+            if (minType > CDSECT) continue; // no "real" event so far
+            
+            if (minType >= TEXT) {  // text, see if accumulate
+                
+                if (save != null) text = text == null ? save : save + text;
+                
+                switch(peekId()) {
+                    case Wbxml.ENTITY:
+                    case Wbxml.STR_I:
+                    case Wbxml.STR_T:
+                    case Wbxml.LITERAL:
+                    case Wbxml.LITERAL_C:
+                    case Wbxml.LITERAL_A:
+                    case Wbxml.LITERAL_AC: continue;
+                }
+            }
+            
+            break;
+        }
+        
+        type = minType;
+        
+        if (type > TEXT)
+            type = TEXT;
+        
+        return type;
+    }
+    
+    
+    public int nextToken() throws XmlPullParserException, IOException {
+        
+        isWhitespace = true;
+        nextImpl();
+        return type;
+    }
+    
+    
+    
+    public int nextTag() throws XmlPullParserException, IOException {
+        
+        next();
+        if (type == TEXT && isWhitespace)
+            next();
+        
+        if (type != END_TAG && type != START_TAG)
+            exception("unexpected type");
+        
+        return type;
+    }
+    
+    
+    public String nextText() throws XmlPullParserException, IOException {
+        if (type != START_TAG)
+            exception("precondition: START_TAG");
+        
+        next();
+        
+        String result;
+        
+        if (type == TEXT) {
+            result = getText();
+            next();
+        }
+        else
+            result = "";
+        
+        if (type != END_TAG)
+            exception("END_TAG expected");
+        
+        return result;
+    }
+    
+    
+    public void require(int type, String namespace, String name)
+    throws XmlPullParserException, IOException {
+        
+        if (type != this.type
+        || (namespace != null && !namespace.equals(getNamespace()))
+        || (name != null && !name.equals(getName())))
+            exception(
+            "expected: " + (type == WAP_EXTENSION ? "WAP Ext." : (TYPES[type] + " {" + namespace + "}" + name)));
+    }
+    
+    
+    public void setInput(Reader reader) throws XmlPullParserException {
+        exception("InputStream required");
+    }
+    
+    public void setInput(InputStream in, String enc)
+    throws XmlPullParserException {
+        
+        this.in = in;
+        
+        try {
+            version = readByte();
+            publicIdentifierId = readInt();
+            
+            if (publicIdentifierId == 0)
+                readInt();
+            
+            int charset = readInt(); // skip charset
+            
+            if (null == enc){
+                switch (charset){
+                    case   4: encoding = "ISO-8859-1"; break;
+                    case 106: encoding = "UTF-8";      break;
+                    // add more if you need them
+                    // http://www.iana.org/assignments/character-sets
+                    // case MIBenum: encoding = Name  break;
+                    default:  throw new UnsupportedEncodingException(""+charset);
+                } 
+            }else{
+                encoding = enc;
+            }
+
+            int strTabSize = readInt();
+            stringTable = new byte[strTabSize];
+            
+            int ok = 0;
+            while(ok < strTabSize){
+                int cnt = in.read(stringTable, ok, strTabSize - ok);
+                if(cnt <= 0) break;
+                ok += cnt;
+            }
+            
+            selectPage(0, true);
+            selectPage(0, false);
+        }
+        catch (IOException e) {
+            exception("Illegal input format");
+        }
+    }
+    
+    public void setFeature(String feature, boolean value)
+    throws XmlPullParserException {
+        if (XmlPullParser.FEATURE_PROCESS_NAMESPACES.equals(feature))
+            processNsp = value;
+        else
+            exception("unsupported feature: " + feature);
+    }
+    
+    public void setProperty(String property, Object value)
+    throws XmlPullParserException {
+        throw new XmlPullParserException("unsupported property: " + property);
+    }
+    
+    // ---------------------- private / internal methods
+    
+    private final boolean adjustNsp()
+    throws XmlPullParserException {
+        
+        boolean any = false;
+        
+        for (int i = 0; i < attributeCount << 2; i += 4) {
+            // * 4 - 4; i >= 0; i -= 4) {
+            
+            String attrName = attributes[i + 2];
+            int cut = attrName.indexOf(':');
+            String prefix;
+            
+            if (cut != -1) {
+                prefix = attrName.substring(0, cut);
+                attrName = attrName.substring(cut + 1);
+            }
+            else if (attrName.equals("xmlns")) {
+                prefix = attrName;
+                attrName = null;
+            }
+            else
+                continue;
+            
+            if (!prefix.equals("xmlns")) {
+                any = true;
+            }
+            else {
+                int j = (nspCounts[depth]++) << 1;
+                
+                nspStack = ensureCapacity(nspStack, j + 2);
+                nspStack[j] = attrName;
+                nspStack[j + 1] = attributes[i + 3];
+                
+                if (attrName != null
+                && attributes[i + 3].equals(""))
+                    exception("illegal empty namespace");
+                
+                //  prefixMap = new PrefixMap (prefixMap, attrName, attr.getValue ());
+                
+                //System.out.println (prefixMap);
+                
+                System.arraycopy(
+                attributes,
+                i + 4,
+                attributes,
+                i,
+                ((--attributeCount) << 2) - i);
+                
+                i -= 4;
+            }
+        }
+        
+        if (any) {
+            for (int i = (attributeCount << 2) - 4;
+            i >= 0;
+            i -= 4) {
+                
+                String attrName = attributes[i + 2];
+                int cut = attrName.indexOf(':');
+                
+                if (cut == 0)
+                    throw new RuntimeException(
+                    "illegal attribute name: "
+                    + attrName
+                    + " at "
+                    + this);
+                
+                else if (cut != -1) {
+                    String attrPrefix =
+                    attrName.substring(0, cut);
+                    
+                    attrName = attrName.substring(cut + 1);
+                    
+                    String attrNs = getNamespace(attrPrefix);
+                    
+                    if (attrNs == null)
+                        throw new RuntimeException(
+                        "Undefined Prefix: "
+                        + attrPrefix
+                        + " in "
+                        + this);
+                    
+                    attributes[i] = attrNs;
+                    attributes[i + 1] = attrPrefix;
+                    attributes[i + 2] = attrName;
+                    
+                    for (int j = (attributeCount << 2) - 4;
+                    j > i;
+                    j -= 4)
+                        if (attrName.equals(attributes[j + 2])
+                        && attrNs.equals(attributes[j]))
+                            exception(
+                            "Duplicate Attribute: {"
+                            + attrNs
+                            + "}"
+                            + attrName);
+                }
+            }
+        }
+        
+        int cut = name.indexOf(':');
+        
+        if (cut == 0)
+            exception("illegal tag name: " + name);
+        else if (cut != -1) {
+            prefix = name.substring(0, cut);
+            name = name.substring(cut + 1);
+        }
+        
+        this.namespace = getNamespace(prefix);
+        
+        if (this.namespace == null) {
+            if (prefix != null)
+                exception("undefined prefix: " + prefix);
+            this.namespace = NO_NAMESPACE;
+        }
+        
+        return any;
+    }
+    
+    private final void setTable(int page, int type, String[] table) {
+        if(stringTable != null){
+            throw new RuntimeException("setXxxTable must be called before setInput!");
+        }
+        while(tables.size() < 3*page +3){
+            tables.addElement(null);
+        }
+        tables.setElementAt(table, page*3+type);
+    }
+    
+    
+    
+    
+    
+    private final void exception(String desc)
+    throws XmlPullParserException {
+        throw new XmlPullParserException(desc, this, null);
+    }
+    
+    
+    private void selectPage(int nr, boolean tags) throws XmlPullParserException{
+        if(tables.size() == 0 && nr == 0) return;
+        
+        if(nr*3 > tables.size())
+            exception("Code Page "+nr+" undefined!");
+        
+        if(tags)
+            tagTable = (String[]) tables.elementAt(nr * 3 + TAG_TABLE);
+        else {
+            attrStartTable = (String[]) tables.elementAt(nr * 3 + ATTR_START_TABLE);
+            attrValueTable = (String[]) tables.elementAt(nr * 3 + ATTR_VALUE_TABLE);
+        }
+    }
+    
+    private final void nextImpl()
+    throws IOException, XmlPullParserException {
+        
+        String s;
+        
+        if (type == END_TAG) {
+            depth--;
+        }
+        
+        if (degenerated) {
+            type = XmlPullParser.END_TAG;
+            degenerated = false;
+            return;
+        }
+        
+        text = null;
+        prefix = null;
+        name = null;
+        
+        int id = peekId ();
+        while(id == Wbxml.SWITCH_PAGE){
+            nextId = -2;
+            selectPage(readByte(), true);
+            id = peekId();
+        }
+        nextId = -2;
+        
+        switch (id) {
+            case -1 :
+                type = XmlPullParser.END_DOCUMENT;
+                break;
+                
+            case Wbxml.END : 
+            {
+                int sp = (depth - 1) << 2;
+                
+                type = END_TAG;
+                namespace = elementStack[sp];
+                prefix = elementStack[sp + 1];
+                name = elementStack[sp + 2];
+            }
+            break;
+            
+            case Wbxml.ENTITY : 
+            {
+                type = ENTITY_REF;
+                char c = (char) readInt();
+                text = "" + c;
+                name = "#" + ((int) c);
+            }
+            
+            break;
+            
+            case Wbxml.STR_I :
+                type = TEXT;
+                text = readStrI();
+                break;
+                
+            case Wbxml.EXT_I_0 :
+            case Wbxml.EXT_I_1 :
+            case Wbxml.EXT_I_2 :
+            case Wbxml.EXT_T_0 :
+            case Wbxml.EXT_T_1 :
+            case Wbxml.EXT_T_2 :
+            case Wbxml.EXT_0 :
+            case Wbxml.EXT_1 :
+            case Wbxml.EXT_2 :
+            case Wbxml.OPAQUE :
+                
+                type = WAP_EXTENSION;
+                wapCode = id;
+                wapExtensionData = parseWapExtension(id);
+                break;
+                
+            case Wbxml.PI :
+                throw new RuntimeException("PI curr. not supp.");
+                // readPI;
+                // break;
+                
+            case Wbxml.STR_T : 
+            {
+                type = TEXT;
+                text = readStrT();
+            }
+            break;
+            
+            default :
+                parseElement(id);
+        }
+        //        }
+        //      while (next == null);
+        
+        //        return next;
+    }
+    
+    /** Overwrite this method to intercept all wap events */
+    
+    public Object parseWapExtension(int id)  throws IOException, XmlPullParserException {
+        
+        switch (id) {
+            case Wbxml.EXT_I_0 :
+            case Wbxml.EXT_I_1 :
+            case Wbxml.EXT_I_2 :
+                return readStrI();
+                
+            case Wbxml.EXT_T_0 :
+            case Wbxml.EXT_T_1 :
+            case Wbxml.EXT_T_2 :
+                return new Integer(readInt());
+                
+            case Wbxml.EXT_0 :
+            case Wbxml.EXT_1 :
+            case Wbxml.EXT_2 :
+                return null;
+                
+            case Wbxml.OPAQUE : 
+            {
+                int count = readInt();
+                byte[] buf = new byte[count];
+                
+                while(count > 0){
+                    count -= in.read(buf, buf.length-count, count);
+                }
+                
+                return buf;
+            } // case OPAQUE
+    
+            
+            default:
+                exception("illegal id: "+id);
+                return null; // dead code
+        } // SWITCH
+    }
+    
+    public void readAttr() throws IOException, XmlPullParserException {
+        
+        int id = readByte();
+        int i = 0;
+        
+        while (id != 1) {
+            
+            while(id == Wbxml.SWITCH_PAGE){
+                selectPage(readByte(), false);
+                id = readByte();
+            }
+            
+            String name = resolveId(attrStartTable, id);
+            StringBuffer value;
+            
+            int cut = name.indexOf('=');
+            
+            if (cut == -1)
+                value = new StringBuffer();
+            else {
+                value =
+                new StringBuffer(name.substring(cut + 1));
+                name = name.substring(0, cut);
+            }
+            
+            id = readByte();
+            while (id > 128
+            || id == Wbxml.SWITCH_PAGE
+            || id == Wbxml.ENTITY
+            || id == Wbxml.STR_I
+            || id == Wbxml.STR_T
+            || (id >= Wbxml.EXT_I_0 && id <= Wbxml.EXT_I_2)
+            || (id >= Wbxml.EXT_T_0 && id <= Wbxml.EXT_T_2)) {
+                
+                switch (id) {
+                    case Wbxml.SWITCH_PAGE :
+                        selectPage(readByte(), false);
+                        break;
+                        
+                    case Wbxml.ENTITY :
+                        value.append((char) readInt());
+                        break;
+                        
+                    case Wbxml.STR_I :
+                        value.append(readStrI());
+                        break;
+                        
+                    case Wbxml.EXT_I_0 :
+                    case Wbxml.EXT_I_1 :
+                    case Wbxml.EXT_I_2 :
+                    case Wbxml.EXT_T_0 :
+                    case Wbxml.EXT_T_1 :
+                    case Wbxml.EXT_T_2 :
+                    case Wbxml.EXT_0 :
+                    case Wbxml.EXT_1 :
+                    case Wbxml.EXT_2 :
+                    case Wbxml.OPAQUE :
+                        value.append(resolveWapExtension(id, parseWapExtension(id)));
+                        break;
+                        
+                    case Wbxml.STR_T :
+                        value.append(readStrT());
+                        break;
+                        
+                    default :
+                        value.append(
+                        resolveId(attrValueTable, id));
+                }
+                
+                id = readByte();
+            }
+            
+            attributes = ensureCapacity(attributes, i + 4);
+            
+            attributes[i++] = "";
+            attributes[i++] = null;
+            attributes[i++] = name;
+            attributes[i++] = value.toString();
+            
+            attributeCount++;
+        }
+    }
+    
+    private int peekId () throws IOException {
+        if (nextId == -2) {
+            nextId = in.read ();
+        }
+        return nextId;
+    }
+    
+    /** overwrite for own WAP extension handling in attributes and high level parsing 
+     * (above nextToken() level) */
+    
+    protected String resolveWapExtension(int id, Object data){
+        
+        if(data instanceof byte[]){
+            StringBuffer sb = new StringBuffer();
+            byte[] b = (byte[]) data;
+            
+            for (int i = 0; i < b.length; i++) {
+                sb.append(HEX_DIGITS.charAt((b[i] >> 4) & 0x0f));
+                sb.append(HEX_DIGITS.charAt(b[i] & 0x0f));
+            }
+            return sb.toString();
+        }
+
+        return "$("+data+")";
+    }
+    
+    String resolveId(String[] tab, int id) throws IOException {
+        int idx = (id & 0x07f) - 5;
+        if (idx == -1){
+            wapCode = -1;
+            return readStrT();
+        }
+        if (idx < 0
+        || tab == null
+        || idx >= tab.length
+        || tab[idx] == null)
+            throw new IOException("id " + id + " undef.");
+        
+        wapCode = idx+5;
+        
+        return tab[idx];
+    }
+    
+    void parseElement(int id)
+    throws IOException, XmlPullParserException {
+        
+        type = START_TAG;
+        name = resolveId(tagTable, id & 0x03f);
+        
+        attributeCount = 0;
+        if ((id & 128) != 0) {
+            readAttr();
+        }
+        
+        degenerated = (id & 64) == 0;
+        
+        int sp = depth++ << 2;
+        
+        // transfer to element stack
+        
+        elementStack = ensureCapacity(elementStack, sp + 4);
+        elementStack[sp + 3] = name;
+        
+        if (depth >= nspCounts.length) {
+            int[] bigger = new int[depth + 4];
+            System.arraycopy(nspCounts, 0, bigger, 0, nspCounts.length);
+            nspCounts = bigger;
+        }
+        
+        nspCounts[depth] = nspCounts[depth - 1];
+        
+        for (int i = attributeCount - 1; i > 0; i--) {
+            for (int j = 0; j < i; j++) {
+                if (getAttributeName(i)
+                .equals(getAttributeName(j)))
+                    exception(
+                    "Duplicate Attribute: "
+                    + getAttributeName(i));
+            }
+        }
+        
+        if (processNsp)
+            adjustNsp();
+        else
+            namespace = "";
+        
+        elementStack[sp] = namespace;
+        elementStack[sp + 1] = prefix;
+        elementStack[sp + 2] = name;
+        
+    }
+    
+    private final String[] ensureCapacity(
+    String[] arr,
+    int required) {
+        if (arr.length >= required)
+            return arr;
+        String[] bigger = new String[required + 16];
+        System.arraycopy(arr, 0, bigger, 0, arr.length);
+        return bigger;
+    }
+    
+    int readByte() throws IOException {
+        int i = in.read();
+        if (i == -1)
+            throw new IOException("Unexpected EOF");
+        return i;
+    }
+    
+    int readInt() throws IOException {
+        int result = 0;
+        int i;
+        
+        do {
+            i = readByte();
+            result = (result << 7) | (i & 0x7f);
+        }
+        while ((i & 0x80) != 0);
+        
+        return result;
+    }
+    
+    String readStrI() throws IOException {
+        ByteArrayOutputStream buf = new ByteArrayOutputStream();
+        boolean wsp = true;
+        while (true){
+            int i = in.read();
+            if (i == 0){
+                break;
+            }
+            if (i == -1){
+                throw new IOException(UNEXPECTED_EOF);
+            }
+            if (i > 32){
+                wsp = false;
+            }
+            buf.write(i);
+        }
+        isWhitespace = wsp;
+        String result = new String(buf.toByteArray(), encoding);
+        buf.close();
+        return result;
+    }
+    
+    String readStrT() throws IOException {
+        int pos = readInt();
+        // As the main reason of stringTable is compression we build a cache of Strings
+        // stringTable is supposed to help create Strings from parts which means some cache hit rate
+        // This will help to minimize the Strings created when invoking readStrT() repeatedly
+        if (cacheStringTable == null){
+            //Lazy init if device is not using StringTable but inline 0x03 strings
+            cacheStringTable = new Hashtable();
+        }
+        String forReturn = (String) cacheStringTable.get(new Integer(pos));
+        if (forReturn == null){
+
+            int end = pos;
+            while(end < stringTable.length && stringTable[end] != '\0'){
+                end++;
+            }
+            forReturn = new String(stringTable, pos, end-pos, encoding);
+            cacheStringTable.put(new Integer(pos), forReturn);
+        }
+        return forReturn;
+    }
+    
+    /**
+     * Sets the tag table for a given page.
+     * The first string in the array defines tag 5, the second tag 6 etc.
+     */
+    
+    public void setTagTable(int page, String[] table) {
+        setTable(page, TAG_TABLE, table);
+        
+        //        this.tagTable = tagTable;
+        //      if (page != 0)
+        //        throw new RuntimeException("code pages curr. not supp.");
+    }
+    
+    /** Sets the attribute start Table for a given page.
+     *  The first string in the array defines attribute
+     *  5, the second attribute 6 etc. Please use the
+     *  character '=' (without quote!) as delimiter
+     *  between the attribute name and the (start of the) value
+     */
+    
+    public void setAttrStartTable(
+    int page,
+    String[] table) {
+        
+        setTable(page, ATTR_START_TABLE, table);
+    }
+    
+    /** Sets the attribute value Table for a given page.
+     *  The first string in the array defines attribute value 0x85,
+     *  the second attribute value 0x86 etc.
+     */
+    
+    public void setAttrValueTable(
+    int page,
+    String[] table) {
+        
+        setTable(page, ATTR_VALUE_TABLE, table);
+    }
+    
+    /** Returns the token ID for start tags or the event type for wap proprietary events
+     * such as OPAQUE.
+     */
+    
+    public int getWapCode(){
+        return wapCode;
+    }
+    
+    public Object getWapExtensionData(){
+        return wapExtensionData;
+    }
+    
+    
+}
diff --git a/xml/src/main/java/org/kxml2/wap/WbxmlSerializer.java b/xml/src/main/java/org/kxml2/wap/WbxmlSerializer.java
new file mode 100644
index 0000000..8c1b598
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/wap/WbxmlSerializer.java
@@ -0,0 +1,512 @@
+/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The  above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE. */
+
+//Contributors: Jonathan Cox, Bogdan Onoiu, Jerry Tian
+
+package org.kxml2.wap;
+
+import java.io.*;
+import java.util.*;
+
+import org.xmlpull.v1.*;
+
+// TODO: make some of the "direct" WBXML token writing methods public??
+
+/**
+ * A class for writing WBXML.
+ *
+ */
+
+
+
+public class WbxmlSerializer implements XmlSerializer {
+    
+    
+    Hashtable stringTable = new Hashtable();
+    
+    OutputStream out;
+    
+    ByteArrayOutputStream buf = new ByteArrayOutputStream();
+    ByteArrayOutputStream stringTableBuf = new ByteArrayOutputStream();
+    
+    String pending;
+    int depth;
+    String name;
+    String namespace;
+    Vector attributes = new Vector();
+    
+    Hashtable attrStartTable = new Hashtable();
+    Hashtable attrValueTable = new Hashtable();
+    Hashtable tagTable = new Hashtable();
+    
+    private int attrPage;
+    private int tagPage;
+    
+    private String encoding;
+    
+    
+    public XmlSerializer attribute(String namespace, String name, String value) {
+        attributes.addElement(name);
+        attributes.addElement(value);
+        return this;
+    }
+    
+    
+    public void cdsect (String cdsect) throws IOException{
+        text (cdsect);
+    }
+    
+    
+    
+    /* silently ignore comment */
+    
+    public void comment (String comment) {
+    }
+    
+    
+    public void docdecl (String docdecl) {
+        throw new RuntimeException ("Cannot write docdecl for WBXML");
+    }
+    
+    
+    public void entityRef (String er) {
+        throw new RuntimeException ("EntityReference not supported for WBXML");
+    }
+    
+    public int getDepth() {
+        return depth;
+    }
+    
+    
+    public boolean getFeature (String name) {
+        return false;
+    }
+    
+    public String getNamespace() {
+        throw new RuntimeException("NYI");
+    }
+    
+    public String getName() {
+        throw new RuntimeException("NYI");
+    }
+    
+    public String getPrefix(String nsp, boolean create) {
+        throw new RuntimeException ("NYI");
+    }
+    
+    
+    public Object getProperty (String name) {
+        return null;
+    }
+    
+    public void ignorableWhitespace (String sp) {
+    }
+    
+    
+    public void endDocument() throws IOException {
+        writeInt(out, stringTableBuf.size());
+        
+        // write StringTable
+        
+        out.write(stringTableBuf.toByteArray());
+        
+        // write buf
+        
+        out.write(buf.toByteArray());
+        
+        // ready!
+        
+        out.flush();
+    }
+    
+    
+    /** ATTENTION: flush cannot work since Wbxml documents require
+      buffering. Thus, this call does nothing. */
+    
+    public void flush() {
+    }
+    
+    
+    public void checkPending(boolean degenerated) throws IOException {
+        if (pending == null)
+            return;
+        
+        int len = attributes.size();
+        
+        int[] idx = (int[]) tagTable.get(pending);
+        
+        // if no entry in known table, then add as literal
+        if (idx == null) {
+            buf.write(
+            len == 0
+            ? (degenerated ? Wbxml.LITERAL : Wbxml.LITERAL_C)
+            : (degenerated ? Wbxml.LITERAL_A : Wbxml.LITERAL_AC));
+            
+            writeStrT(pending, false);
+        }
+        else {
+            if(idx[0] != tagPage){
+                tagPage=idx[0];
+                buf.write(Wbxml.SWITCH_PAGE);
+                buf.write(tagPage);
+            }
+            
+            buf.write(
+            len == 0
+            ? (degenerated ? idx[1] : idx[1] | 64)
+            : (degenerated
+            ? idx[1] | 128
+            : idx[1] | 192));
+           
+        }
+        
+        for (int i = 0; i < len;) {
+            idx = (int[]) attrStartTable.get(attributes.elementAt(i));
+            
+            if (idx == null) {
+                buf.write(Wbxml.LITERAL);
+                writeStrT((String) attributes.elementAt(i), false);
+            }
+            else {
+                if(idx[0] != attrPage){
+                        attrPage = idx[0];
+                    buf.write(0);
+                    buf.write(attrPage);
+                }
+                buf.write(idx[1]);
+            }
+            idx = (int[]) attrValueTable.get(attributes.elementAt(++i));
+            if (idx == null) {
+                writeStr((String) attributes.elementAt(i));
+            }
+            else {
+                if(idx[0] != attrPage){
+                        attrPage = idx[0];
+                    buf.write(0);
+                    buf.write(attrPage);                    
+                }
+                buf.write(idx[1]);
+            }
+            ++i;
+        }
+        
+        if (len > 0)
+            buf.write(Wbxml.END);
+        
+        pending = null;
+        attributes.removeAllElements();
+    }
+    
+    
+    public void processingInstruction(String pi) {
+        throw new RuntimeException ("PI NYI");
+    }
+    
+    
+    public void setFeature(String name, boolean value) {
+        throw new IllegalArgumentException ("unknown feature "+name);
+    }
+    
+    
+    
+    public void setOutput (Writer writer) {
+        throw new RuntimeException ("Wbxml requires an OutputStream!");
+    }
+    
+    public void setOutput (OutputStream out, String encoding) throws IOException {
+        
+        this.encoding = encoding == null ? "UTF-8" : encoding;
+        this.out = out;
+        
+        buf = new ByteArrayOutputStream();
+        stringTableBuf = new ByteArrayOutputStream();
+        
+        // ok, write header
+    }
+    
+    
+    public void setPrefix(String prefix, String nsp) {
+        throw new RuntimeException("NYI");
+    }
+    
+    public void setProperty(String property, Object value) {
+        throw new IllegalArgumentException ("unknown property "+property);
+    }
+    
+    
+    public void startDocument(String s, Boolean b) throws IOException{
+        out.write(0x03); // version 1.3
+        // http://www.openmobilealliance.org/tech/omna/omna-wbxml-public-docid.htm
+        out.write(0x01); // unknown or missing public identifier
+
+        // default encoding is UTF-8
+        
+        if(s != null){
+            encoding = s;
+        }
+        
+        if (encoding.toUpperCase().equals("UTF-8")){
+            out.write(106);
+        }else if (encoding.toUpperCase().equals("ISO-8859-1")){
+            out.write(0x04);
+        }else{
+            throw new UnsupportedEncodingException(s);
+        }
+    }
+    
+    
+    public XmlSerializer startTag(String namespace, String name) throws IOException {
+        
+        if (namespace != null && !"".equals(namespace))
+            throw new RuntimeException ("NSP NYI");
+        
+        //current = new State(current, prefixMap, name);
+        
+        checkPending(false);
+        pending = name;
+        depth++;
+        
+        return this;
+    }
+    
+    public XmlSerializer text(char[] chars, int start, int len) throws IOException {
+
+        checkPending(false);
+        
+        writeStr(new String(chars, start, len));
+        
+        return this;
+    }
+    
+    public XmlSerializer text(String text) throws IOException {
+        
+        checkPending(false);
+        
+        writeStr(text);
+    
+        return this;
+    }
+    
+
+    /** Used in text() and attribute() to write text */
+    
+    private void writeStr(String text) throws IOException{
+        int p0 = 0;
+        int lastCut = 0;
+        int len = text.length();
+        
+        while(p0 < len){
+            while(p0 < len && text.charAt(p0) < 'A' ){ // skip interpunctation
+                p0++;
+            }
+            int p1 = p0;
+            while(p1 < len && text.charAt(p1) >= 'A'){
+                p1++;
+            }
+            
+            if(p1 - p0 > 10) {
+
+                if(p0 > lastCut && text.charAt(p0-1) == ' ' 
+                    && stringTable.get(text.substring(p0, p1)) == null){
+                    
+                       buf.write(Wbxml.STR_T);
+                       writeStrT(text.substring(lastCut, p1), false);
+                }
+                else {
+
+                    if(p0 > lastCut && text.charAt(p0-1) == ' '){
+                        p0--;
+                    }
+
+                    if(p0 > lastCut){
+                        buf.write(Wbxml.STR_T);
+                        writeStrT(text.substring(lastCut, p0), false);
+                    }
+                    buf.write(Wbxml.STR_T);
+                    writeStrT(text.substring(p0, p1), true);
+                }
+                lastCut = p1;
+            }
+            p0 = p1;
+        }
+
+        if(lastCut < len){
+            buf.write(Wbxml.STR_T);
+            writeStrT(text.substring(lastCut, len), false);
+        }
+    }
+    
+    
+
+    public XmlSerializer endTag(String namespace, String name) throws IOException {
+        
+        //        current = current.prev;
+        
+        if (pending != null)
+            checkPending(true);
+        else
+            buf.write(Wbxml.END);
+        
+        depth--;
+        
+        return this;
+    }
+    
+    /** 
+     * @throws IOException */
+    
+    public void writeWapExtension(int type, Object data) throws IOException {
+        checkPending(false);
+        buf.write(type);
+        switch(type){
+        case Wbxml.EXT_0:
+        case Wbxml.EXT_1:
+        case Wbxml.EXT_2:
+            break;
+        
+        case Wbxml.OPAQUE:
+            byte[] bytes = (byte[]) data;
+            writeInt(buf, bytes.length);
+            buf.write(bytes);
+            break;
+            
+        case Wbxml.EXT_I_0:
+        case Wbxml.EXT_I_1:
+        case Wbxml.EXT_I_2:
+            writeStrI(buf, (String) data);
+            break;
+
+        case Wbxml.EXT_T_0:
+        case Wbxml.EXT_T_1:
+        case Wbxml.EXT_T_2:
+            writeStrT((String) data, false);
+            break;
+            
+        default: 
+            throw new IllegalArgumentException();
+        }
+    }
+    
+    // ------------- internal methods --------------------------
+    
+    static void writeInt(OutputStream out, int i) throws IOException {
+        byte[] buf = new byte[5];
+        int idx = 0;
+        
+        do {
+            buf[idx++] = (byte) (i & 0x7f);
+            i = i >> 7;
+        }
+        while (i != 0);
+        
+        while (idx > 1) {
+            out.write(buf[--idx] | 0x80);
+        }
+        out.write(buf[0]);
+    }
+    
+    void writeStrI(OutputStream out, String s) throws IOException {
+        byte[] data = s.getBytes(encoding);
+        out.write(data);
+        out.write(0);
+    }
+    
+    private final void writeStrT(String s, boolean mayPrependSpace) throws IOException {
+        
+        Integer idx = (Integer) stringTable.get(s);
+        
+        if (idx != null) {
+            writeInt(buf, idx.intValue());
+        }
+        else{
+            int i = stringTableBuf.size();
+            if(s.charAt(0) >= '0' && mayPrependSpace){
+                s = ' ' + s;
+                writeInt(buf, i+1);
+            }
+            else{
+                writeInt(buf, i);
+            }
+            
+               stringTable.put(s, new Integer(i));
+               if(s.charAt(0) == ' '){
+                   stringTable.put(s.substring(1), new Integer(i+1));
+               }
+               int j = s.lastIndexOf(' ');
+               if(j > 1){
+                   stringTable.put(s.substring(j), new Integer(i+j));
+                   stringTable.put(s.substring(j+1), new Integer(i+j+1));
+               }
+                
+            writeStrI(stringTableBuf, s);
+            stringTableBuf.flush();
+        }
+        
+    }
+    
+    /**
+     * Sets the tag table for a given page.
+     * The first string in the array defines tag 5, the second tag 6 etc.
+     */
+    
+    public void setTagTable(int page, String[] tagTable) {
+        // TODO: clear entries in tagTable?
+        
+        for (int i = 0; i < tagTable.length; i++) {
+            if (tagTable[i] != null) {
+                Object idx = new int[]{page, i+5};
+                this.tagTable.put(tagTable[i], idx);
+            }
+        }
+    }
+    
+    /**
+     * Sets the attribute start Table for a given page.
+     * The first string in the array defines attribute
+     * 5, the second attribute 6 etc.
+     *  Please use the
+     *  character '=' (without quote!) as delimiter
+     *  between the attribute name and the (start of the) value
+     */
+    public void setAttrStartTable(int page, String[] attrStartTable) {
+        
+        for (int i = 0; i < attrStartTable.length; i++) {
+            if (attrStartTable[i] != null) {
+                Object idx = new int[] {page, i + 5};
+                this.attrStartTable.put(attrStartTable[i], idx);
+            }
+        }
+    }
+    
+    /**
+     * Sets the attribute value Table for a given page.
+     * The first string in the array defines attribute value 0x85,
+     * the second attribute value 0x86 etc.
+     */
+    public void setAttrValueTable(int page, String[] attrValueTable) {
+        // clear entries in this.table!
+        for (int i = 0; i < attrValueTable.length; i++) {
+            if (attrValueTable[i] != null) {
+                Object idx = new int[]{page, i + 0x085};
+                this.attrValueTable.put(attrValueTable[i], idx);
+            }
+        }
+    }
+}
diff --git a/xml/src/main/java/org/kxml2/wap/syncml/SyncML.java b/xml/src/main/java/org/kxml2/wap/syncml/SyncML.java
new file mode 100644
index 0000000..5ea8496
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/wap/syncml/SyncML.java
@@ -0,0 +1,192 @@
+package org.kxml2.wap.syncml;
+
+import org.kxml2.wap.*;
+
+public abstract class SyncML {
+    
+    
+    // SyncML-Common (-//SYNCML//DTD SyncML 1.2//EN and -//SYNCML//DTD MetInf 1.2//EN) support
+    
+    public static WbxmlParser createParser() {
+        WbxmlParser p = new WbxmlParser();
+        p.setTagTable(0, TAG_TABLE_0);
+        p.setTagTable(1, TAG_TABLE_1);
+        return p;
+    }
+
+    public static WbxmlSerializer createSerializer() {
+        WbxmlSerializer s = new WbxmlSerializer();
+        s.setTagTable(0, TAG_TABLE_0);
+        s.setTagTable(1, TAG_TABLE_1);
+        return s;
+    }
+    
+    
+    // SyncML-Common + DMDDF (-//OMA//DTD-DM-DDF 1.2//EN) support
+    
+    public static WbxmlParser createDMParser() {
+        WbxmlParser p = createParser();
+        p.setTagTable(2, TAG_TABLE_2_DM);
+        return p;
+    }
+
+    public static WbxmlSerializer createDMSerializer() {
+        WbxmlSerializer s = createSerializer();
+        s.setTagTable(2, TAG_TABLE_2_DM);
+        return s;
+    }
+
+    // Tables
+    
+    public static final String [] TAG_TABLE_0 = {
+        
+         //  -//SYNCML//DTD SyncML 1.2//EN
+        
+         "Add",            // 0x05 
+         "Alert",          // 0x06 
+         "Archive",        // 0x07 
+         "Atomic",         // 0x08 
+         "Chal",           // 0x09 
+         "Cmd",            // 0x0a 
+         "CmdID",          // 0x0b 
+         "CmdRef",         // 0x0c 
+         "Copy",           // 0x0d 
+         "Cred",           // 0x0e 
+         "Data",           // 0x0f 
+         "Delete",         // 0x10 
+         "Exec",           // 0x11 
+         "Final",          // 0x12 
+         "Get",            // 0x13 
+         "Item",           // 0x14 
+         "Lang",           // 0x15 
+         "LocName",        // 0x16 
+         "LocURI",         // 0x17 
+         "Map",            // 0x18 
+         "MapItem",        // 0x19 
+         "Meta",           // 0x1a 
+         "MsgID",          // 0x1b 
+         "MsgRef",         // 0x1c 
+         "NoResp",         // 0x1d 
+         "NoResults",      // 0x1e 
+         "Put",            // 0x1f 
+         "Replace",        // 0x20 
+         "RespURI",        // 0x21 
+         "Results",        // 0x22 
+         "Search",         // 0x23 
+         "Sequence",       // 0x24 
+         "SessionID",      // 0x25 
+         "SftDel",         // 0x26 
+         "Source",         // 0x27 
+         "SourceRef",      // 0x28 
+         "Status",         // 0x29 
+         "Sync",           // 0x2a 
+         "SyncBody",       // 0x2b 
+         "SyncHdr",        // 0x2c 
+         "SyncML",         // 0x2d 
+         "Target",         // 0x2e 
+         "TargetRef",      // 0x2f 
+         "Reserved for future use",    // 0x30 
+         "VerDTD",         // 0x31 
+         "VerProto",       // 0x32 
+         "NumberOfChanged",// 0x33 
+         "MoreData",       // 0x34 
+         "Field",          // 0x35
+         "Filter",         // 0x36
+         "Record",         // 0x37
+         "FilterType",     // 0x38
+         "SourceParent",   // 0x39
+         "TargetParent",   // 0x3a
+         "Move",           // 0x3b
+         "Correlator"      // 0x3c
+    };  
+    
+    public static final String [] TAG_TABLE_1 = {
+       
+         //  -//SYNCML//DTD MetInf 1.2//EN 
+        
+         "Anchor",         // 0x05 
+         "EMI",            // 0x06 
+         "Format",         // 0x07 
+         "FreeID",         // 0x08 
+         "FreeMem",        // 0x09 
+         "Last",           // 0x0a 
+         "Mark",           // 0x0b 
+         "MaxMsgSize",     // 0x0c 
+         "Mem",            // 0x0d 
+         "MetInf",         // 0x0e 
+         "Next",           // 0x0f 
+         "NextNonce",      // 0x10 
+         "SharedMem",      // 0x11 
+         "Size",           // 0x12 
+         "Type",           // 0x13 
+         "Version",        // 0x14 
+         "MaxObjSize",     // 0x15
+         "FieldLevel"      // 0x16
+         
+    };
+
+    public static final String [] TAG_TABLE_2_DM = {
+        
+        //  -//OMA//DTD-DM-DDF 1.2//EN 
+       
+        "AccessType",         // 0x05 
+        "ACL",                // 0x06 
+        "Add",                // 0x07 
+        "b64",                // 0x08 
+        "bin",                // 0x09 
+        "bool",               // 0x0a 
+        "chr",                // 0x0b 
+        "CaseSense",          // 0x0c 
+        "CIS",                // 0x0d 
+        "Copy",               // 0x0e 
+        "CS",                 // 0x0f 
+        "date",               // 0x10 
+        "DDFName",            // 0x11 
+        "DefaultValue",       // 0x12 
+        "Delete",             // 0x13 
+        "Description",        // 0x14 
+        "DDFFormat",          // 0x15 
+        "DFProperties",       // 0x16 
+        "DFTitle",            // 0x17 
+        "DFType",             // 0x18 
+        "Dynamic",            // 0x19 
+        "Exec",               // 0x1a 
+        "float",              // 0x1b 
+        "Format",             // 0x1c 
+        "Get",                // 0x1d 
+        "int",                // 0x1e 
+        "Man",                // 0x1f 
+        "MgmtTree",           // 0x20 
+        "MIME",               // 0x21 
+        "Mod",                // 0x22 
+        "Name",               // 0x23 
+        "Node",               // 0x24 
+        "node",               // 0x25 
+        "NodeName",           // 0x26 
+        "null",               // 0x27 
+        "Occurence",          // 0x28 
+        "One",                // 0x29 
+        "OneOrMore",          // 0x2a 
+        "OneOrN",             // 0x2b 
+        "Path",               // 0x2c 
+        "Permanent",          // 0x2d 
+        "Replace",            // 0x2e 
+        "RTProperties",       // 0x2f 
+        "Scope",              // 0x30 
+        "Size",               // 0x31 
+        "time",               // 0x32 
+        "Title",              // 0x33 
+        "TStamp",             // 0x34 
+        "Type",               // 0x35
+        "Value",              // 0x36
+        "VerDTD",             // 0x37
+        "VerNo",              // 0x38
+        "xml",                // 0x39
+        "ZeroOrMore",         // 0x3a
+        "ZeroOrN",            // 0x3b
+        "ZeroOrOne"           // 0x3c
+        
+   };
+    
+}
+
diff --git a/xml/src/main/java/org/kxml2/wap/wml/Wml.java b/xml/src/main/java/org/kxml2/wap/wml/Wml.java
new file mode 100644
index 0000000..7e925d8
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/wap/wml/Wml.java
@@ -0,0 +1,233 @@
+package org.kxml2.wap.wml;
+
+import org.kxml2.wap.*;
+
+
+/** This class contains the wml coding tables for elements 
+ *  and attributes needed by the WmlParser. 
+ */
+
+
+public abstract class Wml {
+
+    /** Creates a WbxmlParser with the WML code pages set */
+
+    public static WbxmlParser createParser() {
+        WbxmlParser p = new WbxmlParser();
+        p.setTagTable(0, TAG_TABLE);
+        p.setAttrStartTable(0, ATTR_START_TABLE);
+        p.setAttrValueTable(0, ATTR_VALUE_TABLE);
+        return p;
+    }
+
+    public static WbxmlSerializer createSerializer() {
+        WbxmlSerializer s = new WbxmlSerializer();
+        s.setTagTable(0, TAG_TABLE);
+        s.setAttrStartTable(0, ATTR_START_TABLE);
+        s.setAttrValueTable(0, ATTR_VALUE_TABLE);
+        return s;
+    }
+
+
+    public static final String [] TAG_TABLE = {
+
+    null, // 05
+    null, // 06
+    null, // 07
+    null, // 08
+    null, // 09
+    null, // 0A
+    null, // 0B
+    null, // 0C
+    null, // 0D
+    null, // 0E
+    null, // 0F
+
+    null, // 10
+    null, // 11
+    null, // 12
+    null, // 13
+    null, // 14
+    null, // 15
+    null, // 16
+    null, // 17
+    null, // 18
+    null, // 19
+    null, // 1A
+    null, // 1B
+    "a",  // 1C
+    "td", // 1D
+    "tr", // 1E
+    "table", // 1F
+
+    "p", // 20
+    "postfield", // 21
+    "anchor", // 22
+    "access", // 23
+    "b",  // 24
+    "big", // 25
+    "br", // 26
+    "card", // 27
+    "do", // 28
+    "em", // 29
+    "fieldset", // 2A
+    "go", // 2B
+    "head", // 2C
+    "i", // 2D
+    "img", // 2E
+    "input", // 2F
+
+    "meta", // 30
+    "noop", // 31
+    "prev", // 32
+    "onevent", // 33
+    "optgroup", // 34
+    "option", // 35
+    "refresh", // 36
+    "select", // 37
+    "small", // 38
+    "strong", // 39
+    null, // 3A
+    "template", // 3B
+    "timer", // 3C
+    "u", // 3D
+    "setvar", // 3E
+    "wml", // 3F
+    };
+
+    
+    public static final String [] ATTR_START_TABLE = { 
+    "accept-charset", // 05
+    "align=bottom", // 06
+    "align=center", // 07
+    "align=left", // 08
+    "align=middle", // 09
+    "align=right", // 0A
+    "align=top", // 0B
+    "alt", // 0C
+    "content", // 0D
+    null, // 0E
+    "domain", // 0F
+    
+    "emptyok=false", // 10
+    "emptyok=true", // 11
+    "format", // 12
+    "height", // 13
+    "hspace", // 14
+    "ivalue", // 15
+    "iname", // 16
+    null, // 17
+    "label", // 18
+    "localsrc", // 19
+    "maxlength", // 1A
+    "method=get", // 1B
+    "method=post", // 1C
+    "mode=nowrap", // 1D
+    "mode=wrap", // 1E
+    "multiple=false", // 1F
+
+    "multiple=true", // 20
+    "name", // 21
+    "newcontext=false", // 22
+    "newcontext=true", // 23
+    "onpick", // 24
+    "onenterbackward", // 25
+    "onenterforward", // 26
+    "ontimer", // 27
+    "optimal=false", // 28
+    "optimal=true", // 29
+    "path", // 2A
+    null, // 2B
+    null, // 2C
+    null, // 2D
+    "scheme", // 2E
+    "sendreferer=false", // 2F
+    
+    "sendreferer=true", // 30
+    "size", // 31
+    "src", // 32
+    "ordered=true", // 33
+    "ordered=false", // 34
+    "tabindex", // 35
+    "title", // 36
+    "type", // 37
+    "type=accept", // 38
+    "type=delete", // 39
+    "type=help", // 3A
+    "type=password", // 3B
+    "type=onpick", // 3C
+    "type=onenterbackward", // 3D
+    "type=onenterforward", // 3E
+    "type=ontimer", // 3F
+
+    null, // 40
+    null, // 41
+    null, // 42
+    null, // 43
+    null, // 44
+    "type=options", // 45
+    "type=prev", // 46
+    "type=reset", // 47
+    "type=text", // 48
+    "type=vnd.", // 49
+    "href", // 4A
+    "href=http://", // 4B
+    "href=https://", // 4C
+    "value", // 4D
+    "vspace", // 4E
+    "width", // 4F
+
+    "xml:lang", // 50
+    null, // 51
+    "align", // 52
+    "columns", // 53
+    "class", // 54
+    "id", // 55
+    "forua=false", // 56
+    "forua=true", // 57
+    "src=http://", // 58
+    "src=https://", // 59
+    "http-equiv", // 5A
+    "http-equiv=Content-Type", // 5B
+    "content=application/vnd.wap.wmlc;charset=", // 5C
+    "http-equiv=Expires", // 5D
+    null, // 5E
+    null, // 5F
+    };
+
+
+    public static final String [] ATTR_VALUE_TABLE = {
+    ".com/", // 85
+    ".edu/", // 86
+    ".net/", // 87
+    ".org/", // 88
+    "accept", // 89
+    "bottom", // 8A
+    "clear", // 8B
+    "delete", // 8C
+    "help", // 8D
+    "http://", // 8E
+    "http://www.", // 8F
+    
+    "https://", // 90
+    "https://www.", // 91
+    null, // 92
+    "middle", // 93
+    "nowrap", // 94
+    "onpick", // 95
+    "onenterbackward", // 96
+    "onenterforward", // 97
+    "ontimer", // 98
+    "options", // 99
+    "password", // 9A
+    "reset", // 9B
+    null, // 9C
+    "text", // 9D
+    "top", // 9E
+    "unknown", // 9F
+    
+    "wrap", // A0
+    "www.", // A1
+    };
+}    
+
diff --git a/xml/src/main/java/org/kxml2/wap/wv/WV.java b/xml/src/main/java/org/kxml2/wap/wv/WV.java
new file mode 100644
index 0000000..e2afbfb
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/wap/wv/WV.java
@@ -0,0 +1,593 @@
+package org.kxml2.wap.wv;
+
+import java.io.IOException;
+
+import org.kxml2.wap.*;
+
+/*
+
+ * WV.java
+
+ *
+
+ * Created on 25 September 2003, 10:40
+
+ */
+
+
+
+
+
+   /** 
+     *    Wireless Village CSP 1.1 ("OMA-WV-CSP-V1_1-20021001-A.pdf")
+     *    Wireless Village CSP 1.2 ("OMA-IMPS-WV-CSP_WBXML-v1_2-20030221-C.PDF")
+     *    There are some bugs in the 1.2 spec but this is Ok. 1.2 is candidate  
+ *
+
+ * @author  Bogdan Onoiu
+
+ */
+
+public abstract class WV {
+
+    
+
+    
+    
+    public static WbxmlParser createParser () throws IOException {
+        
+        WbxmlParser parser = new WbxmlParser();
+
+        parser.setTagTable (0, WV.tagTablePage0);
+        parser.setTagTable (1, WV.tagTablePage1);
+        parser.setTagTable (2, WV.tagTablePage2);
+        parser.setTagTable (3, WV.tagTablePage3);
+        parser.setTagTable (4, WV.tagTablePage4);
+        parser.setTagTable (5, WV.tagTablePage5);
+        parser.setTagTable (6, WV.tagTablePage6);
+        parser.setTagTable (7, WV.tagTablePage7);
+        parser.setTagTable (8, WV.tagTablePage8);
+        parser.setTagTable (9, WV.tagTablePage9);
+        parser.setTagTable (10, WV.tagTablePageA);
+
+        parser.setAttrStartTable (0, WV.attrStartTable);
+        
+        parser.setAttrValueTable (0, WV.attrValueTable);
+
+        return parser;
+    }
+    
+   
+    
+    public static final String [] tagTablePage0 = {
+        /* Common ... continue on Page 0x09 */
+        "Acceptance",     //0x00, 0x05
+        "AddList",        //0x00, 0x06
+        "AddNickList",    //0x00, 0x07
+        "SName",          //0x00, 0x08
+        "WV-CSP-Message", //0x00, 0x09
+        "ClientID",       //0x00, 0x0A
+        "Code",           //0x00, 0x0B
+        "ContactList",    //0x00, 0x0C
+        "ContentData",    //0x00, 0x0D
+        "ContentEncoding",//0x00, 0x0E
+        "ContentSize",    //0x00, 0x0F
+        "ContentType",    //0x00, 0x10
+        "DateTime",       //0x00, 0x11
+        "Description",    //0x00, 0x12
+        "DetailedResult", //0x00, 0x13
+        "EntityList",     //0x00, 0x14
+        "Group",          //0x00, 0x15
+        "GroupID",        //0x00, 0x16
+        "GroupList",      //0x00, 0x17
+        "InUse",          //0x00, 0x18
+        "Logo",           //0x00, 0x19
+        "MessageCount",   //0x00, 0x1A
+        "MessageID",      //0x00, 0x1B
+        "MessageURI",     //0x00, 0x1C
+        "MSISDN",         //0x00, 0x1D
+        "Name",           //0x00, 0x1E
+        "NickList",       //0x00, 0x1F
+        "NickName",       //0x00, 0x20
+        "Poll",           //0x00, 0x21
+        "Presence",       //0x00, 0x22
+        "PresenceSubList",//0x00, 0x23
+        "PresenceValue",  //0x00, 0x24
+        "Property",       //0x00, 0x25
+        "Qualifier",      //0x00, 0x26
+        "Recipient",      //0x00, 0x27
+        "RemoveList",     //0x00, 0x28
+        "RemoveNickList", //0x00, 0x29
+        "Result",         //0x00, 0x2A
+        "ScreenName",     //0x00, 0x2B
+        "Sender",         //0x00, 0x2C
+        "Session",        //0x00, 0x2D
+        "SessionDescriptor",//0x00, 0x2E
+        "SessionID",      //0x00, 0x2F
+        "SessionType",    //0x00, 0x30
+        "Status",         //0x00, 0x31
+        "Transaction",    //0x00, 0x32
+        "TransactionContent",//0x00, 0x33
+        "TransactionDescriptor",//0x00, 0x34
+        "TransactionID",  //0x00, 0x35
+        "TransactionMode",//0x00, 0x36
+        "URL",            //0x00, 0x37
+        "URLList",        //0x00, 0x38
+        "User",           //0x00, 0x39
+        "UserID",         //0x00, 0x3A
+        "UserList",       //0x00, 0x3B
+        "Validity",       //0x00, 0x3C
+        "Value",          //0x00, 0x3D
+    };
+    
+    public static final String [] tagTablePage1 = {
+        /* Access ... continue on Page 0x0A */
+        "AllFunctions",             //  0x01, 0x05
+        "AllFunctionsRequest",      //  0x01, 0x06
+        "CancelInvite-Request",     //  0x01, 0x07
+        "CancelInviteUser-Request", //  0x01, 0x08
+        "Capability",               //  0x01, 0x09
+        "CapabilityList",           //  0x01, 0x0A
+        "CapabilityRequest",        //  0x01, 0x0B
+        "ClientCapability-Request", //  0x01, 0x0C
+        "ClientCapability-Response",//  0x01, 0x0D
+        "DigestBytes",          //  0x01, 0x0E
+        "DigestSchema",         //  0x01, 0x0F
+        "Disconnect",           //  0x01, 0x10
+        "Functions",            //  0x01, 0x11
+        "GetSPInfo-Request",    //  0x01, 0x12
+        "GetSPInfo-Response",   //  0x01, 0x13
+        "InviteID",             //  0x01, 0x14
+        "InviteNote",           //  0x01, 0x15
+        "Invite-Request",       //  0x01, 0x16
+        "Invite-Response",      //  0x01, 0x17
+        "InviteType",           //  0x01, 0x18
+        "InviteUser-Request",   //  0x01, 0x19
+        "InviteUser-Response",  //  0x01, 0x1A
+        "KeepAlive-Request",    //  0x01, 0x1B
+        "KeepAliveTime",        //  0x01, 0x1C
+        "Login-Request",        //  0x01, 0x1D
+        "Login-Response",       //  0x01, 0x1E
+        "Logout-Request",       //  0x01, 0x1F
+        "Nonce",                //  0x01, 0x20
+        "Password",             //  0x01, 0x21
+        "Polling-Request",      //  0x01, 0x22
+        "ResponseNote",         //  0x01, 0x23
+        "SearchElement",        //  0x01, 0x24
+        "SearchFindings",       //  0x01, 0x25
+        "SearchID",             //  0x01, 0x26
+        "SearchIndex",          //  0x01, 0x27
+        "SearchLimit",          //  0x01, 0x28
+        "KeepAlive-Response",   //  0x01, 0x29
+        "SearchPairList",       //  0x01, 0x2A
+        "Search-Request",       //  0x01, 0x2B
+        "Search-Response",      //  0x01, 0x2C
+        "SearchResult",         //  0x01, 0x2D
+        "Service-Request",      //  0x01, 0x2E
+        "Service-Response",     //  0x01, 0x2F
+        "SessionCookie",        //  0x01, 0x30
+        "StopSearch-Request",   //  0x01, 0x31
+        "TimeToLive",           //  0x01, 0x32
+        "SearchString",         //  0x01, 0x33
+        "CompletionFlag",       //  0x01, 0x34
+        null,                   //  0x01, 0x35
+        "ReceiveList",          //  0x01, 0x36 /* WV 1.2 */
+        "VerifyID-Request",     //  0x01, 0x37 /* WV 1.2 */
+        "Extended-Request",     //  0x01, 0x38 /* WV 1.2 */
+        "Extended-Response",    //  0x01, 0x39 /* WV 1.2 */
+        "AgreedCapabilityList", //  0x01, 0x3A /* WV 1.2 */
+        "Extended-Data",        //  0x01, 0x3B /* WV 1.2 */
+        "OtherServer",          //  0x01, 0x3C /* WV 1.2 */
+        "PresenceAttributeNSName",//0x01, 0x3D /* WV 1.2 */
+        "SessionNSName",        //  0x01, 0x3E /* WV 1.2 */
+        "TransactionNSName",    //  0x01, 0x3F /* WV 1.2 */
+    };
+    
+    public static final String [] tagTablePage2 = {
+        /* Service ... continue on Page 0x08 */
+        "ADDGM",        //  0x02, 0x05
+        "AttListFunc",  //  0x02, 0x06
+        "BLENT",        //  0x02, 0x07
+        "CAAUT",        //  0x02, 0x08
+        "CAINV",        //  0x02, 0x09
+        "CALI",         //  0x02, 0x0A
+        "CCLI",         //  0x02, 0x0B
+        "ContListFunc", //  0x02, 0x0C
+        "CREAG",        //  0x02, 0x0D
+        "DALI",         //  0x02, 0x0E
+        "DCLI",         //  0x02, 0x0F
+        "DELGR",        //  0x02, 0x10
+        "FundamentalFeat",//0x02, 0x11
+        "FWMSG",        //  0x02, 0x12
+        "GALS",         //  0x02, 0x13
+        "GCLI",         //  0x02, 0x14
+        "GETGM",        //  0x02, 0x15
+        "GETGP",        //  0x02, 0x16
+        "GETLM",        //  0x02, 0x17
+        "GETM",         //  0x02, 0x18
+        "GETPR",        //  0x02, 0x19
+        "GETSPI",       //  0x02, 0x1A
+        "GETWL",        //  0x02, 0x1B
+        "GLBLU",        //  0x02, 0x1C
+        "GRCHN",        //  0x02, 0x1D
+        "GroupAuthFunc",//  0x02, 0x1E
+        "GroupFeat",    //  0x02, 0x1F
+        "GroupMgmtFunc",//  0x02, 0x20
+        "GroupUseFunc", //  0x02, 0x21
+        "IMAuthFunc",   //  0x02, 0x22
+        "IMFeat",       //  0x02, 0x23
+        "IMReceiveFunc",//  0x02, 0x24
+        "IMSendFunc",   //  0x02, 0x25
+        "INVIT",        //  0x02, 0x26
+        "InviteFunc",   //  0x02, 0x27
+        "MBRAC",        //  0x02, 0x28
+        "MCLS",         //  0x02, 0x29
+        "MDELIV",       //  0x02, 0x2A
+        "NEWM",         //  0x02, 0x2B
+        "NOTIF",        //  0x02, 0x2C
+        "PresenceAuthFunc",//0x02, 0x2D
+        "PresenceDeliverFunc",//0x02, 0x2E
+        "PresenceFeat", //  0x02, 0x2F
+        "REACT",        //  0x02, 0x30
+        "REJCM",        //  0x02, 0x31
+        "REJEC",        //  0x02, 0x32
+        "RMVGM",        //  0x02, 0x33
+        "SearchFunc",   //  0x02, 0x34
+        "ServiceFunc",  //  0x02, 0x35
+        "SETD",         //  0x02, 0x36
+        "SETGP",        //  0x02, 0x37
+        "SRCH",         //  0x02, 0x38
+        "STSRC",        //  0x02, 0x39
+        "SUBGCN",       //  0x02, 0x3A
+        "UPDPR",        //  0x02, 0x3B
+        "WVCSPFeat",    //  0x02, 0x3C
+        "MF",           //  0x02, 0x3D /* WV 1.2 */
+        "MG",           //  0x02, 0x3E /* WV 1.2 */
+        "MM"            //  0x02, 0x3F /* WV 1.2 */
+    };
+    
+    public static final String [] tagTablePage3 = {
+        /* Client Capability */
+        "AcceptedCharset",          //  0x03, 0x05
+        "AcceptedContentLength",    //  0x03, 0x06
+        "AcceptedContentType",      //  0x03, 0x07
+        "AcceptedTransferEncoding", //  0x03, 0x08
+        "AnyContent",               //  0x03, 0x09
+        "DefaultLanguage",          //  0x03, 0x0A
+        "InitialDeliveryMethod",    //  0x03, 0x0B
+        "MultiTrans",               //  0x03, 0x0C
+        "ParserSize",               //  0x03, 0x0D
+        "ServerPollMin",            //  0x03, 0x0E
+        "SupportedBearer",          //  0x03, 0x0F
+        "SupportedCIRMethod",       //  0x03, 0x10
+        "TCPAddress",               //  0x03, 0x11
+        "TCPPort",                  //  0x03, 0x12
+        "UDPPort"                  //  0x03, 0x13
+    };
+    
+    public static final String [] tagTablePage4 = {
+        /* Presence Primitive */
+        "CancelAuth-Request",           //  0x04, 0x05
+        "ContactListProperties",        //  0x04, 0x06
+        "CreateAttributeList-Request",  //  0x04, 0x07
+        "CreateList-Request",           //  0x04, 0x08
+        "DefaultAttributeList",         //  0x04, 0x09
+        "DefaultContactList",           //  0x04, 0x0A
+        "DefaultList",                  //  0x04, 0x0B
+        "DeleteAttributeList-Request",  //  0x04, 0x0C
+        "DeleteList-Request",           //  0x04, 0x0D
+        "GetAttributeList-Request",     //  0x04, 0x0E
+        "GetAttributeList-Response",    //  0x04, 0x0F
+        "GetList-Request",              //  0x04, 0x10
+        "GetList-Response",             //  0x04, 0x11
+        "GetPresence-Request",          //  0x04, 0x12
+        "GetPresence-Response",         //  0x04, 0x13
+        "GetWatcherList-Request",       //  0x04, 0x14
+        "GetWatcherList-Response",      //  0x04, 0x15
+        "ListManage-Request",           //  0x04, 0x16
+        "ListManage-Response",          //  0x04, 0x17
+        "UnsubscribePresence-Request",  //  0x04, 0x18
+        "PresenceAuth-Request",         //  0x04, 0x19
+        "PresenceAuth-User",            //  0x04, 0x1A
+        "PresenceNotification-Request", //  0x04, 0x1B
+        "UpdatePresence-Request",       //  0x04, 0x1C
+        "SubscribePresence-Request",    //  0x04, 0x1D
+        "Auto-Subscribe",               //  0x04, 0x1E /* WV 1.2 */
+        "GetReactiveAuthStatus-Request",//  0x04, 0x1F /* WV 1.2 */
+        "GetReactiveAuthStatus-Response",// 0x04, 0x20 /* WV 1.2 */
+    };
+    
+    public static final String [] tagTablePage5 = {
+        /* Presence Attribute */
+        "Accuracy",         //  0x05, 0x05
+        "Address",          //  0x05, 0x06
+        "AddrPref",         //  0x05, 0x07
+        "Alias",            //  0x05, 0x08
+        "Altitude",         //  0x05, 0x09
+        "Building",         //  0x05, 0x0A
+        "Caddr",            //  0x05, 0x0B
+        "City",             //  0x05, 0x0C
+        "ClientInfo",       //  0x05, 0x0D
+        "ClientProducer",   //  0x05, 0x0E
+        "ClientType",       //  0x05, 0x0F
+        "ClientVersion",    //  0x05, 0x10
+        "CommC",            //  0x05, 0x11
+        "CommCap",          //  0x05, 0x12
+        "ContactInfo",      //  0x05, 0x13
+        "ContainedvCard",   //  0x05, 0x14
+        "Country",          //  0x05, 0x15
+        "Crossing1",        //  0x05, 0x16
+        "Crossing2",        //  0x05, 0x17
+        "DevManufacturer",  //  0x05, 0x18
+        "DirectContent",    //  0x05, 0x19
+        "FreeTextLocation", //  0x05, 0x1A
+        "GeoLocation",      //  0x05, 0x1B
+        "Language",         //  0x05, 0x1C
+        "Latitude",         //  0x05, 0x1D
+        "Longitude",        //  0x05, 0x1E
+        "Model",            //  0x05, 0x1F
+        "NamedArea",        //  0x05, 0x20
+        "OnlineStatus",     //  0x05, 0x21
+        "PLMN",             //  0x05, 0x22
+        "PrefC",            //  0x05, 0x23
+        "PreferredContacts",//  0x05, 0x24
+        "PreferredLanguage",//  0x05, 0x25
+        "PreferredContent", //  0x05, 0x26
+        "PreferredvCard",   //  0x05, 0x27
+        "Registration",     //  0x05, 0x28
+        "StatusContent",    //  0x05, 0x29
+        "StatusMood",       //  0x05, 0x2A
+        "StatusText",       //  0x05, 0x2B
+        "Street",           //  0x05, 0x2C
+        "TimeZone",         //  0x05, 0x2D
+        "UserAvailability", //  0x05, 0x2E
+        "Cap",              //  0x05, 0x2F
+        "Cname",            //  0x05, 0x30
+        "Contact",          //  0x05, 0x31
+        "Cpriority",        //  0x05, 0x32
+        "Cstatus",          //  0x05, 0x33
+        "Note",             //  0x05, 0x34 /* WV 1.2 */
+        "Zone",             //  0x05, 0x35
+        null,
+        "Inf_link",         //  0x05, 0x37 /* WV 1.2 */
+        "InfoLink",         //  0x05, 0x38 /* WV 1.2 */
+        "Link",             //  0x05, 0x39 /* WV 1.2 */
+        "Text",             //  0x05, 0x3A /* WV 1.2 */
+    };
+    
+    public static final String [] tagTablePage6 = {
+        /* Messaging */
+        "BlockList",                //  0x06, 0x05
+//      "BlockUser-Request",        //  0x06, 0x06  //This is a bug in the spec
+        "BlockEntity-Request",        //  0x06, 0x06  
+        "DeliveryMethod",           //  0x06, 0x07
+        "DeliveryReport",           //  0x06, 0x08
+        "DeliveryReport-Request",   //  0x06, 0x09
+        "ForwardMessage-Request",   //  0x06, 0x0A
+        "GetBlockedList-Request",   //  0x06, 0x0B
+        "GetBlockedList-Response",  //  0x06, 0x0C
+        "GetMessageList-Request",   //  0x06, 0x0D
+        "GetMessageList-Response",  //  0x06, 0x0E
+        "GetMessage-Request",       //  0x06, 0x0F
+        "GetMessage-Response",      //  0x06, 0x10
+        "GrantList",                //  0x06, 0x11
+        "MessageDelivered",         //  0x06, 0x12
+        "MessageInfo",              //  0x06, 0x13
+        "MessageNotification",      //  0x06, 0x14
+        "NewMessage",               //  0x06, 0x15
+        "RejectMessage-Request",    //  0x06, 0x16
+        "SendMessage-Request",      //  0x06, 0x17
+        "SendMessage-Response",     //  0x06, 0x18
+        "SetDeliveryMethod-Request",//  0x06, 0x19
+        "DeliveryTime",             //  0x06, 0x1A
+    };
+    
+    public static final String [] tagTablePage7 = {
+        /* Group */
+        "AddGroupMembers-Request",  //  0x07, 0x05
+        "Admin",                    //  0x07, 0x06
+        "CreateGroup-Request",      //  0x07, 0x07
+        "DeleteGroup-Request",      //  0x07, 0x08
+        "GetGroupMembers-Request",  //  0x07, 0x09
+        "GetGroupMembers-Response", //  0x07, 0x0A
+        "GetGroupProps-Request",    //  0x07, 0x0B
+        "GetGroupProps-Response",   //  0x07, 0x0C
+        "GroupChangeNotice",        //  0x07, 0x0D
+        "GroupProperties",          //  0x07, 0x0E
+        "Joined",                   //  0x07, 0x0F
+        "JoinedRequest",            //  0x07, 0x10
+        "JoinGroup-Request",        //  0x07, 0x11
+        "JoinGroup-Response",       //  0x07, 0x12
+        "LeaveGroup-Request",       //  0x07, 0x13
+        "LeaveGroup-Response",      //  0x07, 0x14
+        "Left",                     //  0x07, 0x15
+        "MemberAccess-Request",     //  0x07, 0x16
+        "Mod",                      //  0x07, 0x17
+        "OwnProperties",            //  0x07, 0x18
+        "RejectList-Request",       //  0x07, 0x19
+        "RejectList-Response",      //  0x07, 0x1A
+        "RemoveGroupMembers-Request",// 0x07, 0x1B
+        "SetGroupProps-Request",    //  0x07, 0x1C
+        "SubscribeGroupNotice-Request", //  0x07, 0x1D
+        "SubscribeGroupNotice-Response",//  0x07, 0x1E
+        "Users",                    //  0x07, 0x1F
+        "WelcomeNote",              //  0x07, 0x20
+        "JoinGroup",                //  0x07, 0x21
+        "SubscribeNotification",    //  0x07, 0x22
+        "SubscribeType",            //  0x07, 0x23
+        "GetJoinedUsers-Request",   //  0x07, 0x24 /* WV 1.2 */
+        "GetJoinedUsers-Response",  //  0x07, 0x25 /* WV 1.2 */
+        "AdminMapList",             //  0x07, 0x26 /* WV 1.2 */
+        "AdminMapping",             //  0x07, 0x27 /* WV 1.2 */
+        "Mapping",                  //  0x07, 0x28 /* WV 1.2 */
+        "ModMapping",               //  0x07, 0x29 /* WV 1.2 */
+        "UserMapList",              //  0x07, 0x2A /* WV 1.2 */
+        "UserMapping",              //  0x07, 0x2B /* WV 1.2 */
+    };
+    
+    public static final String [] tagTablePage8 = {
+        /* Service ... continued */
+        "MP",                       //  0x08, 0x05 /* WV 1.2 */
+        "GETAUT",                   //  0x08, 0x06 /* WV 1.2 */
+        "GETJU",                    //  0x08, 0x07 /* WV 1.2 */
+        "VRID",                     //  0x08, 0x08 /* WV 1.2 */
+        "VerifyIDFunc",             //  0x08, 0x09 /* WV 1.2 */
+    };
+    
+    public static final String [] tagTablePage9 = {
+        /* Common ... continued */
+        "CIR",                      //  0x09, 0x05 /* WV 1.2 */
+        "Domain",                   //  0x09, 0x06 /* WV 1.2 */
+        "ExtBlock",                 //  0x09, 0x07 /* WV 1.2 */
+        "HistoryPeriod",            //  0x09, 0x08 /* WV 1.2 */
+        "IDList",                   //  0x09, 0x09 /* WV 1.2 */
+        "MaxWatcherList",           //  0x09, 0x0A /* WV 1.2 */
+        "ReactiveAuthState",        //  0x09, 0x0B /* WV 1.2 */
+        "ReactiveAuthStatus",       //  0x09, 0x0C /* WV 1.2 */
+        "ReactiveAuthStatusList",   //  0x09, 0x0D /* WV 1.2 */
+        "Watcher",                  //  0x09, 0x0E /* WV 1.2 */
+        "WatcherStatus"             //  0x09, 0x0F /* WV 1.2 */
+    };
+    
+    public static final String [] tagTablePageA = {
+        /* Access ... continued */
+        "WV-CSP-NSDiscovery-Request",  //0x0A, 0x05 /* WV 1.2 */
+        "WV-CSP-NSDiscovery-Response", //0x0A, 0x06 /* WV 1.2 */
+        "VersionList"                  //0x0A, 0x07 /* WV 1.2 */
+    };
+    
+    public static final String [] attrStartTable = {
+        "xmlns=http://www.wireless-village.org/CSP",//  0x00, 0x05
+        "xmlns=http://www.wireless-village.org/PA", //  0x00, 0x06
+        "xmlns=http://www.wireless-village.org/TRC",//  0x00, 0x07
+        "xmlns=http://www.openmobilealliance.org/DTD/WV-CSP",   //  0x00, 0x08
+        "xmlns=http://www.openmobilealliance.org/DTD/WV-PA",    //  0x00, 0x09
+        "xmlns=http://www.openmobilealliance.org/DTD/WV-TRC",   //  0x00, 0x0A
+    };
+    
+    public static final String [] attrValueTable = {
+      
+        "AccessType",                           // 0x00 /* Common value token */
+        "ActiveUsers",                          // 0x01 /* Common value token */
+        "Admin",                                // 0x02 /* Common value token */
+        "application/",                         // 0x03 /* Common value token */
+        "application/vnd.wap.mms-message",      // 0x04 /* Common value token */
+        "application/x-sms",                    // 0x05 /* Common value token */
+        "AutoJoin",                             // 0x06 /* Common value token */
+        "BASE64",                               // 0x07 /* Common value token */
+        "Closed",                               // 0x08 /* Common value token */
+        "Default",                              // 0x09 /* Common value token */
+        "DisplayName",                          // 0x0a /* Common value token */
+        "F",                                    // 0x0b /* Common value token */
+        "G",                                    // 0x0c /* Common value token */
+        "GR",                                   // 0x0d /* Common value token */
+        "http://",                              // 0x0e /* Common value token */
+        "https://",                             // 0x0f /* Common value token */
+        "image/",                               // 0x10 /* Common value token */
+        "Inband",                               // 0x11 /* Common value token */
+        "IM",                                   // 0x12 /* Common value token */
+        "MaxActiveUsers",                       // 0x13 /* Common value token */
+        "Mod",                                  // 0x14 /* Common value token */
+        "Name",                                 // 0x15 /* Common value token */
+        "None",                                 // 0x16 /* Common value token */
+        "N",                                    // 0x17 /* Common value token */
+        "Open",                                 // 0x18 /* Common value token */
+        "Outband",                              // 0x19 /* Common value token */
+        "PR",                                   // 0x1a /* Common value token */
+        "Private",                              // 0x1b /* Common value token */
+        "PrivateMessaging",                     // 0x1c /* Common value token */
+        "PrivilegeLevel",                       // 0x1d /* Common value token */
+        "Public",                               // 0x1e /* Common value token */
+        "P",                                    // 0x1f /* Common value token */
+        "Request",                              // 0x20 /* Common value token */
+        "Response",                             // 0x21 /* Common value token */
+        "Restricted",                           // 0x22 /* Common value token */
+        "ScreenName",                           // 0x23 /* Common value token */
+        "Searchable",                           // 0x24 /* Common value token */
+        "S",                                    // 0x25 /* Common value token */
+        "SC",                                   // 0x26 /* Common value token */
+        "text/",                                // 0x27 /* Common value token */
+        "text/plain",                           // 0x28 /* Common value token */
+        "text/x-vCalendar",                     // 0x29 /* Common value token */
+        "text/x-vCard",                         // 0x2a /* Common value token */
+        "Topic",                                // 0x2b /* Common value token */
+        "T",                                    // 0x2c /* Common value token */
+        "Type",                                 // 0x2d /* Common value token */
+        "U",                                    // 0x2e /* Common value token */
+        "US",                                   // 0x2f /* Common value token */
+        "www.wireless-village.org",             // 0x30 /* Common value token */
+        "AutoDelete",                           // 0x31 /* Common value token */ /* WV 1.2 */
+        "GM",                                   // 0x32 /* Common value token */ /* WV 1.2 */
+        "Validity",                             // 0x33 /* Common value token */ /* WV 1.2 */
+        "ShowID",                               // 0x34 /* Common value token */ /* WV 1.2 */
+        "GRANTED",                              // 0x35 /* Common value token */ /* WV 1.2 */
+        "PENDING",                              // 0x36 /* Common value token */ /* WV 1.2 */
+        null,                                   // 0x37
+        null,                                   // 0x38
+        null,                                   // 0x39
+        null,                                   // 0x3a
+        null,                                   // 0x3b
+        null,                                   // 0x3c
+        "GROUP_ID",                             // 0x3d /* Access value token */
+        "GROUP_NAME",                           // 0x3e /* Access value token */
+        "GROUP_TOPIC",                          // 0x3f /* Access value token */
+        "GROUP_USER_ID_JOINED",                 // 0x40 /* Access value token */
+        "GROUP_USER_ID_OWNER",                  // 0x41 /* Access value token */
+        "HTTP",                                 // 0x42 /* Access value token */
+        "SMS",                                  // 0x43 /* Access value token */
+        "STCP",                                 // 0x44 /* Access value token */
+        "SUDP",                                 // 0x45 /* Access value token */
+        "USER_ALIAS",                           // 0x46 /* Access value token */
+        "USER_EMAIL_ADDRESS",                   // 0x47 /* Access value token */
+        "USER_FIRST_NAME",                      // 0x48 /* Access value token */
+        "USER_ID",                              // 0x49 /* Access value token */
+        "USER_LAST_NAME",                       // 0x4a /* Access value token */
+        "USER_MOBILE_NUMBER",                   // 0x4b /* Access value token */
+        "USER_ONLINE_STATUS",                   // 0x4c /* Access value token */
+        "WAPSMS",                               // 0x4d /* Access value token */
+        "WAPUDP",                               // 0x4e /* Access value token */
+        "WSP",                                  // 0x4f /* Access value token */
+        "GROUP_USER_ID_AUTOJOIN",               // 0x50 /* Access value token */ /* WV 1.2 */
+        null,                                   // 0x51
+        null,                                   // 0x52
+        null,                                   // 0x53
+        null,                                   // 0x54
+        null,                                   // 0x55
+        null,                                   // 0x56
+        null,                                   // 0x57
+        null,                                   // 0x58
+        null,                                   // 0x59
+        null,                                   // 0x5a
+        "ANGRY",                                // 0x5b /* Presence value token */
+        "ANXIOUS",                              // 0x5c /* Presence value token */
+        "ASHAMED",                              // 0x5d /* Presence value token */
+        "AUDIO_CALL",                           // 0x5e /* Presence value token */
+        "AVAILABLE",                            // 0x5f /* Presence value token */
+        "BORED",                                // 0x60 /* Presence value token */
+        "CALL",                                 // 0x61 /* Presence value token */
+        "CLI",                                  // 0x62 /* Presence value token */
+        "COMPUTER",                             // 0x63 /* Presence value token */
+        "DISCREET",                             // 0x64 /* Presence value token */
+        "EMAIL",                                // 0x65 /* Presence value token */
+        "EXCITED",                              // 0x66 /* Presence value token */
+        "HAPPY",                                // 0x67 /* Presence value token */
+        "IM",                                   // 0x68 /* Presence value token */
+        "IM_OFFLINE",                           // 0x69 /* Presence value token */
+        "IM_ONLINE",                            // 0x6a /* Presence value token */
+        "IN_LOVE",                              // 0x6b /* Presence value token */
+        "INVINCIBLE",                           // 0x6c /* Presence value token */
+        "JEALOUS",                              // 0x6d /* Presence value token */
+        "MMS",                                  // 0x6e /* Presence value token */
+        "MOBILE_PHONE",                         // 0x6f /* Presence value token */
+        "NOT_AVAILABLE",                        // 0x70 /* Presence value token */
+        "OTHER",                                // 0x71 /* Presence value token */
+        "PDA",                                  // 0x72 /* Presence value token */
+        "SAD",                                  // 0x73 /* Presence value token */
+        "SLEEPY",                               // 0x74 /* Presence value token */
+        "SMS",                                  // 0x75 /* Presence value token */
+        "VIDEO_CALL",                           // 0x76 /* Presence value token */
+        "VIDEO_STREAM",                         // 0x77 /* Presence value token */
+    };
+    
+    
+}
diff --git a/xml/src/main/java/org/w3c/dom/Attr.java b/xml/src/main/java/org/w3c/dom/Attr.java
new file mode 100644
index 0000000..3bfde52
--- /dev/null
+++ b/xml/src/main/java/org/w3c/dom/Attr.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2000 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.w3c.dom;
+
+//BEGIN android-note
+//Filled some gaps in the documentation and refactored parts of the existing
+//documentation to make the Doclet happy.
+//END android-note
+
+/**
+ *  The <code>Attr</code> interface represents an attribute in an 
+ * <code>Element</code> object. Typically the allowable values for the 
+ * attribute are defined in a document type definition.
+ * <p><code>Attr</code> objects inherit the <code>Node</code> interface, but 
+ * since they are not actually child nodes of the element they describe, the 
+ * DOM does not consider them part of the document tree. Thus, the 
+ * <code>Node</code> attributes <code>parentNode</code>, 
+ * <code>previousSibling</code>, and <code>nextSibling</code> have a 
+ * <code>null</code> value for <code>Attr</code> objects. The DOM takes the 
+ * view that attributes are properties of elements rather than having a 
+ * separate identity from the elements they are associated with; this should 
+ * make it more efficient to implement such features as default attributes 
+ * associated with all elements of a given type. Furthermore, 
+ * <code>Attr</code> nodes may not be immediate children of a 
+ * <code>DocumentFragment</code>. However, they can be associated with 
+ * <code>Element</code> nodes contained within a 
+ * <code>DocumentFragment</code>. In short, users and implementors of the 
+ * DOM need to be aware that <code>Attr</code> nodes have some things in 
+ * common with other objects inheriting the <code>Node</code> interface, but 
+ * they also are quite distinct.
+ * <p> The attribute's effective value is determined as follows: if this 
+ * attribute has been explicitly assigned any value, that value is the 
+ * attribute's effective value; otherwise, if there is a declaration for 
+ * this attribute, and that declaration includes a default value, then that 
+ * default value is the attribute's effective value; otherwise, the 
+ * attribute does not exist on this element in the structure model until it 
+ * has been explicitly added. Note that the <code>nodeValue</code> attribute 
+ * on the <code>Attr</code> instance can also be used to retrieve the string 
+ * version of the attribute's value(s). 
+ * <p>In XML, where the value of an attribute can contain entity references, 
+ * the child nodes of the <code>Attr</code> node may be either 
+ * <code>Text</code> or <code>EntityReference</code> nodes (when these are 
+ * in use; see the description of <code>EntityReference</code> for 
+ * discussion). Because the DOM Core is not aware of attribute types, it 
+ * treats all attribute values as simple strings, even if the DTD or schema 
+ * declares them as having tokenized types. 
+ * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>.
+ */
+public interface Attr extends Node {
+    /**
+     * Returns the name of this attribute.
+     * 
+     * @return the name of the attribute.
+     */
+    public String getName();
+
+    /**
+     * If this attribute was explicitly given a value in the original 
+     * document, this is <code>true</code>; otherwise, it is 
+     * <code>false</code>. Note that the implementation is in charge of this 
+     * attribute, not the user. If the user changes the value of the 
+     * attribute (even if it ends up having the same value as the default 
+     * value) then the <code>specified</code> flag is automatically flipped 
+     * to <code>true</code>. To re-specify the attribute as the default 
+     * value from the DTD, the user must delete the attribute. The 
+     * implementation will then make a new attribute available with 
+     * <code>specified</code> set to <code>false</code> and the default 
+     * value (if one exists).
+     * <br>In summary:  If the attribute has an assigned value in the document 
+     * then <code>specified</code> is <code>true</code>, and the value is 
+     * the assigned value.  If the attribute has no assigned value in the 
+     * document and has a default value in the DTD, then 
+     * <code>specified</code> is <code>false</code>, and the value is the 
+     * default value in the DTD. If the attribute has no assigned value in 
+     * the document and has a value of #IMPLIED in the DTD, then the 
+     * attribute does not appear in the structure model of the document. If 
+     * the <code>ownerElement</code> attribute is <code>null</code> (i.e. 
+     * because it was just created or was set to <code>null</code> by the 
+     * various removal and cloning operations) <code>specified</code> is 
+     * <code>true</code>.
+     * 
+     * @return <code>true</code> if the attribute was specified,
+     *         <code>false</false> otherwise.
+     */
+    public boolean getSpecified();
+
+    /**
+     * Returns the value of the attribute is returned as a string. 
+     * Character and general entity references are replaced with their 
+     * values. See also the method <code>getAttribute</code> on the 
+     * <code>Element</code> interface.
+     * 
+     * @return the attribute value as a string.
+     */
+    public String getValue();
+    
+    /**
+     * Sets the value of the attribute. This creates a <code>Text</code> node
+     * with the unparsed contents of the string. I.e. any characters that an
+     * XML processor would recognize as markup are instead treated as literal
+     * text. See also the method <code>setAttribute</code> on the
+     * <code>Element</code> 
+     * interface.
+     * 
+     * @param value the new attribute value.
+     * 
+     * @exception DOMException 
+     *   NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
+     */
+    public void setValue(String value)
+                            throws DOMException;
+
+    /**
+     * The <code>Element</code> node this attribute is attached to or 
+     * <code>null</code> if this attribute is not in use.
+     * 
+     * @return the owner <code>Element</element>, or <code>null</code> is the
+     *         attribute is unused.
+     * 
+     * @since DOM Level 2
+     */
+    public Element getOwnerElement();
+
+}
diff --git a/xml/src/main/java/org/w3c/dom/CDATASection.java b/xml/src/main/java/org/w3c/dom/CDATASection.java
new file mode 100644
index 0000000..9e74734
--- /dev/null
+++ b/xml/src/main/java/org/w3c/dom/CDATASection.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2000 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.w3c.dom;
+
+/**
+ * CDATA sections are used to escape blocks of text containing characters that 
+ * would otherwise be regarded as markup. The only delimiter that is 
+ * recognized in a CDATA section is the "]]&gt;" string that ends the CDATA 
+ * section. CDATA sections cannot be nested. Their primary purpose is for 
+ * including material such as XML fragments, without needing to escape all 
+ * the delimiters.
+ * <p>The <code>DOMString</code> attribute of the <code>Text</code> node holds 
+ * the text that is contained by the CDATA section. Note that this may 
+ * contain characters that need to be escaped outside of CDATA sections and 
+ * that, depending on the character encoding ("charset") chosen for 
+ * serialization, it may be impossible to write out some characters as part 
+ * of a CDATA section. 
+ * <p> The <code>CDATASection</code> interface inherits from the 
+ * <code>CharacterData</code> interface through the <code>Text</code> 
+ * interface. Adjacent <code>CDATASection</code> nodes are not merged by use 
+ * of the <code>normalize</code> method of the <code>Node</code> interface.
+ * Because no markup is recognized within a <code>CDATASection</code>, 
+ * character numeric references cannot be used as an escape mechanism when 
+ * serializing. Therefore, action needs to be taken when serializing a 
+ * <code>CDATASection</code> with a character encoding where some of the 
+ * contained characters cannot be represented. Failure to do so would not 
+ * produce well-formed XML.One potential solution in the serialization 
+ * process is to end the CDATA section before the character, output the 
+ * character using a character reference or entity reference, and open a new 
+ * CDATA section for any further characters in the text node. Note, however, 
+ * that some code conversion libraries at the time of writing do not return 
+ * an error or exception when a character is missing from the encoding, 
+ * making the task of ensuring that data is not corrupted on serialization 
+ * more difficult.
+ * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>.
+ */
+public interface CDATASection extends Text {
+}
diff --git a/xml/src/main/java/org/w3c/dom/CharacterData.java b/xml/src/main/java/org/w3c/dom/CharacterData.java
new file mode 100644
index 0000000..47386e9
--- /dev/null
+++ b/xml/src/main/java/org/w3c/dom/CharacterData.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2000 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.w3c.dom;
+
+// BEGIN android-note
+// Cleaned up @param tags that seemed to be missing spaces between
+// the parameter name and the start of the description.
+// END android-note
+
+//BEGIN android-note
+//Filled some gaps in the documentation and refactored parts of the existing
+//documentation to make the Doclet happy.
+//END android-note
+
+/**
+ * The <code>CharacterData</code> interface extends Node with a set of 
+ * attributes and methods for accessing character data in the DOM. For 
+ * clarity this set is defined here rather than on each object that uses 
+ * these attributes and methods. No DOM objects correspond directly to 
+ * <code>CharacterData</code>, though <code>Text</code> and others do 
+ * inherit the interface from it. All <code>offsets</code> in this interface 
+ * start from <code>0</code>.
+ * <p>As explained in the <code>DOMString</code> interface, text strings in 
+ * the DOM are represented in UTF-16, i.e. as a sequence of 16-bit units. In 
+ * the following, the term 16-bit units is used whenever necessary to 
+ * indicate that indexing on CharacterData is done in 16-bit units.
+ * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>.
+ */
+public interface CharacterData extends Node {
+    /**
+     * Returns the character data of the node that implements this interface.
+     * The DOM implementation may not put arbitrary limits on the amount of data 
+     * that may be stored in a <code>CharacterData</code> node. However, 
+     * implementation limits may mean that the entirety of a node's data may 
+     * not fit into a single <code>DOMString</code>. In such cases, the user 
+     * may call <code>substringData</code> to retrieve the data in 
+     * appropriately sized pieces.
+     * 
+     * @return the character data as a string.
+     * 
+     * @exception DOMException
+     *   DOMSTRING_SIZE_ERR: Raised when it would return more characters than 
+     *   fit in a <code>DOMString</code> variable on the implementation 
+     *   platform.
+     */
+    public String getData()
+                            throws DOMException;
+    /**
+     * Sets the character data of the node that implements this interface. The
+     * DOM implementation may not put arbitrary limits on the amount of data 
+     * that may be stored in a <code>CharacterData</code> node. However, 
+     * implementation limits may mean that the entirety of a node's data may 
+     * not fit into a single <code>DOMString</code>. In such cases, the user 
+     * may call <code>substringData</code> to retrieve the data in 
+     * appropriately sized pieces.
+     * 
+     * @param data the new character data.
+     * 
+     * @exception DOMException
+     *   NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
+     */
+    public void setData(String data)
+                            throws DOMException;
+
+    /**
+     * The number of 16-bit units that are available through <code>data</code> 
+     * and the <code>substringData</code> method below. This may have the 
+     * value zero, i.e., <code>CharacterData</code> nodes may be empty.
+     * 
+     * @return the length in characters.
+     */
+    public int getLength();
+
+    /**
+     * Extracts a range of data from the node.
+     * @param offset Start offset of substring to extract.
+     * @param count The number of 16-bit units to extract.
+     * @return The specified substring. If the sum of <code>offset</code> and 
+     *   <code>count</code> exceeds the <code>length</code>, then all 16-bit 
+     *   units to the end of the data are returned.
+     * @exception DOMException
+     *   INDEX_SIZE_ERR: Raised if the specified <code>offset</code> is 
+     *   negative or greater than the number of 16-bit units in 
+     *   <code>data</code>, or if the specified <code>count</code> is 
+     *   negative.
+     *   <br>DOMSTRING_SIZE_ERR: Raised if the specified range of text does 
+     *   not fit into a <code>DOMString</code>.
+     */
+    public String substringData(int offset, 
+                                int count)
+                                throws DOMException;
+
+    /**
+     * Append the string to the end of the character data of the node. Upon 
+     * success, <code>data</code> provides access to the concatenation of 
+     * <code>data</code> and the <code>DOMString</code> specified.
+     * @param arg The <code>DOMString</code> to append.
+     * @exception DOMException
+     *   NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+     */
+    public void appendData(String arg)
+                           throws DOMException;
+
+    /**
+     * Insert a string at the specified 16-bit unit offset.
+     * @param offset The character offset at which to insert.
+     * @param arg The <code>DOMString</code> to insert.
+     * @exception DOMException
+     *   INDEX_SIZE_ERR: Raised if the specified <code>offset</code> is 
+     *   negative or greater than the number of 16-bit units in 
+     *   <code>data</code>.
+     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+     */
+    public void insertData(int offset, 
+                           String arg)
+                           throws DOMException;
+
+    /**
+     * Remove a range of 16-bit units from the node. Upon success, 
+     * <code>data</code> and <code>length</code> reflect the change.
+     * @param offset The offset from which to start removing.
+     * @param count The number of 16-bit units to delete. If the sum of 
+     *   <code>offset</code> and <code>count</code> exceeds 
+     *   <code>length</code> then all 16-bit units from <code>offset</code> 
+     *   to the end of the data are deleted.
+     * @exception DOMException
+     *   INDEX_SIZE_ERR: Raised if the specified <code>offset</code> is 
+     *   negative or greater than the number of 16-bit units in 
+     *   <code>data</code>, or if the specified <code>count</code> is 
+     *   negative.
+     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+     */
+    public void deleteData(int offset, 
+                           int count)
+                           throws DOMException;
+
+    /**
+     * Replace the characters starting at the specified 16-bit unit offset 
+     * with the specified string.
+     * @param offset The offset from which to start replacing.
+     * @param count The number of 16-bit units to replace. If the sum of 
+     *   <code>offset</code> and <code>count</code> exceeds 
+     *   <code>length</code>, then all 16-bit units to the end of the data 
+     *   are replaced; (i.e., the effect is the same as a <code>remove</code>
+     *    method call with the same range, followed by an <code>append</code>
+     *    method invocation).
+     * @param arg The <code>DOMString</code> with which the range must be 
+     *   replaced.
+     * @exception DOMException
+     *   INDEX_SIZE_ERR: Raised if the specified <code>offset</code> is 
+     *   negative or greater than the number of 16-bit units in 
+     *   <code>data</code>, or if the specified <code>count</code> is 
+     *   negative.
+     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+     */
+    public void replaceData(int offset, 
+                            int count, 
+                            String arg)
+                            throws DOMException;
+
+}
diff --git a/xml/src/main/java/org/w3c/dom/Comment.java b/xml/src/main/java/org/w3c/dom/Comment.java
new file mode 100644
index 0000000..1097921
--- /dev/null
+++ b/xml/src/main/java/org/w3c/dom/Comment.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2000 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.w3c.dom;
+
+/**
+ * This interface inherits from <code>CharacterData</code> and represents the 
+ * content of a comment, i.e., all the characters between the starting '
+ * <code>&lt;!--</code>' and ending '<code>--&gt;</code>'. Note that this is 
+ * the definition of a comment in XML, and, in practice, HTML, although some 
+ * HTML tools may implement the full SGML comment structure.
+ * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>.
+ */
+public interface Comment extends CharacterData {
+}
diff --git a/xml/src/main/java/org/w3c/dom/DOMException.java b/xml/src/main/java/org/w3c/dom/DOMException.java
new file mode 100644
index 0000000..76bac3c
--- /dev/null
+++ b/xml/src/main/java/org/w3c/dom/DOMException.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2000 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.w3c.dom;
+
+//BEGIN android-note
+//Filled some gaps in the documentation and refactored parts of the existing
+//documentation to make the Doclet happy.
+//END android-note
+
+/**
+ * DOM operations only raise exceptions in "exceptional" circumstances, i.e., 
+ * when an operation is impossible to perform (either for logical reasons, 
+ * because data is lost, or because the implementation has become unstable). 
+ * In general, DOM methods return specific error values in ordinary 
+ * processing situations, such as out-of-bound errors when using 
+ * <code>NodeList</code>. 
+ * <p>Implementations should raise other exceptions under other circumstances. 
+ * For example, implementations should raise an implementation-dependent 
+ * exception if a <code>null</code> argument is passed. 
+ * <p>Some languages and object systems do not support the concept of 
+ * exceptions. For such systems, error conditions may be indicated using 
+ * native error reporting mechanisms. For some bindings, for example, 
+ * methods may return error codes similar to those listed in the 
+ * corresponding method descriptions.
+ * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>.
+ */
+public class DOMException extends RuntimeException {
+    /**
+     * Creates a new <code>DOMException</code> with the given error code and
+     * human-readable message.
+     * @param code the error code.
+     * @param message the human-readable message.
+     */
+    public DOMException(short code, String message) {
+       super(message);
+       this.code = code;
+    }
+    /**
+     * Holds the error code of the <code>DOMException</code>.
+     */
+    public short   code;
+    // ExceptionCode
+    /**
+     * If index or size is negative, or greater than the allowed value
+     */
+    public static final short INDEX_SIZE_ERR            = 1;
+    /**
+     * If the specified range of text does not fit into a DOMString
+     */
+    public static final short DOMSTRING_SIZE_ERR        = 2;
+    /**
+     * If any node is inserted somewhere it doesn't belong
+     */
+    public static final short HIERARCHY_REQUEST_ERR     = 3;
+    /**
+     * If a node is used in a different document than the one that created it 
+     * (that doesn't support it)
+     */
+    public static final short WRONG_DOCUMENT_ERR        = 4;
+    /**
+     * If an invalid or illegal character is specified, such as in a name. See 
+     * production 2 in the XML specification for the definition of a legal 
+     * character, and production 5 for the definition of a legal name 
+     * character.
+     */
+    public static final short INVALID_CHARACTER_ERR     = 5;
+    /**
+     * If data is specified for a node which does not support data
+     */
+    public static final short NO_DATA_ALLOWED_ERR       = 6;
+    /**
+     * If an attempt is made to modify an object where modifications are not 
+     * allowed
+     */
+    public static final short NO_MODIFICATION_ALLOWED_ERR = 7;
+    /**
+     * If an attempt is made to reference a node in a context where it does 
+     * not exist
+     */
+    public static final short NOT_FOUND_ERR             = 8;
+    /**
+     * If the implementation does not support the requested type of object or 
+     * operation.
+     */
+    public static final short NOT_SUPPORTED_ERR         = 9;
+    /**
+     * If an attempt is made to add an attribute that is already in use 
+     * elsewhere
+     */
+    public static final short INUSE_ATTRIBUTE_ERR       = 10;
+    /**
+     * If an attempt is made to use an object that is not, or is no longer, 
+     * usable.
+     * @since DOM Level 2
+     */
+    public static final short INVALID_STATE_ERR         = 11;
+    /**
+     * If an invalid or illegal string is specified.
+     * @since DOM Level 2
+     */
+    public static final short SYNTAX_ERR                = 12;
+    /**
+     * If an attempt is made to modify the type of the underlying object.
+     * @since DOM Level 2
+     */
+    public static final short INVALID_MODIFICATION_ERR  = 13;
+    /**
+     * If an attempt is made to create or change an object in a way which is 
+     * incorrect with regard to namespaces.
+     * @since DOM Level 2
+     */
+    public static final short NAMESPACE_ERR             = 14;
+    /**
+     * If a parameter or an operation is not supported by the underlying 
+     * object.
+     * @since DOM Level 2
+     */
+    public static final short INVALID_ACCESS_ERR        = 15;
+
+}
diff --git a/xml/src/main/java/org/w3c/dom/DOMImplementation.java b/xml/src/main/java/org/w3c/dom/DOMImplementation.java
new file mode 100644
index 0000000..dcb19c9
--- /dev/null
+++ b/xml/src/main/java/org/w3c/dom/DOMImplementation.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2000 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.w3c.dom;
+
+// BEGIN android-note
+// Cleaned up @param tags that seemed to be missing spaces between
+// the parameter name and the start of the description.
+// END android-note
+
+/**
+ * The <code>DOMImplementation</code> interface provides a number of methods 
+ * for performing operations that are independent of any particular instance 
+ * of the document object model.
+ * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>.
+ */
+public interface DOMImplementation {
+    /**
+     * Test if the DOM implementation implements a specific feature.
+     * @param feature The name of the feature to test (case-insensitive). The 
+     *   values used by DOM features are defined throughout the DOM Level 2 
+     *   specifications and listed in the  section. The name must be an XML 
+     *   name. To avoid possible conflicts, as a convention, names referring 
+     *   to features defined outside the DOM specification should be made 
+     *   unique by reversing the name of the Internet domain name of the 
+     *   person (or the organization that the person belongs to) who defines 
+     *   the feature, component by component, and using this as a prefix. 
+     *   For instance, the W3C SVG Working Group defines the feature 
+     *   "org.w3c.dom.svg".
+     * @param version This is the version number of the feature to test. In 
+     *   Level 2, the string can be either "2.0" or "1.0". If the version is 
+     *   not specified, supporting any version of the feature causes the 
+     *   method to return <code>true</code>.
+     * @return <code>true</code> if the feature is implemented in the 
+     *   specified version, <code>false</code> otherwise.
+     */
+    public boolean hasFeature(String feature, 
+                              String version);
+
+    /**
+     * Creates an empty <code>DocumentType</code> node. Entity declarations 
+     * and notations are not made available. Entity reference expansions and 
+     * default attribute additions do not occur. It is expected that a 
+     * future version of the DOM will provide a way for populating a 
+     * <code>DocumentType</code>.
+     * <br>HTML-only DOM implementations do not need to implement this method.
+     * @param qualifiedName The qualified name of the document type to be 
+     *   created. 
+     * @param publicId The external subset public identifier.
+     * @param systemId The external subset system identifier.
+     * @return A new <code>DocumentType</code> node with 
+     *   <code>Node.ownerDocument</code> set to <code>null</code>.
+     * @exception DOMException
+     *   INVALID_CHARACTER_ERR: Raised if the specified qualified name 
+     *   contains an illegal character.
+     *   <br>NAMESPACE_ERR: Raised if the <code>qualifiedName</code> is 
+     *   malformed.
+     * @since DOM Level 2
+     */
+    public DocumentType createDocumentType(String qualifiedName, 
+                                           String publicId, 
+                                           String systemId)
+                                           throws DOMException;
+
+    /**
+     * Creates an XML <code>Document</code> object of the specified type with 
+     * its document element. HTML-only DOM implementations do not need to 
+     * implement this method.
+     * @param namespaceURI The namespace URI of the document element to create.
+     * @param qualifiedName The qualified name of the document element to be 
+     *   created.
+     * @param doctype The type of document to be created or <code>null</code>.
+     *   When <code>doctype</code> is not <code>null</code>, its 
+     *   <code>Node.ownerDocument</code> attribute is set to the document 
+     *   being created.
+     * @return A new <code>Document</code> object.
+     * @exception DOMException
+     *   INVALID_CHARACTER_ERR: Raised if the specified qualified name 
+     *   contains an illegal character.
+     *   <br>NAMESPACE_ERR: Raised if the <code>qualifiedName</code> is 
+     *   malformed, if the <code>qualifiedName</code> has a prefix and the 
+     *   <code>namespaceURI</code> is <code>null</code>, or if the 
+     *   <code>qualifiedName</code> has a prefix that is "xml" and the 
+     *   <code>namespaceURI</code> is different from "
+     *   http://www.w3.org/XML/1998/namespace" .
+     *   <br>WRONG_DOCUMENT_ERR: Raised if <code>doctype</code> has already 
+     *   been used with a different document or was created from a different 
+     *   implementation.
+     * @since DOM Level 2
+     */
+    public Document createDocument(String namespaceURI, 
+                                   String qualifiedName, 
+                                   DocumentType doctype)
+                                   throws DOMException;
+
+}
diff --git a/xml/src/main/java/org/w3c/dom/Document.java b/xml/src/main/java/org/w3c/dom/Document.java
new file mode 100644
index 0000000..3beddaa
--- /dev/null
+++ b/xml/src/main/java/org/w3c/dom/Document.java
@@ -0,0 +1,382 @@
+/*
+ * Copyright (c) 2000 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.w3c.dom;
+
+// BEGIN android-note
+// Cleaned up @param tags that seemed to be missing spaces between
+// the parameter name and the start of the description.
+// END android-note
+
+//BEGIN android-note
+//Filled some gaps in the documentation and refactored parts of the existing
+//documentation to make the Doclet happy.
+//END android-note
+
+/**
+ * The <code>Document</code> interface represents the entire HTML or XML 
+ * document. Conceptually, it is the root of the document tree, and provides 
+ * the primary access to the document's data.
+ * <p>Since elements, text nodes, comments, processing instructions, etc. 
+ * cannot exist outside the context of a <code>Document</code>, the 
+ * <code>Document</code> interface also contains the factory methods needed 
+ * to create these objects. The <code>Node</code> objects created have a 
+ * <code>ownerDocument</code> attribute which associates them with the 
+ * <code>Document</code> within whose context they were created.
+ * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>.
+ */
+public interface Document extends Node {
+    /**
+     * The Document Type Declaration (see <code>DocumentType</code>) 
+     * associated with this document. For HTML documents as well as XML 
+     * documents without a document type declaration this returns 
+     * <code>null</code>. The DOM Level 2 does not support editing the 
+     * Document Type Declaration. <code>docType</code> cannot be altered in 
+     * any way, including through the use of methods inherited from the 
+     * <code>Node</code> interface, such as <code>insertNode</code> or 
+     * <code>removeNode</code>.
+     * 
+     * @return the Document Type Declaration associated with this document, if
+     * any.
+     */
+    public DocumentType getDoctype();
+
+    /**
+     * The <code>DOMImplementation</code> object that handles this document. A 
+     * DOM application may use objects from multiple implementations.
+     * 
+     * @return <code>DOMImplementation</code> object that handles this document.
+     */
+    public DOMImplementation getImplementation();
+
+    /**
+     * This is a convenience attribute that allows direct access to the child 
+     * node that is the root element of the document. For HTML documents, 
+     * this is the element with the tagName "HTML".
+     * 
+     * @return the root element of this document. 
+     */
+    public Element getDocumentElement();
+
+    /**
+     * Creates an element of the type specified. Note that the instance 
+     * returned implements the <code>Element</code> interface, so attributes 
+     * can be specified directly on the returned object.
+     * <br>In addition, if there are known attributes with default values, 
+     * <code>Attr</code> nodes representing them are automatically created 
+     * and attached to the element.
+     * <br>To create an element with a qualified name and namespace URI, use 
+     * the <code>createElementNS</code> method.
+     * @param tagName The name of the element type to instantiate. For XML, 
+     *   this is case-sensitive. For HTML, the <code>tagName</code> 
+     *   parameter may be provided in any case, but it must be mapped to the 
+     *   canonical uppercase form by the DOM implementation. 
+     * @return A new <code>Element</code> object with the 
+     *   <code>nodeName</code> attribute set to <code>tagName</code>, and 
+     *   <code>localName</code>, <code>prefix</code>, and 
+     *   <code>namespaceURI</code> set to <code>null</code>.
+     * @exception DOMException
+     *   INVALID_CHARACTER_ERR: Raised if the specified name contains an 
+     *   illegal character.
+     */
+    public Element createElement(String tagName)
+                                 throws DOMException;
+
+    /**
+     * Creates an empty <code>DocumentFragment</code> object. 
+     * @return A new <code>DocumentFragment</code>.
+     */
+    public DocumentFragment createDocumentFragment();
+
+    /**
+     * Creates a <code>Text</code> node given the specified string.
+     * @param data The data for the node.
+     * @return The new <code>Text</code> object.
+     */
+    public Text createTextNode(String data);
+
+    /**
+     * Creates a <code>Comment</code> node given the specified string.
+     * @param data The data for the node.
+     * @return The new <code>Comment</code> object.
+     */
+    public Comment createComment(String data);
+
+    /**
+     * Creates a <code>CDATASection</code> node whose value is the specified 
+     * string.
+     * @param data The data for the <code>CDATASection</code> contents.
+     * @return The new <code>CDATASection</code> object.
+     * @exception DOMException
+     *   NOT_SUPPORTED_ERR: Raised if this document is an HTML document.
+     */
+    public CDATASection createCDATASection(String data)
+                                           throws DOMException;
+
+    /**
+     * Creates a <code>ProcessingInstruction</code> node given the specified 
+     * name and data strings.
+     * @param target The target part of the processing instruction.
+     * @param data The data for the node.
+     * @return The new <code>ProcessingInstruction</code> object.
+     * @exception DOMException
+     *   INVALID_CHARACTER_ERR: Raised if the specified target contains an 
+     *   illegal character.
+     *   <br>NOT_SUPPORTED_ERR: Raised if this document is an HTML document.
+     */
+    public ProcessingInstruction createProcessingInstruction(String target, 
+                                                             String data)
+                                                             throws DOMException;
+
+    /**
+     * Creates an <code>Attr</code> of the given name. Note that the 
+     * <code>Attr</code> instance can then be set on an <code>Element</code> 
+     * using the <code>setAttributeNode</code> method. 
+     * <br>To create an attribute with a qualified name and namespace URI, use 
+     * the <code>createAttributeNS</code> method.
+     * @param name The name of the attribute.
+     * @return A new <code>Attr</code> object with the <code>nodeName</code> 
+     *   attribute set to <code>name</code>, and <code>localName</code>, 
+     *   <code>prefix</code>, and <code>namespaceURI</code> set to 
+     *   <code>null</code>. The value of the attribute is the empty string.
+     * @exception DOMException
+     *   INVALID_CHARACTER_ERR: Raised if the specified name contains an 
+     *   illegal character.
+     */
+    public Attr createAttribute(String name)
+                                throws DOMException;
+
+    /**
+     * Creates an <code>EntityReference</code> object. In addition, if the 
+     * referenced entity is known, the child list of the 
+     * <code>EntityReference</code> node is made the same as that of the 
+     * corresponding <code>Entity</code> node.If any descendant of the 
+     * <code>Entity</code> node has an unbound namespace prefix, the 
+     * corresponding descendant of the created <code>EntityReference</code> 
+     * node is also unbound; (its <code>namespaceURI</code> is 
+     * <code>null</code>). The DOM Level 2 does not support any mechanism to 
+     * resolve namespace prefixes.
+     * @param name The name of the entity to reference. 
+     * @return The new <code>EntityReference</code> object.
+     * @exception DOMException
+     *   INVALID_CHARACTER_ERR: Raised if the specified name contains an 
+     *   illegal character.
+     *   <br>NOT_SUPPORTED_ERR: Raised if this document is an HTML document.
+     */
+    public EntityReference createEntityReference(String name)
+                                                 throws DOMException;
+
+    /**
+     * Returns a <code>NodeList</code> of all the <code>Elements</code> with a 
+     * given tag name in the order in which they are encountered in a 
+     * preorder traversal of the <code>Document</code> tree. 
+     * @param tagname The name of the tag to match on. The special value "*" 
+     *   matches all tags.
+     * @return A new <code>NodeList</code> object containing all the matched 
+     *   <code>Elements</code>.
+     */
+    public NodeList getElementsByTagName(String tagname);
+
+    /**
+     * Imports a node from another document to this document. The returned 
+     * node has no parent; (<code>parentNode</code> is <code>null</code>). 
+     * The source node is not altered or removed from the original document; 
+     * this method creates a new copy of the source node.
+     * <br>For all nodes, importing a node creates a node object owned by the 
+     * importing document, with attribute values identical to the source 
+     * node's <code>nodeName</code> and <code>nodeType</code>, plus the 
+     * attributes related to namespaces (<code>prefix</code>, 
+     * <code>localName</code>, and <code>namespaceURI</code>). As in the 
+     * <code>cloneNode</code> operation on a <code>Node</code>, the source 
+     * node is not altered.
+     * <br>Additional information is copied as appropriate to the 
+     * <code>nodeType</code>, attempting to mirror the behavior expected if 
+     * a fragment of XML or HTML source was copied from one document to 
+     * another, recognizing that the two documents may have different DTDs 
+     * in the XML case. The following list describes the specifics for each 
+     * type of node. 
+     * <dl>
+     * <dt>ATTRIBUTE_NODE</dt>
+     * <dd>The <code>ownerElement</code> attribute 
+     * is set to <code>null</code> and the <code>specified</code> flag is 
+     * set to <code>true</code> on the generated <code>Attr</code>. The 
+     * descendants of the source <code>Attr</code> are recursively imported 
+     * and the resulting nodes reassembled to form the corresponding subtree.
+     * Note that the <code>deep</code> parameter has no effect on 
+     * <code>Attr</code> nodes; they always carry their children with them 
+     * when imported.</dd>
+     * <dt>DOCUMENT_FRAGMENT_NODE</dt>
+     * <dd>If the <code>deep</code> option 
+     * was set to <code>true</code>, the descendants of the source element 
+     * are recursively imported and the resulting nodes reassembled to form 
+     * the corresponding subtree. Otherwise, this simply generates an empty 
+     * <code>DocumentFragment</code>.</dd>
+     * <dt>DOCUMENT_NODE</dt>
+     * <dd><code>Document</code> 
+     * nodes cannot be imported.</dd>
+     * <dt>DOCUMENT_TYPE_NODE</dt>
+     * <dd><code>DocumentType</code> 
+     * nodes cannot be imported.</dd>
+     * <dt>ELEMENT_NODE</dt>
+     * <dd>Specified attribute nodes of the 
+     * source element are imported, and the generated <code>Attr</code> 
+     * nodes are attached to the generated <code>Element</code>. Default 
+     * attributes are not copied, though if the document being imported into 
+     * defines default attributes for this element name, those are assigned. 
+     * If the <code>importNode</code> <code>deep</code> parameter was set to 
+     * <code>true</code>, the descendants of the source element are 
+     * recursively imported and the resulting nodes reassembled to form the 
+     * corresponding subtree.</dd>
+     * <dt>ENTITY_NODE</dt>
+     * <dd><code>Entity</code> nodes can be 
+     * imported, however in the current release of the DOM the 
+     * <code>DocumentType</code> is readonly. Ability to add these imported 
+     * nodes to a <code>DocumentType</code> will be considered for addition 
+     * to a future release of the DOM.On import, the <code>publicId</code>, 
+     * <code>systemId</code>, and <code>notationName</code> attributes are 
+     * copied. If a <code>deep</code> import is requested, the descendants 
+     * of the the source <code>Entity</code> are recursively imported and 
+     * the resulting nodes reassembled to form the corresponding subtree.</dd>
+     * <dt>
+     * ENTITY_REFERENCE_NODE</dt>
+     * <dd>Only the <code>EntityReference</code> itself is 
+     * copied, even if a <code>deep</code> import is requested, since the 
+     * source and destination documents might have defined the entity 
+     * differently. If the document being imported into provides a 
+     * definition for this entity name, its value is assigned.</dd>
+     * <dt>NOTATION_NODE</dt>
+     * <dd>
+     * <code>Notation</code> nodes can be imported, however in the current 
+     * release of the DOM the <code>DocumentType</code> is readonly. Ability 
+     * to add these imported nodes to a <code>DocumentType</code> will be 
+     * considered for addition to a future release of the DOM.On import, the 
+     * <code>publicId</code> and <code>systemId</code> attributes are copied.
+     * Note that the <code>deep</code> parameter has no effect on 
+     * <code>Notation</code> nodes since they never have any children.</dd>
+     * <dt>
+     * PROCESSING_INSTRUCTION_NODE</dt>
+     * <dd>The imported node copies its 
+     * <code>target</code> and <code>data</code> values from those of the 
+     * source node.</dd>
+     * <dt>TEXT_NODE, CDATA_SECTION_NODE, COMMENT_NODE</dt>
+     * <dd>These three 
+     * types of nodes inheriting from <code>CharacterData</code> copy their 
+     * <code>data</code> and <code>length</code> attributes from those of 
+     * the source node.</dd>
+     *  
+     * @param importedNode The node to import.
+     * @param deep If <code>true</code>, recursively import the subtree under 
+     *   the specified node; if <code>false</code>, import only the node 
+     *   itself, as explained above. This has no effect on <code>Attr</code>
+     *   , <code>EntityReference</code>, and <code>Notation</code> nodes.
+     * @return The imported node that belongs to this <code>Document</code>.
+     * @exception DOMException
+     *   NOT_SUPPORTED_ERR: Raised if the type of node being imported is not 
+     *   supported.
+     * @since DOM Level 2
+     */
+    public Node importNode(Node importedNode, 
+                           boolean deep)
+                           throws DOMException;
+
+    /**
+     * Creates an element of the given qualified name and namespace URI. 
+     * HTML-only DOM implementations do not need to implement this method.
+     * @param namespaceURI The namespace URI of the element to create.
+     * @param qualifiedName The qualified name of the element type to 
+     *   instantiate.
+     * @return A new <code>Element</code> object with the following 
+     *   attributes:AttributeValue<code>Node.nodeName</code>
+     *   <code>qualifiedName</code><code>Node.namespaceURI</code>
+     *   <code>namespaceURI</code><code>Node.prefix</code>prefix, extracted 
+     *   from <code>qualifiedName</code>, or <code>null</code> if there is 
+     *   no prefix<code>Node.localName</code>local name, extracted from 
+     *   <code>qualifiedName</code><code>Element.tagName</code>
+     *   <code>qualifiedName</code>
+     * @exception DOMException
+     *   INVALID_CHARACTER_ERR: Raised if the specified qualified name 
+     *   contains an illegal character.
+     *   <br>NAMESPACE_ERR: Raised if the <code>qualifiedName</code> is 
+     *   malformed, if the <code>qualifiedName</code> has a prefix and the 
+     *   <code>namespaceURI</code> is <code>null</code>, or if the 
+     *   <code>qualifiedName</code> has a prefix that is "xml" and the 
+     *   <code>namespaceURI</code> is different from "
+     *   http://www.w3.org/XML/1998/namespace" .
+     * @since DOM Level 2
+     */
+    public Element createElementNS(String namespaceURI, 
+                                   String qualifiedName)
+                                   throws DOMException;
+
+    /**
+     * Creates an attribute of the given qualified name and namespace URI. 
+     * HTML-only DOM implementations do not need to implement this method.
+     * @param namespaceURI The namespace URI of the attribute to create.
+     * @param qualifiedName The qualified name of the attribute to instantiate.
+     * @return A new <code>Attr</code> object with the following attributes:
+     *   AttributeValue<code>Node.nodeName</code>qualifiedName
+     *   <code>Node.namespaceURI</code><code>namespaceURI</code>
+     *   <code>Node.prefix</code>prefix, extracted from 
+     *   <code>qualifiedName</code>, or <code>null</code> if there is no 
+     *   prefix<code>Node.localName</code>local name, extracted from 
+     *   <code>qualifiedName</code><code>Attr.name</code>
+     *   <code>qualifiedName</code><code>Node.nodeValue</code>the empty 
+     *   string
+     * @exception DOMException
+     *   INVALID_CHARACTER_ERR: Raised if the specified qualified name 
+     *   contains an illegal character.
+     *   <br>NAMESPACE_ERR: Raised if the <code>qualifiedName</code> is 
+     *   malformed, if the <code>qualifiedName</code> has a prefix and the 
+     *   <code>namespaceURI</code> is <code>null</code>, if the 
+     *   <code>qualifiedName</code> has a prefix that is "xml" and the 
+     *   <code>namespaceURI</code> is different from "
+     *   http://www.w3.org/XML/1998/namespace", or if the 
+     *   <code>qualifiedName</code> is "xmlns" and the 
+     *   <code>namespaceURI</code> is different from "
+     *   http://www.w3.org/2000/xmlns/".
+     * @since DOM Level 2
+     */
+    public Attr createAttributeNS(String namespaceURI, 
+                                  String qualifiedName)
+                                  throws DOMException;
+
+    /**
+     * Returns a <code>NodeList</code> of all the <code>Elements</code> with a 
+     * given local name and namespace URI in the order in which they are 
+     * encountered in a preorder traversal of the <code>Document</code> tree.
+     * @param namespaceURI The namespace URI of the elements to match on. The 
+     *   special value "*" matches all namespaces.
+     * @param localName The local name of the elements to match on. The 
+     *   special value "*" matches all local names.
+     * @return A new <code>NodeList</code> object containing all the matched 
+     *   <code>Elements</code>.
+     * @since DOM Level 2
+     */
+    public NodeList getElementsByTagNameNS(String namespaceURI, 
+                                           String localName);
+
+    /**
+     * Returns the <code>Element</code> whose <code>ID</code> is given by 
+     * <code>elementId</code>. If no such element exists, returns 
+     * <code>null</code>. Behavior is not defined if more than one element 
+     * has this <code>ID</code>. The DOM implementation must have 
+     * information that says which attributes are of type ID. Attributes 
+     * with the name "ID" are not of type ID unless so defined. 
+     * Implementations that do not know whether attributes are of type ID or 
+     * not are expected to return <code>null</code>.
+     * @param elementId The unique <code>id</code> value for an element.
+     * @return The matching element.
+     * @since DOM Level 2
+     */
+    public Element getElementById(String elementId);
+
+}
diff --git a/xml/src/main/java/org/w3c/dom/DocumentFragment.java b/xml/src/main/java/org/w3c/dom/DocumentFragment.java
new file mode 100644
index 0000000..6ade30c
--- /dev/null
+++ b/xml/src/main/java/org/w3c/dom/DocumentFragment.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2000 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.w3c.dom;
+
+/**
+ * <code>DocumentFragment</code> is a "lightweight" or "minimal" 
+ * <code>Document</code> object. It is very common to want to be able to 
+ * extract a portion of a document's tree or to create a new fragment of a 
+ * document. Imagine implementing a user command like cut or rearranging a 
+ * document by moving fragments around. It is desirable to have an object 
+ * which can hold such fragments and it is quite natural to use a Node for 
+ * this purpose. While it is true that a <code>Document</code> object could 
+ * fulfill this role, a <code>Document</code> object can potentially be a 
+ * heavyweight object, depending on the underlying implementation. What is 
+ * really needed for this is a very lightweight object. 
+ * <code>DocumentFragment</code> is such an object.
+ * <p>Furthermore, various operations -- such as inserting nodes as children 
+ * of another <code>Node</code> -- may take <code>DocumentFragment</code> 
+ * objects as arguments; this results in all the child nodes of the 
+ * <code>DocumentFragment</code> being moved to the child list of this node.
+ * <p>The children of a <code>DocumentFragment</code> node are zero or more 
+ * nodes representing the tops of any sub-trees defining the structure of 
+ * the document. <code>DocumentFragment</code> nodes do not need to be 
+ * well-formed XML documents (although they do need to follow the rules 
+ * imposed upon well-formed XML parsed entities, which can have multiple top 
+ * nodes). For example, a <code>DocumentFragment</code> might have only one 
+ * child and that child node could be a <code>Text</code> node. Such a 
+ * structure model represents neither an HTML document nor a well-formed XML 
+ * document.
+ * <p>When a <code>DocumentFragment</code> is inserted into a 
+ * <code>Document</code> (or indeed any other <code>Node</code> that may 
+ * take children) the children of the <code>DocumentFragment</code> and not 
+ * the <code>DocumentFragment</code> itself are inserted into the 
+ * <code>Node</code>. This makes the <code>DocumentFragment</code> very 
+ * useful when the user wishes to create nodes that are siblings; the 
+ * <code>DocumentFragment</code> acts as the parent of these nodes so that 
+ * the user can use the standard methods from the <code>Node</code> 
+ * interface, such as <code>insertBefore</code> and <code>appendChild</code>.
+ * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>.
+ */
+public interface DocumentFragment extends Node {
+}
diff --git a/xml/src/main/java/org/w3c/dom/DocumentType.java b/xml/src/main/java/org/w3c/dom/DocumentType.java
new file mode 100644
index 0000000..685c073
--- /dev/null
+++ b/xml/src/main/java/org/w3c/dom/DocumentType.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2000 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.w3c.dom;
+
+//BEGIN android-note
+//Filled some gaps in the documentation and refactored parts of the existing
+//documentation to make the Doclet happy.
+//END android-note
+
+/**
+ * Each <code>Document</code> has a <code>doctype</code> attribute whose value 
+ * is either <code>null</code> or a <code>DocumentType</code> object. The 
+ * <code>DocumentType</code> interface in the DOM Core provides an interface 
+ * to the list of entities that are defined for the document, and little 
+ * else because the effect of namespaces and the various XML schema efforts 
+ * on DTD representation are not clearly understood as of this writing.
+ * <p>The DOM Level 2 doesn't support editing <code>DocumentType</code> nodes.
+ * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>.
+ */
+public interface DocumentType extends Node {
+    /**
+     * The name of DTD; i.e., the name immediately following the 
+     * <code>DOCTYPE</code> keyword.
+     * 
+     * @return the name of the DTD.
+     */
+    public String getName();
+
+    /**
+     * A <code>NamedNodeMap</code> containing the general entities, both 
+     * external and internal, declared in the DTD. Parameter entities are 
+     * not contained. Duplicates are discarded. For example in: 
+     * <pre>&lt;!DOCTYPE 
+     * ex SYSTEM "ex.dtd" [ &lt;!ENTITY foo "foo"&gt; &lt;!ENTITY bar 
+     * "bar"&gt; &lt;!ENTITY bar "bar2"&gt; &lt;!ENTITY % baz "baz"&gt; 
+     * ]&gt; &lt;ex/&gt;</pre>
+     *  the interface provides access to <code>foo</code> 
+     * and the first declaration of <code>bar</code> but not the second 
+     * declaration of <code>bar</code> or <code>baz</code>. Every node in 
+     * this map also implements the <code>Entity</code> interface.
+     * <br>The DOM Level 2 does not support editing entities, therefore 
+     * <code>entities</code> cannot be altered in any way.
+     * 
+     * @return the entities declared in this DTD.
+     */
+    public NamedNodeMap getEntities();
+
+    /**
+     * A <code>NamedNodeMap</code> containing the notations declared in the 
+     * DTD. Duplicates are discarded. Every node in this map also implements 
+     * the <code>Notation</code> interface.
+     * <br>The DOM Level 2 does not support editing notations, therefore 
+     * <code>notations</code> cannot be altered in any way.
+     * 
+     * @return the notations declared in this DTD.
+     */
+    public NamedNodeMap getNotations();
+
+    /**
+     * The public identifier of the external subset.
+     * 
+     * @return the public identifier.
+     * 
+     * @since DOM Level 2
+     */
+    public String getPublicId();
+
+    /**
+     * The system identifier of the external subset.
+     * 
+     * @return the system identifier.
+     * 
+     * @since DOM Level 2
+     */
+    public String getSystemId();
+
+    /**
+     * The internal subset as a string. The actual content returned depends on 
+     * how much information is available to the implementation. This may 
+     * vary depending on various parameters, including the XML processor 
+     * used to build the document.
+     * 
+     * @return the internal subset.
+     * 
+     * @since DOM Level 2
+     */
+    public String getInternalSubset();
+
+}
diff --git a/xml/src/main/java/org/w3c/dom/Element.java b/xml/src/main/java/org/w3c/dom/Element.java
new file mode 100644
index 0000000..72e3478
--- /dev/null
+++ b/xml/src/main/java/org/w3c/dom/Element.java
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2000 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.w3c.dom;
+
+// BEGIN android-note
+// Cleaned up @param tags that seemed to be missing spaces between
+// the parameter name and the start of the description.
+// END android-note
+
+//BEGIN android-note
+//Filled some gaps in the documentation and refactored parts of the existing
+//documentation to make the Doclet happy.
+//END android-note
+
+/**
+ * The <code>Element</code> interface represents an element in an HTML or XML 
+ * document. Elements may have attributes associated with them; since the 
+ * <code>Element</code> interface inherits from <code>Node</code>, the 
+ * generic <code>Node</code> interface attribute <code>attributes</code> may 
+ * be used to retrieve the set of all attributes for an element. There are 
+ * methods on the <code>Element</code> interface to retrieve either an 
+ * <code>Attr</code> object by name or an attribute value by name. In XML, 
+ * where an attribute value may contain entity references, an 
+ * <code>Attr</code> object should be retrieved to examine the possibly 
+ * fairly complex sub-tree representing the attribute value. On the other 
+ * hand, in HTML, where all attributes have simple string values, methods to 
+ * directly access an attribute value can safely be used as a convenience.In 
+ * DOM Level 2, the method <code>normalize</code> is inherited from the 
+ * <code>Node</code> interface where it was moved.
+ * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>.
+ */
+public interface Element extends Node {
+    /**
+     * The name of the element. For example, in: 
+     * <pre> &lt;elementExample 
+     * id="demo"&gt; ... &lt;/elementExample&gt; , </pre>
+     *  <code>tagName</code> has 
+     * the value <code>"elementExample"</code>. Note that this is 
+     * case-preserving in XML, as are all of the operations of the DOM. The 
+     * HTML DOM returns the <code>tagName</code> of an HTML element in the 
+     * canonical uppercase form, regardless of the case in the source HTML 
+     * document.
+     * 
+     * @return the name of the element.
+     */
+    public String getTagName();
+
+    /**
+     * Retrieves an attribute value by name.
+     * @param name The name of the attribute to retrieve.
+     * @return The <code>Attr</code> value as a string, or the empty string 
+     *   if that attribute does not have a specified or default value.
+     */
+    public String getAttribute(String name);
+
+    /**
+     * Adds a new attribute. If an attribute with that name is already present 
+     * in the element, its value is changed to be that of the value 
+     * parameter. This value is a simple string; it is not parsed as it is 
+     * being set. So any markup (such as syntax to be recognized as an 
+     * entity reference) is treated as literal text, and needs to be 
+     * appropriately escaped by the implementation when it is written out. 
+     * In order to assign an attribute value that contains entity 
+     * references, the user must create an <code>Attr</code> node plus any 
+     * <code>Text</code> and <code>EntityReference</code> nodes, build the 
+     * appropriate subtree, and use <code>setAttributeNode</code> to assign 
+     * it as the value of an attribute.
+     * <br>To set an attribute with a qualified name and namespace URI, use 
+     * the <code>setAttributeNS</code> method.
+     * @param name The name of the attribute to create or alter.
+     * @param value Value to set in string form.
+     * @exception DOMException
+     *   INVALID_CHARACTER_ERR: Raised if the specified name contains an 
+     *   illegal character.
+     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+     */
+    public void setAttribute(String name, 
+                             String value)
+                             throws DOMException;
+
+    /**
+     * Removes an attribute by name. If the removed attribute is known to have 
+     * a default value, an attribute immediately appears containing the 
+     * default value as well as the corresponding namespace URI, local name, 
+     * and prefix when applicable.
+     * <br>To remove an attribute by local name and namespace URI, use the 
+     * <code>removeAttributeNS</code> method.
+     * @param name The name of the attribute to remove.
+     * @exception DOMException
+     *   NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+     */
+    public void removeAttribute(String name)
+                                throws DOMException;
+
+    /**
+     * Retrieves an attribute node by name.
+     * <br>To retrieve an attribute node by qualified name and namespace URI, 
+     * use the <code>getAttributeNodeNS</code> method.
+     * @param name The name (<code>nodeName</code>) of the attribute to 
+     *   retrieve.
+     * @return The <code>Attr</code> node with the specified name (
+     *   <code>nodeName</code>) or <code>null</code> if there is no such 
+     *   attribute.
+     */
+    public Attr getAttributeNode(String name);
+
+    /**
+     * Adds a new attribute node. If an attribute with that name (
+     * <code>nodeName</code>) is already present in the element, it is 
+     * replaced by the new one.
+     * <br>To add a new attribute node with a qualified name and namespace 
+     * URI, use the <code>setAttributeNodeNS</code> method.
+     * @param newAttr The <code>Attr</code> node to add to the attribute list.
+     * @return If the <code>newAttr</code> attribute replaces an existing 
+     *   attribute, the replaced <code>Attr</code> node is returned, 
+     *   otherwise <code>null</code> is returned.
+     * @exception DOMException
+     *   WRONG_DOCUMENT_ERR: Raised if <code>newAttr</code> was created from a 
+     *   different document than the one that created the element.
+     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+     *   <br>INUSE_ATTRIBUTE_ERR: Raised if <code>newAttr</code> is already an 
+     *   attribute of another <code>Element</code> object. The DOM user must 
+     *   explicitly clone <code>Attr</code> nodes to re-use them in other 
+     *   elements.
+     */
+    public Attr setAttributeNode(Attr newAttr)
+                                 throws DOMException;
+
+    /**
+     * Removes the specified attribute node. If the removed <code>Attr</code> 
+     * has a default value it is immediately replaced. The replacing 
+     * attribute has the same namespace URI and local name, as well as the 
+     * original prefix, when applicable.
+     * @param oldAttr The <code>Attr</code> node to remove from the attribute 
+     *   list.
+     * @return The <code>Attr</code> node that was removed.
+     * @exception DOMException
+     *   NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+     *   <br>NOT_FOUND_ERR: Raised if <code>oldAttr</code> is not an attribute 
+     *   of the element.
+     */
+    public Attr removeAttributeNode(Attr oldAttr)
+                                    throws DOMException;
+
+    /**
+     * Returns a <code>NodeList</code> of all descendant <code>Elements</code> 
+     * with a given tag name, in the order in which they are encountered in 
+     * a preorder traversal of this <code>Element</code> tree.
+     * @param name The name of the tag to match on. The special value "*" 
+     *   matches all tags.
+     * @return A list of matching <code>Element</code> nodes.
+     */
+    public NodeList getElementsByTagName(String name);
+
+    /**
+     * Retrieves an attribute value by local name and namespace URI. HTML-only 
+     * DOM implementations do not need to implement this method.
+     * @param namespaceURI The namespace URI of the attribute to retrieve.
+     * @param localName The local name of the attribute to retrieve.
+     * @return The <code>Attr</code> value as a string, or the empty string 
+     *   if that attribute does not have a specified or default value.
+     * @since DOM Level 2
+     */
+    public String getAttributeNS(String namespaceURI, 
+                                 String localName);
+
+    /**
+     * Adds a new attribute. If an attribute with the same local name and 
+     * namespace URI is already present on the element, its prefix is 
+     * changed to be the prefix part of the <code>qualifiedName</code>, and 
+     * its value is changed to be the <code>value</code> parameter. This 
+     * value is a simple string; it is not parsed as it is being set. So any 
+     * markup (such as syntax to be recognized as an entity reference) is 
+     * treated as literal text, and needs to be appropriately escaped by the 
+     * implementation when it is written out. In order to assign an 
+     * attribute value that contains entity references, the user must create 
+     * an <code>Attr</code> node plus any <code>Text</code> and 
+     * <code>EntityReference</code> nodes, build the appropriate subtree, 
+     * and use <code>setAttributeNodeNS</code> or 
+     * <code>setAttributeNode</code> to assign it as the value of an 
+     * attribute.
+     * <br>HTML-only DOM implementations do not need to implement this method.
+     * @param namespaceURI The namespace URI of the attribute to create or 
+     *   alter.
+     * @param qualifiedName The qualified name of the attribute to create or 
+     *   alter.
+     * @param value The value to set in string form.
+     * @exception DOMException
+     *   INVALID_CHARACTER_ERR: Raised if the specified qualified name 
+     *   contains an illegal character.
+     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+     *   <br>NAMESPACE_ERR: Raised if the <code>qualifiedName</code> is 
+     *   malformed, if the <code>qualifiedName</code> has a prefix and the 
+     *   <code>namespaceURI</code> is <code>null</code>, if the 
+     *   <code>qualifiedName</code> has a prefix that is "xml" and the 
+     *   <code>namespaceURI</code> is different from "
+     *   http://www.w3.org/XML/1998/namespace", or if the 
+     *   <code>qualifiedName</code> is "xmlns" and the 
+     *   <code>namespaceURI</code> is different from "
+     *   http://www.w3.org/2000/xmlns/".
+     * @since DOM Level 2
+     */
+    public void setAttributeNS(String namespaceURI, 
+                               String qualifiedName, 
+                               String value)
+                               throws DOMException;
+
+    /**
+     * Removes an attribute by local name and namespace URI. If the removed 
+     * attribute has a default value it is immediately replaced. The 
+     * replacing attribute has the same namespace URI and local name, as 
+     * well as the original prefix.
+     * <br>HTML-only DOM implementations do not need to implement this method.
+     * @param namespaceURI The namespace URI of the attribute to remove.
+     * @param localName The local name of the attribute to remove.
+     * @exception DOMException
+     *   NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+     * @since DOM Level 2
+     */
+    public void removeAttributeNS(String namespaceURI, 
+                                  String localName)
+                                  throws DOMException;
+
+    /**
+     * Retrieves an <code>Attr</code> node by local name and namespace URI. 
+     * HTML-only DOM implementations do not need to implement this method.
+     * @param namespaceURI The namespace URI of the attribute to retrieve.
+     * @param localName The local name of the attribute to retrieve.
+     * @return The <code>Attr</code> node with the specified attribute local 
+     *   name and namespace URI or <code>null</code> if there is no such 
+     *   attribute.
+     * @since DOM Level 2
+     */
+    public Attr getAttributeNodeNS(String namespaceURI, 
+                                   String localName);
+
+    /**
+     * Adds a new attribute. If an attribute with that local name and that 
+     * namespace URI is already present in the element, it is replaced by 
+     * the new one.
+     * <br>HTML-only DOM implementations do not need to implement this method.
+     * @param newAttr The <code>Attr</code> node to add to the attribute list.
+     * @return If the <code>newAttr</code> attribute replaces an existing 
+     *   attribute with the same local name and namespace URI, the replaced 
+     *   <code>Attr</code> node is returned, otherwise <code>null</code> is 
+     *   returned.
+     * @exception DOMException
+     *   WRONG_DOCUMENT_ERR: Raised if <code>newAttr</code> was created from a 
+     *   different document than the one that created the element.
+     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+     *   <br>INUSE_ATTRIBUTE_ERR: Raised if <code>newAttr</code> is already an 
+     *   attribute of another <code>Element</code> object. The DOM user must 
+     *   explicitly clone <code>Attr</code> nodes to re-use them in other 
+     *   elements.
+     * @since DOM Level 2
+     */
+    public Attr setAttributeNodeNS(Attr newAttr)
+                                   throws DOMException;
+
+    /**
+     * Returns a <code>NodeList</code> of all the descendant 
+     * <code>Elements</code> with a given local name and namespace URI in 
+     * the order in which they are encountered in a preorder traversal of 
+     * this <code>Element</code> tree.
+     * <br>HTML-only DOM implementations do not need to implement this method.
+     * @param namespaceURI The namespace URI of the elements to match on. The 
+     *   special value "*" matches all namespaces.
+     * @param localName The local name of the elements to match on. The 
+     *   special value "*" matches all local names.
+     * @return A new <code>NodeList</code> object containing all the matched 
+     *   <code>Elements</code>.
+     * @since DOM Level 2
+     */
+    public NodeList getElementsByTagNameNS(String namespaceURI, 
+                                           String localName);
+
+    /**
+     * Returns <code>true</code> when an attribute with a given name is 
+     * specified on this element or has a default value, <code>false</code> 
+     * otherwise.
+     * @param name The name of the attribute to look for.
+     * @return <code>true</code> if an attribute with the given name is 
+     *   specified on this element or has a default value, <code>false</code>
+     *    otherwise.
+     * @since DOM Level 2
+     */
+    public boolean hasAttribute(String name);
+
+    /**
+     * Returns <code>true</code> when an attribute with a given local name and 
+     * namespace URI is specified on this element or has a default value, 
+     * <code>false</code> otherwise. HTML-only DOM implementations do not 
+     * need to implement this method.
+     * @param namespaceURI The namespace URI of the attribute to look for.
+     * @param localName The local name of the attribute to look for.
+     * @return <code>true</code> if an attribute with the given local name 
+     *   and namespace URI is specified or has a default value on this 
+     *   element, <code>false</code> otherwise.
+     * @since DOM Level 2
+     */
+    public boolean hasAttributeNS(String namespaceURI, 
+                                  String localName);
+
+}
diff --git a/xml/src/main/java/org/w3c/dom/Entity.java b/xml/src/main/java/org/w3c/dom/Entity.java
new file mode 100644
index 0000000..5b09608
--- /dev/null
+++ b/xml/src/main/java/org/w3c/dom/Entity.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2000 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.w3c.dom;
+
+//BEGIN android-note
+//Filled some gaps in the documentation and refactored parts of the existing
+//documentation to make the Doclet happy.
+//END android-note
+
+/**
+ * This interface represents an entity, either parsed or unparsed, in an XML 
+ * document. Note that this models the entity itself not the entity 
+ * declaration. <code>Entity</code> declaration modeling has been left for a 
+ * later Level of the DOM specification.
+ * <p>The <code>nodeName</code> attribute that is inherited from 
+ * <code>Node</code> contains the name of the entity.
+ * <p>An XML processor may choose to completely expand entities before the 
+ * structure model is passed to the DOM; in this case there will be no 
+ * <code>EntityReference</code> nodes in the document tree.
+ * <p>XML does not mandate that a non-validating XML processor read and 
+ * process entity declarations made in the external subset or declared in 
+ * external parameter entities. This means that parsed entities declared in 
+ * the external subset need not be expanded by some classes of applications, 
+ * and that the replacement value of the entity may not be available. When 
+ * the replacement value is available, the corresponding <code>Entity</code> 
+ * node's child list represents the structure of that replacement text. 
+ * Otherwise, the child list is empty.
+ * <p>The DOM Level 2 does not support editing <code>Entity</code> nodes; if a 
+ * user wants to make changes to the contents of an <code>Entity</code>, 
+ * every related <code>EntityReference</code> node has to be replaced in the 
+ * structure model by a clone of the <code>Entity</code>'s contents, and 
+ * then the desired changes must be made to each of those clones instead. 
+ * <code>Entity</code> nodes and all their descendants are readonly.
+ * <p>An <code>Entity</code> node does not have any parent.If the entity 
+ * contains an unbound namespace prefix, the <code>namespaceURI</code> of 
+ * the corresponding node in the <code>Entity</code> node subtree is 
+ * <code>null</code>. The same is true for <code>EntityReference</code> 
+ * nodes that refer to this entity, when they are created using the 
+ * <code>createEntityReference</code> method of the <code>Document</code> 
+ * interface. The DOM Level 2 does not support any mechanism to resolve 
+ * namespace prefixes.
+ * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>.
+ */
+public interface Entity extends Node {
+    /**
+     * The public identifier associated with the entity, if specified. If the 
+     * public identifier was not specified, this is <code>null</code>.
+     * 
+     * @return the public identifier of the entity or <code>null</code>, if the
+     * entity does not have a public identifier.
+     */
+    public String getPublicId();
+
+    /**
+     * The system identifier associated with the entity, if specified. If the 
+     * system identifier was not specified, this is <code>null</code>.
+     * 
+     * @return the system identifier of the entity or <code>null</code>, if the
+     * entity does not have a system identifier.
+     */
+    public String getSystemId();
+
+    /**
+     * For unparsed entities, the name of the notation for the entity. For 
+     * parsed entities, this is <code>null</code>. 
+     * 
+     * @return the notation name of the entity or <code>null</code>, if the
+     * entity is parsed.
+     */
+    public String getNotationName();
+
+}
diff --git a/xml/src/main/java/org/w3c/dom/EntityReference.java b/xml/src/main/java/org/w3c/dom/EntityReference.java
new file mode 100644
index 0000000..ff3cf9d
--- /dev/null
+++ b/xml/src/main/java/org/w3c/dom/EntityReference.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2000 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.w3c.dom;
+
+/**
+ * <code>EntityReference</code> objects may be inserted into the structure 
+ * model when an entity reference is in the source document, or when the 
+ * user wishes to insert an entity reference. Note that character references 
+ * and references to predefined entities are considered to be expanded by 
+ * the HTML or XML processor so that characters are represented by their 
+ * Unicode equivalent rather than by an entity reference. Moreover, the XML 
+ * processor may completely expand references to entities while building the 
+ * structure model, instead of providing <code>EntityReference</code> 
+ * objects. If it does provide such objects, then for a given 
+ * <code>EntityReference</code> node, it may be that there is no 
+ * <code>Entity</code> node representing the referenced entity. If such an 
+ * <code>Entity</code> exists, then the subtree of the 
+ * <code>EntityReference</code> node is in general a copy of the 
+ * <code>Entity</code> node subtree. However, this may not be true when an 
+ * entity contains an unbound namespace prefix. In such a case, because the 
+ * namespace prefix resolution depends on where the entity reference is, the 
+ * descendants of the <code>EntityReference</code> node may be bound to 
+ * different namespace URIs.
+ * <p>As for <code>Entity</code> nodes, <code>EntityReference</code> nodes and 
+ * all their descendants are readonly.
+ * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>.
+ */
+public interface EntityReference extends Node {
+}
diff --git a/xml/src/main/java/org/w3c/dom/NamedNodeMap.java b/xml/src/main/java/org/w3c/dom/NamedNodeMap.java
new file mode 100644
index 0000000..a6cbf09
--- /dev/null
+++ b/xml/src/main/java/org/w3c/dom/NamedNodeMap.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2000 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.w3c.dom;
+
+// BEGIN android-note
+// Cleaned up @param tags that seemed to be missing spaces between
+// the parameter name and the start of the description.
+// END android-note
+
+//BEGIN android-note
+//Filled some gaps in the documentation and refactored parts of the existing
+//documentation to make the Doclet happy.
+//END android-note
+
+/**
+ * Objects implementing the <code>NamedNodeMap</code> interface are used to 
+ * represent collections of nodes that can be accessed by name. Note that 
+ * <code>NamedNodeMap</code> does not inherit from <code>NodeList</code>; 
+ * <code>NamedNodeMaps</code> are not maintained in any particular order. 
+ * Objects contained in an object implementing <code>NamedNodeMap</code> may 
+ * also be accessed by an ordinal index, but this is simply to allow 
+ * convenient enumeration of the contents of a <code>NamedNodeMap</code>, 
+ * and does not imply that the DOM specifies an order to these Nodes. 
+ * <p><code>NamedNodeMap</code> objects in the DOM are live.
+ * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>.
+ */
+public interface NamedNodeMap {
+    /**
+     * Retrieves a node specified by name.
+     * @param name The <code>nodeName</code> of a node to retrieve.
+     * @return A <code>Node</code> (of any type) with the specified 
+     *   <code>nodeName</code>, or <code>null</code> if it does not identify 
+     *   any node in this map.
+     */
+    public Node getNamedItem(String name);
+
+    /**
+     * Adds a node using its <code>nodeName</code> attribute. If a node with 
+     * that name is already present in this map, it is replaced by the new 
+     * one.
+     * <br>As the <code>nodeName</code> attribute is used to derive the name 
+     * which the node must be stored under, multiple nodes of certain types 
+     * (those that have a "special" string value) cannot be stored as the 
+     * names would clash. This is seen as preferable to allowing nodes to be 
+     * aliased.
+     * @param arg A node to store in this map. The node will later be 
+     *   accessible using the value of its <code>nodeName</code> attribute.
+     * @return If the new <code>Node</code> replaces an existing node the 
+     *   replaced <code>Node</code> is returned, otherwise <code>null</code> 
+     *   is returned.
+     * @exception DOMException
+     *   WRONG_DOCUMENT_ERR: Raised if <code>arg</code> was created from a 
+     *   different document than the one that created this map.
+     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly.
+     *   <br>INUSE_ATTRIBUTE_ERR: Raised if <code>arg</code> is an 
+     *   <code>Attr</code> that is already an attribute of another 
+     *   <code>Element</code> object. The DOM user must explicitly clone 
+     *   <code>Attr</code> nodes to re-use them in other elements.
+     */
+    public Node setNamedItem(Node arg)
+                             throws DOMException;
+
+    /**
+     * Removes a node specified by name. When this map contains the attributes 
+     * attached to an element, if the removed attribute is known to have a 
+     * default value, an attribute immediately appears containing the 
+     * default value as well as the corresponding namespace URI, local name, 
+     * and prefix when applicable.
+     * @param name The <code>nodeName</code> of the node to remove.
+     * @return The node removed from this map if a node with such a name 
+     *   exists.
+     * @exception DOMException
+     *   NOT_FOUND_ERR: Raised if there is no node named <code>name</code> in 
+     *   this map.
+     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly.
+     */
+    public Node removeNamedItem(String name)
+                                throws DOMException;
+
+    /**
+     * Returns the <code>index</code>th item in the map. If <code>index</code> 
+     * is greater than or equal to the number of nodes in this map, this 
+     * returns <code>null</code>.
+     * @param index Index into this map.
+     * @return The node at the <code>index</code>th position in the map, or 
+     *   <code>null</code> if that is not a valid index.
+     */
+    public Node item(int index);
+
+    /**
+     * The number of nodes in this map. The range of valid child node indices 
+     * is <code>0</code> to <code>length-1</code> inclusive.
+     * 
+     * @return the length of the map.
+     */
+    public int getLength();
+
+    /**
+     * Retrieves a node specified by local name and namespace URI. HTML-only 
+     * DOM implementations do not need to implement this method.
+     * @param namespaceURI The namespace URI of the node to retrieve.
+     * @param localName The local name of the node to retrieve.
+     * @return A <code>Node</code> (of any type) with the specified local 
+     *   name and namespace URI, or <code>null</code> if they do not 
+     *   identify any node in this map.
+     * @since DOM Level 2
+     */
+    public Node getNamedItemNS(String namespaceURI, 
+                               String localName);
+
+    /**
+     * Adds a node using its <code>namespaceURI</code> and 
+     * <code>localName</code>. If a node with that namespace URI and that 
+     * local name is already present in this map, it is replaced by the new 
+     * one.
+     * <br>HTML-only DOM implementations do not need to implement this method.
+     * @param arg A node to store in this map. The node will later be 
+     *   accessible using the value of its <code>namespaceURI</code> and 
+     *   <code>localName</code> attributes.
+     * @return If the new <code>Node</code> replaces an existing node the 
+     *   replaced <code>Node</code> is returned, otherwise <code>null</code> 
+     *   is returned.
+     * @exception DOMException
+     *   WRONG_DOCUMENT_ERR: Raised if <code>arg</code> was created from a 
+     *   different document than the one that created this map.
+     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly.
+     *   <br>INUSE_ATTRIBUTE_ERR: Raised if <code>arg</code> is an 
+     *   <code>Attr</code> that is already an attribute of another 
+     *   <code>Element</code> object. The DOM user must explicitly clone 
+     *   <code>Attr</code> nodes to re-use them in other elements.
+     * @since DOM Level 2
+     */
+    public Node setNamedItemNS(Node arg)
+                               throws DOMException;
+
+    /**
+     * Removes a node specified by local name and namespace URI. A removed 
+     * attribute may be known to have a default value when this map contains 
+     * the attributes attached to an element, as returned by the attributes 
+     * attribute of the <code>Node</code> interface. If so, an attribute 
+     * immediately appears containing the default value as well as the 
+     * corresponding namespace URI, local name, and prefix when applicable.
+     * <br>HTML-only DOM implementations do not need to implement this method.
+     * @param namespaceURI The namespace URI of the node to remove.
+     * @param localName The local name of the node to remove.
+     * @return The node removed from this map if a node with such a local 
+     *   name and namespace URI exists.
+     * @exception DOMException
+     *   NOT_FOUND_ERR: Raised if there is no node with the specified 
+     *   <code>namespaceURI</code> and <code>localName</code> in this map.
+     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly.
+     * @since DOM Level 2
+     */
+    public Node removeNamedItemNS(String namespaceURI, 
+                                  String localName)
+                                  throws DOMException;
+
+}
diff --git a/xml/src/main/java/org/w3c/dom/Node.java b/xml/src/main/java/org/w3c/dom/Node.java
new file mode 100644
index 0000000..c91c46d
--- /dev/null
+++ b/xml/src/main/java/org/w3c/dom/Node.java
@@ -0,0 +1,454 @@
+/*
+ * Copyright (c) 2000 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.w3c.dom;
+
+// BEGIN android-note
+// Cleaned up @param tags that seemed to be missing spaces between
+// the parameter name and the start of the description.
+// END android-note
+
+//BEGIN android-note
+//Filled some gaps in the documentation and refactored parts of the existing
+//documentation to make the Doclet happy.
+//END android-note
+
+/**
+ * The <code>Node</code> interface is the primary datatype for the entire 
+ * Document Object Model. It represents a single node in the document tree. 
+ * While all objects implementing the <code>Node</code> interface expose 
+ * methods for dealing with children, not all objects implementing the 
+ * <code>Node</code> interface may have children. For example, 
+ * <code>Text</code> nodes may not have children, and adding children to 
+ * such nodes results in a <code>DOMException</code> being raised.
+ * <p>The attributes <code>nodeName</code>, <code>nodeValue</code> and 
+ * <code>attributes</code> are included as a mechanism to get at node 
+ * information without casting down to the specific derived interface. In 
+ * cases where there is no obvious mapping of these attributes for a 
+ * specific <code>nodeType</code> (e.g., <code>nodeValue</code> for an 
+ * <code>Element</code> or <code>attributes</code> for a <code>Comment</code>
+ * ), this returns <code>null</code>. Note that the specialized interfaces 
+ * may contain additional and more convenient mechanisms to get and set the 
+ * relevant information.
+ * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>.
+ */
+public interface Node {
+    // NodeType
+    /**
+     * The node is an <code>Element</code>.
+     */
+    public static final short ELEMENT_NODE              = 1;
+    /**
+     * The node is an <code>Attr</code>.
+     */
+    public static final short ATTRIBUTE_NODE            = 2;
+    /**
+     * The node is a <code>Text</code> node.
+     */
+    public static final short TEXT_NODE                 = 3;
+    /**
+     * The node is a <code>CDATASection</code>.
+     */
+    public static final short CDATA_SECTION_NODE        = 4;
+    /**
+     * The node is an <code>EntityReference</code>.
+     */
+    public static final short ENTITY_REFERENCE_NODE     = 5;
+    /**
+     * The node is an <code>Entity</code>.
+     */
+    public static final short ENTITY_NODE               = 6;
+    /**
+     * The node is a <code>ProcessingInstruction</code>.
+     */
+    public static final short PROCESSING_INSTRUCTION_NODE = 7;
+    /**
+     * The node is a <code>Comment</code>.
+     */
+    public static final short COMMENT_NODE              = 8;
+    /**
+     * The node is a <code>Document</code>.
+     */
+    public static final short DOCUMENT_NODE             = 9;
+    /**
+     * The node is a <code>DocumentType</code>.
+     */
+    public static final short DOCUMENT_TYPE_NODE        = 10;
+    /**
+     * The node is a <code>DocumentFragment</code>.
+     */
+    public static final short DOCUMENT_FRAGMENT_NODE    = 11;
+    /**
+     * The node is a <code>Notation</code>.
+     */
+    public static final short NOTATION_NODE             = 12;
+
+    /**
+     * The name of this node, depending on its type; see the table above. 
+     * 
+     * @return the name of the node.
+     */
+    public String getNodeName();
+
+    /**
+     * Returns the value of this node, depending on its type; see the table
+     * above.
+     * 
+     * @return the value of the node.
+     * 
+     * @exception DOMException
+     *   DOMSTRING_SIZE_ERR: Raised when it would return more characters than 
+     *   fit in a <code>DOMString</code> variable on the implementation 
+     *   platform.
+     */
+    public String getNodeValue()
+                                 throws DOMException;
+    /**
+     * Sets the value of this node, depending on its type; see the table above. 
+     * When it is defined to be <code>null</code>, setting it has no effect.
+     * 
+     * @param nodeValue the new value of the node.
+     * 
+     * @exception DOMException
+     *   NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
+     */
+    public void setNodeValue(String nodeValue)
+                                 throws DOMException;
+
+    /**
+     * A code representing the type of the underlying object, as defined above.
+     * 
+     * @return the type of the node.
+     */
+    public short getNodeType();
+
+    /**
+     * The parent of this node. All nodes, except <code>Attr</code>, 
+     * <code>Document</code>, <code>DocumentFragment</code>, 
+     * <code>Entity</code>, and <code>Notation</code> may have a parent. 
+     * However, if a node has just been created and not yet added to the 
+     * tree, or if it has been removed from the tree, this is 
+     * <code>null</code>.
+     * 
+     * @return the parent node, if any.
+     */
+    public Node getParentNode();
+
+    /**
+     * A <code>NodeList</code> that contains all children of this node. If 
+     * there are no children, this is a <code>NodeList</code> containing no 
+     * nodes.
+     * 
+     * @return the list of children, which may be empty.
+     */
+    public NodeList getChildNodes();
+
+    /**
+     * The first child of this node. If there is no such node, this returns 
+     * <code>null</code>.
+     * 
+     * @return the first child of the node, if any.
+     */
+    public Node getFirstChild();
+
+    /**
+     * The last child of this node. If there is no such node, this returns 
+     * <code>null</code>.
+     * 
+     * @return the last child of the node, if any.
+     */
+    public Node getLastChild();
+
+    /**
+     * The node immediately preceding this node. If there is no such node, 
+     * this returns <code>null</code>.
+     * 
+     * @return the preceding node, if any.
+     */
+    public Node getPreviousSibling();
+
+    /**
+     * The node immediately following this node. If there is no such node, 
+     * this returns <code>null</code>.
+     * 
+     * @return the following node, if any.
+     */
+    public Node getNextSibling();
+
+    /**
+     * A <code>NamedNodeMap</code> containing the attributes of this node (if 
+     * it is an <code>Element</code>) or <code>null</code> otherwise. 
+     * 
+     * @return the attributes of the node, which may be an empty map, or
+     * <code>null</code>, if this the node cannot have any attributes.
+     */
+    public NamedNodeMap getAttributes();
+
+    /**
+     * The <code>Document</code> object associated with this node. This is 
+     * also the <code>Document</code> object used to create new nodes. When 
+     * this node is a <code>Document</code> or a <code>DocumentType</code> 
+     * which is not used with any <code>Document</code> yet, this is 
+     * <code>null</code>.
+     * 
+     * @return the document this node belongs to, if any.
+     * 
+     * @version DOM Level 2
+     */
+    public Document getOwnerDocument();
+
+    /**
+     * Inserts the node <code>newChild</code> before the existing child node 
+     * <code>refChild</code>. If <code>refChild</code> is <code>null</code>, 
+     * insert <code>newChild</code> at the end of the list of children.
+     * <br>If <code>newChild</code> is a <code>DocumentFragment</code> object, 
+     * all of its children are inserted, in the same order, before 
+     * <code>refChild</code>. If the <code>newChild</code> is already in the 
+     * tree, it is first removed.
+     * @param newChild The node to insert.
+     * @param refChild The reference node, i.e., the node before which the new 
+     *   node must be inserted.
+     * @return The node being inserted.
+     * @exception DOMException
+     *   HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not 
+     *   allow children of the type of the <code>newChild</code> node, or if 
+     *   the node to insert is one of this node's ancestors.
+     *   <br>WRONG_DOCUMENT_ERR: Raised if <code>newChild</code> was created 
+     *   from a different document than the one that created this node.
+     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly or 
+     *   if the parent of the node being inserted is readonly.
+     *   <br>NOT_FOUND_ERR: Raised if <code>refChild</code> is not a child of 
+     *   this node.
+     */
+    public Node insertBefore(Node newChild, 
+                             Node refChild)
+                             throws DOMException;
+
+    /**
+     * Replaces the child node <code>oldChild</code> with <code>newChild</code>
+     *  in the list of children, and returns the <code>oldChild</code> node.
+     * <br>If <code>newChild</code> is a <code>DocumentFragment</code> object, 
+     * <code>oldChild</code> is replaced by all of the 
+     * <code>DocumentFragment</code> children, which are inserted in the 
+     * same order. If the <code>newChild</code> is already in the tree, it 
+     * is first removed.
+     * @param newChild The new node to put in the child list.
+     * @param oldChild The node being replaced in the list.
+     * @return The node replaced.
+     * @exception DOMException
+     *   HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not 
+     *   allow children of the type of the <code>newChild</code> node, or if 
+     *   the node to put in is one of this node's ancestors.
+     *   <br>WRONG_DOCUMENT_ERR: Raised if <code>newChild</code> was created 
+     *   from a different document than the one that created this node.
+     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node or the parent of 
+     *   the new node is readonly.
+     *   <br>NOT_FOUND_ERR: Raised if <code>oldChild</code> is not a child of 
+     *   this node.
+     */
+    public Node replaceChild(Node newChild, 
+                             Node oldChild)
+                             throws DOMException;
+
+    /**
+     * Removes the child node indicated by <code>oldChild</code> from the list 
+     * of children, and returns it.
+     * @param oldChild The node being removed.
+     * @return The node removed.
+     * @exception DOMException
+     *   NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+     *   <br>NOT_FOUND_ERR: Raised if <code>oldChild</code> is not a child of 
+     *   this node.
+     */
+    public Node removeChild(Node oldChild)
+                            throws DOMException;
+
+    /**
+     * Adds the node <code>newChild</code> to the end of the list of children 
+     * of this node. If the <code>newChild</code> is already in the tree, it 
+     * is first removed.
+     * @param newChild The node to add.If it is a <code>DocumentFragment</code>
+     *    object, the entire contents of the document fragment are moved 
+     *   into the child list of this node
+     * @return The node added.
+     * @exception DOMException
+     *   HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not 
+     *   allow children of the type of the <code>newChild</code> node, or if 
+     *   the node to append is one of this node's ancestors.
+     *   <br>WRONG_DOCUMENT_ERR: Raised if <code>newChild</code> was created 
+     *   from a different document than the one that created this node.
+     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+     */
+    public Node appendChild(Node newChild)
+                            throws DOMException;
+
+    /**
+     * Returns whether this node has any children.
+     * @return  <code>true</code> if this node has any children, 
+     *   <code>false</code> otherwise.
+     */
+    public boolean hasChildNodes();
+
+    /**
+     * Returns a duplicate of this node, i.e., serves as a generic copy 
+     * constructor for nodes. The duplicate node has no parent; (
+     * <code>parentNode</code> is <code>null</code>.).
+     * <br>Cloning an <code>Element</code> copies all attributes and their 
+     * values, including those generated by the XML processor to represent 
+     * defaulted attributes, but this method does not copy any text it 
+     * contains unless it is a deep clone, since the text is contained in a 
+     * child <code>Text</code> node. Cloning an <code>Attribute</code> 
+     * directly, as opposed to be cloned as part of an <code>Element</code> 
+     * cloning operation, returns a specified attribute (
+     * <code>specified</code> is <code>true</code>). Cloning any other type 
+     * of node simply returns a copy of this node.
+     * <br>Note that cloning an immutable subtree results in a mutable copy, 
+     * but the children of an <code>EntityReference</code> clone are readonly
+     * . In addition, clones of unspecified <code>Attr</code> nodes are 
+     * specified. And, cloning <code>Document</code>, 
+     * <code>DocumentType</code>, <code>Entity</code>, and 
+     * <code>Notation</code> nodes is implementation dependent.
+     * @param deep If <code>true</code>, recursively clone the subtree under 
+     *   the specified node; if <code>false</code>, clone only the node 
+     *   itself (and its attributes, if it is an <code>Element</code>). 
+     * @return The duplicate node.
+     */
+    public Node cloneNode(boolean deep);
+
+    /**
+     * Puts all <code>Text</code> nodes in the full depth of the sub-tree 
+     * underneath this <code>Node</code>, including attribute nodes, into a 
+     * "normal" form where only structure (e.g., elements, comments, 
+     * processing instructions, CDATA sections, and entity references) 
+     * separates <code>Text</code> nodes, i.e., there are neither adjacent 
+     * <code>Text</code> nodes nor empty <code>Text</code> nodes. This can 
+     * be used to ensure that the DOM view of a document is the same as if 
+     * it were saved and re-loaded, and is useful when operations (such as 
+     * XPointer  lookups) that depend on a particular document tree 
+     * structure are to be used.In cases where the document contains 
+     * <code>CDATASections</code>, the normalize operation alone may not be 
+     * sufficient, since XPointers do not differentiate between 
+     * <code>Text</code> nodes and <code>CDATASection</code> nodes.
+     * @version DOM Level 2
+     */
+    public void normalize();
+
+    /**
+     * Tests whether the DOM implementation implements a specific feature and 
+     * that feature is supported by this node.
+     * @param feature The name of the feature to test. This is the same name 
+     *   which can be passed to the method <code>hasFeature</code> on 
+     *   <code>DOMImplementation</code>.
+     * @param version This is the version number of the feature to test. In 
+     *   Level 2, version 1, this is the string "2.0". If the version is not 
+     *   specified, supporting any version of the feature will cause the 
+     *   method to return <code>true</code>.
+     * @return Returns <code>true</code> if the specified feature is 
+     *   supported on this node, <code>false</code> otherwise.
+     * @since DOM Level 2
+     */
+    public boolean isSupported(String feature, 
+                               String version);
+
+    /**
+     * The namespace URI of this node, or <code>null</code> if it is 
+     * unspecified.
+     * <br>This is not a computed value that is the result of a namespace 
+     * lookup based on an examination of the namespace declarations in 
+     * scope. It is merely the namespace URI given at creation time.
+     * <br>For nodes of any type other than <code>ELEMENT_NODE</code> and 
+     * <code>ATTRIBUTE_NODE</code> and nodes created with a DOM Level 1 
+     * method, such as <code>createElement</code> from the 
+     * <code>Document</code> interface, this is always <code>null</code>.Per 
+     * the Namespaces in XML Specification  an attribute does not inherit 
+     * its namespace from the element it is attached to. If an attribute is 
+     * not explicitly given a namespace, it simply has no namespace.
+     * 
+     * @return the namespace URI, if any.
+     * 
+     * @since DOM Level 2
+     */
+    public String getNamespaceURI();
+
+    /**
+     * Returns the namespace prefix of this node, or <code>null</code> if it is 
+     * unspecified.
+     * <br>For nodes of any type other than <code>ELEMENT_NODE</code> and 
+     * <code>ATTRIBUTE_NODE</code> and nodes created with a DOM Level 1 
+     * method, such as <code>createElement</code> from the 
+     * <code>Document</code> interface, this is always <code>null</code>.
+     * 
+     * @return the namespace prefix, if any.
+     * 
+     * @exception DOMException
+     * @since DOM Level 2
+     */
+    public String getPrefix();
+    
+    /**
+     * Sets the namespace prefix of this node.
+     * <br>Note that setting this attribute, when permitted, changes the 
+     * <code>nodeName</code> attribute, which holds the qualified name, as 
+     * well as the <code>tagName</code> and <code>name</code> attributes of 
+     * the <code>Element</code> and <code>Attr</code> interfaces, when 
+     * applicable.
+     * <br>Note also that changing the prefix of an attribute that is known to 
+     * have a default value, does not make a new attribute with the default 
+     * value and the original prefix appear, since the 
+     * <code>namespaceURI</code> and <code>localName</code> do not change.
+     * <br>For nodes of any type other than <code>ELEMENT_NODE</code> and 
+     * <code>ATTRIBUTE_NODE</code> and nodes created with a DOM Level 1 
+     * method, such as <code>createElement</code> from the 
+     * <code>Document</code> interface, this is always <code>null</code>.
+     * @exception DOMException
+     *   INVALID_CHARACTER_ERR: Raised if the specified prefix contains an 
+     *   illegal character.
+     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+     *   <br>NAMESPACE_ERR: Raised if the specified <code>prefix</code> is 
+     *   malformed, if the <code>namespaceURI</code> of this node is 
+     *   <code>null</code>, if the specified prefix is "xml" and the 
+     *   <code>namespaceURI</code> of this node is different from "
+     *   http://www.w3.org/XML/1998/namespace", if this node is an attribute 
+     *   and the specified prefix is "xmlns" and the 
+     *   <code>namespaceURI</code> of this node is different from "
+     *   http://www.w3.org/2000/xmlns/", or if this node is an attribute and 
+     *   the <code>qualifiedName</code> of this node is "xmlns" .
+     *   
+     * @param prefix the new namespace prefix.
+     * 
+     * @since DOM Level 2
+     */
+    public void setPrefix(String prefix)
+                               throws DOMException;
+
+    /**
+     * Returns the local part of the qualified name of this node.
+     * <br>For nodes of any type other than <code>ELEMENT_NODE</code> and 
+     * <code>ATTRIBUTE_NODE</code> and nodes created with a DOM Level 1 
+     * method, such as <code>createElement</code> from the 
+     * <code>Document</code> interface, this is always <code>null</code>.
+     * 
+     * @return the local name, if any.
+     * 
+     * @since DOM Level 2
+     */
+    public String getLocalName();
+
+    /**
+     * Returns whether this node (if it is an element) has any attributes.
+     * @return <code>true</code> if this node has any attributes, 
+     *   <code>false</code> otherwise.
+     * @since DOM Level 2
+     */
+    public boolean hasAttributes();
+
+}
diff --git a/xml/src/main/java/org/w3c/dom/NodeList.java b/xml/src/main/java/org/w3c/dom/NodeList.java
new file mode 100644
index 0000000..0dbadda
--- /dev/null
+++ b/xml/src/main/java/org/w3c/dom/NodeList.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2000 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.w3c.dom;
+
+// BEGIN android-note
+// Cleaned up @param tags that seemed to be missing spaces between
+// the parameter name and the start of the description.
+// END android-note
+
+//BEGIN android-note
+//Filled some gaps in the documentation and refactored parts of the existing
+//documentation to make the Doclet happy.
+//END android-note
+
+/**
+ * The <code>NodeList</code> interface provides the abstraction of an ordered 
+ * collection of nodes, without defining or constraining how this collection 
+ * is implemented. <code>NodeList</code> objects in the DOM are live.
+ * <p>The items in the <code>NodeList</code> are accessible via an integral 
+ * index, starting from 0.
+ * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>.
+ */
+public interface NodeList {
+    /**
+     * Returns the <code>index</code>th item in the collection. If 
+     * <code>index</code> is greater than or equal to the number of nodes in 
+     * the list, this returns <code>null</code>.
+     * @param index Index into the collection.
+     * @return The node at the <code>index</code>th position in the 
+     *   <code>NodeList</code>, or <code>null</code> if that is not a valid 
+     *   index.
+     */
+    public Node item(int index);
+
+    /**
+     * The number of nodes in the list. The range of valid child node indices 
+     * is 0 to <code>length-1</code> inclusive.
+     * 
+     * @return the length of the list. 
+     */
+    public int getLength();
+
+}
diff --git a/xml/src/main/java/org/w3c/dom/Notation.java b/xml/src/main/java/org/w3c/dom/Notation.java
new file mode 100644
index 0000000..00c702f
--- /dev/null
+++ b/xml/src/main/java/org/w3c/dom/Notation.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2000 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.w3c.dom;
+
+//BEGIN android-note
+//Filled some gaps in the documentation and refactored parts of the existing
+//documentation to make the Doclet happy.
+//END android-note
+
+/**
+ * This interface represents a notation declared in the DTD. A notation either 
+ * declares, by name, the format of an unparsed entity (see section 4.7 of 
+ * the XML 1.0 specification ), or is used for formal declaration of 
+ * processing instruction targets (see section 2.6 of the XML 1.0 
+ * specification ). The <code>nodeName</code> attribute inherited from 
+ * <code>Node</code> is set to the declared name of the notation.
+ * <p>The DOM Level 1 does not support editing <code>Notation</code> nodes; 
+ * they are therefore readonly.
+ * <p>A <code>Notation</code> node does not have any parent.
+ * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>.
+ */
+public interface Notation extends Node {
+    /**
+     * The public identifier of this notation. If the public identifier was 
+     * not specified, this is <code>null</code>.
+     * 
+     * @return the public identifier of this notation, if any.
+     */
+    public String getPublicId();
+
+    /**
+     * The system identifier of this notation. If the system identifier was 
+     * not specified, this is <code>null</code>.
+     * 
+     * @return the system identifier of this notation, if any.
+     */
+    public String getSystemId();
+
+}
diff --git a/xml/src/main/java/org/w3c/dom/ProcessingInstruction.java b/xml/src/main/java/org/w3c/dom/ProcessingInstruction.java
new file mode 100644
index 0000000..a702aa6
--- /dev/null
+++ b/xml/src/main/java/org/w3c/dom/ProcessingInstruction.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2000 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.w3c.dom;
+
+//BEGIN android-note
+//Filled some gaps in the documentation and refactored parts of the existing
+//documentation to make the Doclet happy.
+//END android-note
+
+/**
+ * The <code>ProcessingInstruction</code> interface represents a "processing 
+ * instruction", used in XML as a way to keep processor-specific information 
+ * in the text of the document.
+ * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>.
+ */
+public interface ProcessingInstruction extends Node {
+    /**
+     * The target of this processing instruction. XML defines this as being 
+     * the first token following the markup that begins the processing 
+     * instruction.
+     * 
+     * @return the target of this processing instruction.
+     */
+    public String getTarget();
+
+    /**
+     * Returns the content of this processing instruction. This is from the
+     * first non white space character after the target to the character
+     * immediately preceding the <code>?&gt;</code>.
+     * 
+     * @return the data of this processing instruction.
+     */
+    public String getData();
+
+    /**
+     * Sets the content of this processing instruction. This is from the first
+     * non white space character after the target to the character immediately 
+     * preceding the <code>?&gt;</code>.
+     * 
+     * @param data the new data of the processing instruction.
+     * 
+     * @exception DOMException
+     *   NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
+     */
+    public void setData(String data)
+                          throws DOMException;
+
+}
diff --git a/xml/src/main/java/org/w3c/dom/Text.java b/xml/src/main/java/org/w3c/dom/Text.java
new file mode 100644
index 0000000..4d1746b
--- /dev/null
+++ b/xml/src/main/java/org/w3c/dom/Text.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2000 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package org.w3c.dom;
+
+// BEGIN android-note
+// Cleaned up @param tags that seemed to be missing spaces between
+// the parameter name and the start of the description.
+// END android-note
+
+/**
+ * The <code>Text</code> interface inherits from <code>CharacterData</code> 
+ * and represents the textual content (termed character data in XML) of an 
+ * <code>Element</code> or <code>Attr</code>. If there is no markup inside 
+ * an element's content, the text is contained in a single object 
+ * implementing the <code>Text</code> interface that is the only child of 
+ * the element. If there is markup, it is parsed into the information items 
+ * (elements, comments, etc.) and <code>Text</code> nodes that form the list 
+ * of children of the element.
+ * <p>When a document is first made available via the DOM, there is only one 
+ * <code>Text</code> node for each block of text. Users may create adjacent 
+ * <code>Text</code> nodes that represent the contents of a given element 
+ * without any intervening markup, but should be aware that there is no way 
+ * to represent the separations between these nodes in XML or HTML, so they 
+ * will not (in general) persist between DOM editing sessions. The 
+ * <code>normalize()</code> method on <code>Node</code> merges any such 
+ * adjacent <code>Text</code> objects into a single node for each block of 
+ * text.
+ * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113'>Document Object Model (DOM) Level 2 Core Specification</a>.
+ */
+public interface Text extends CharacterData {
+    /**
+     * Breaks this node into two nodes at the specified <code>offset</code>, 
+     * keeping both in the tree as siblings. After being split, this node 
+     * will contain all the content up to the <code>offset</code> point. A 
+     * new node of the same type, which contains all the content at and 
+     * after the <code>offset</code> point, is returned. If the original 
+     * node had a parent node, the new node is inserted as the next sibling 
+     * of the original node. When the <code>offset</code> is equal to the 
+     * length of this node, the new node has no data.
+     * @param offset The 16-bit unit offset at which to split, starting from 
+     *   <code>0</code>.
+     * @return The new node, of the same type as this node.
+     * @exception DOMException
+     *   INDEX_SIZE_ERR: Raised if the specified offset is negative or greater 
+     *   than the number of 16-bit units in <code>data</code>.
+     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+     */
+    public Text splitText(int offset)
+                          throws DOMException;
+
+}
diff --git a/xml/src/main/java/org/w3c/dom/package.html b/xml/src/main/java/org/w3c/dom/package.html
new file mode 100644
index 0000000..8189944
--- /dev/null
+++ b/xml/src/main/java/org/w3c/dom/package.html
@@ -0,0 +1,12 @@
+<html>
+  <body>
+    <p>
+      Provides the official W3C Java bindings for the Document Object Model,
+      level 2 core. XML documents returned by
+      {@link javax.xml.parsers.DocumentBuilder} are accessed and manipulated
+      through these interfaces.
+    </p>
+    
+  @since Android 1.0
+  </body>
+</html>
\ No newline at end of file
diff --git a/xml/src/main/java/org/xml/sax/AttributeList.java b/xml/src/main/java/org/xml/sax/AttributeList.java
new file mode 100644
index 0000000..9285eac
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/AttributeList.java
@@ -0,0 +1,193 @@
+// SAX Attribute List Interface.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: AttributeList.java,v 1.7 2004/04/26 17:34:34 dmegginson Exp $
+
+package org.xml.sax;
+
+/**
+ * Interface for an element's attribute specifications.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This is the original SAX1 interface for reporting an element's
+ * attributes.  Unlike the new {@link org.xml.sax.Attributes Attributes}
+ * interface, it does not support Namespace-related information.</p>
+ *
+ * <p>When an attribute list is supplied as part of a
+ * {@link org.xml.sax.DocumentHandler#startElement startElement}
+ * event, the list will return valid results only during the
+ * scope of the event; once the event handler returns control
+ * to the parser, the attribute list is invalid.  To save a
+ * persistent copy of the attribute list, use the SAX1
+ * {@link org.xml.sax.helpers.AttributeListImpl AttributeListImpl}
+ * helper class.</p>
+ *
+ * <p>An attribute list includes only attributes that have been
+ * specified or defaulted: #IMPLIED attributes will not be included.</p>
+ *
+ * <p>There are two ways for the SAX application to obtain information
+ * from the AttributeList.  First, it can iterate through the entire
+ * list:</p>
+ *
+ * <pre>
+ * public void startElement (String name, AttributeList atts) {
+ *   for (int i = 0; i < atts.getLength(); i++) {
+ *     String name = atts.getName(i);
+ *     String type = atts.getType(i);
+ *     String value = atts.getValue(i);
+ *     [...]
+ *   }
+ * }
+ * </pre>
+ *
+ * <p>(Note that the result of getLength() will be zero if there
+ * are no attributes.)
+ *
+ * <p>As an alternative, the application can request the value or
+ * type of specific attributes:</p>
+ *
+ * <pre>
+ * public void startElement (String name, AttributeList atts) {
+ *   String identifier = atts.getValue("id");
+ *   String label = atts.getValue("label");
+ *   [...]
+ * }
+ * </pre>
+ *
+ * @deprecated This interface has been replaced by the SAX2
+ *             {@link org.xml.sax.Attributes Attributes}
+ *             interface, which includes Namespace support.
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.DocumentHandler#startElement startElement
+ * @see org.xml.sax.helpers.AttributeListImpl AttributeListImpl
+ */
+public interface AttributeList {
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Iteration methods.
+    ////////////////////////////////////////////////////////////////////
+    
+
+    /**
+     * Return the number of attributes in this list.
+     *
+     * <p>The SAX parser may provide attributes in any
+     * arbitrary order, regardless of the order in which they were
+     * declared or specified.  The number of attributes may be
+     * zero.</p>
+     *
+     * @return The number of attributes in the list.  
+     */
+    public abstract int getLength ();
+    
+    
+    /**
+     * Return the name of an attribute in this list (by position).
+     *
+     * <p>The names must be unique: the SAX parser shall not include the
+     * same attribute twice.  Attributes without values (those declared
+     * #IMPLIED without a value specified in the start tag) will be
+     * omitted from the list.</p>
+     *
+     * <p>If the attribute name has a namespace prefix, the prefix
+     * will still be attached.</p>
+     *
+     * @param i The index of the attribute in the list (starting at 0).
+     * @return The name of the indexed attribute, or null
+     *         if the index is out of range.
+     * @see #getLength 
+     */
+    public abstract String getName (int i);
+    
+    
+    /**
+     * Return the type of an attribute in the list (by position).
+     *
+     * <p>The attribute type is one of the strings "CDATA", "ID",
+     * "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY", "ENTITIES",
+     * or "NOTATION" (always in upper case).</p>
+     *
+     * <p>If the parser has not read a declaration for the attribute,
+     * or if the parser does not report attribute types, then it must
+     * return the value "CDATA" as stated in the XML 1.0 Recommentation
+     * (clause 3.3.3, "Attribute-Value Normalization").</p>
+     *
+     * <p>For an enumerated attribute that is not a notation, the
+     * parser will report the type as "NMTOKEN".</p>
+     *
+     * @param i The index of the attribute in the list (starting at 0).
+     * @return The attribute type as a string, or
+     *         null if the index is out of range.
+     * @see #getLength 
+     * @see #getType(java.lang.String)
+     */
+    public abstract String getType (int i);
+    
+    
+    /**
+     * Return the value of an attribute in the list (by position).
+     *
+     * <p>If the attribute value is a list of tokens (IDREFS,
+     * ENTITIES, or NMTOKENS), the tokens will be concatenated
+     * into a single string separated by whitespace.</p>
+     *
+     * @param i The index of the attribute in the list (starting at 0).
+     * @return The attribute value as a string, or
+     *         null if the index is out of range.
+     * @see #getLength
+     * @see #getValue(java.lang.String)
+     */
+    public abstract String getValue (int i);
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Lookup methods.
+    ////////////////////////////////////////////////////////////////////
+    
+    
+    /**
+     * Return the type of an attribute in the list (by name).
+     *
+     * <p>The return value is the same as the return value for
+     * getType(int).</p>
+     *
+     * <p>If the attribute name has a namespace prefix in the document,
+     * the application must include the prefix here.</p>
+     *
+     * @param name The name of the attribute.
+     * @return The attribute type as a string, or null if no
+     *         such attribute exists.
+     * @see #getType(int)
+     */
+    public abstract String getType (String name);
+    
+    
+    /**
+     * Return the value of an attribute in the list (by name).
+     *
+     * <p>The return value is the same as the return value for
+     * getValue(int).</p>
+     *
+     * <p>If the attribute name has a namespace prefix in the document,
+     * the application must include the prefix here.</p>
+     *
+     * @param name the name of the attribute to return
+     * @return The attribute value as a string, or null if
+     *         no such attribute exists.
+     * @see #getValue(int)
+     */
+    public abstract String getValue (String name);
+    
+}
+
+// end of AttributeList.java
diff --git a/xml/src/main/java/org/xml/sax/Attributes.java b/xml/src/main/java/org/xml/sax/Attributes.java
new file mode 100644
index 0000000..b25432d
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/Attributes.java
@@ -0,0 +1,257 @@
+// Attributes.java - attribute list with Namespace support
+// http://www.saxproject.org
+// Written by David Megginson
+// NO WARRANTY!  This class is in the public domain.
+// $Id: Attributes.java,v 1.13 2004/03/18 12:28:05 dmegginson Exp $
+
+package org.xml.sax;
+
+
+/**
+ * Interface for a list of XML attributes.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This interface allows access to a list of attributes in
+ * three different ways:</p>
+ *
+ * <ol>
+ * <li>by attribute index;</li>
+ * <li>by Namespace-qualified name; or</li>
+ * <li>by qualified (prefixed) name.</li>
+ * </ol>
+ *
+ * <p>The list will not contain attributes that were declared
+ * #IMPLIED but not specified in the start tag.  It will also not
+ * contain attributes used as Namespace declarations (xmlns*) unless
+ * the <code>http://xml.org/sax/features/namespace-prefixes</code> 
+ * feature is set to <var>true</var> (it is <var>false</var> by 
+ * default).
+ * Because SAX2 conforms to the original "Namespaces in XML"
+ * recommendation, it normally does not
+ * give namespace declaration attributes a namespace URI.
+ * </p>
+ *
+ * <p>Some SAX2 parsers may support using an optional feature flag
+ * (<code>http://xml.org/sax/features/xmlns-uris</code>) to request
+ * that those attributes be given URIs, conforming to a later
+ * backwards-incompatible revision of that recommendation.  (The
+ * attribute's "local name" will be the prefix, or "xmlns" when
+ * defining a default element namespace.)  For portability, handler
+ * code should always resolve that conflict, rather than requiring
+ * parsers that can change the setting of that feature flag.  </p>
+ *
+ * <p>If the namespace-prefixes feature (see above) is
+ * <var>false</var>, access by qualified name may not be available; if
+ * the <code>http://xml.org/sax/features/namespaces</code> feature is
+ * <var>false</var>, access by Namespace-qualified names may not be
+ * available.</p>
+ *
+ * <p>This interface replaces the now-deprecated SAX1 {@link
+ * org.xml.sax.AttributeList AttributeList} interface, which does not 
+ * contain Namespace support.  In addition to Namespace support, it 
+ * adds the <var>getIndex</var> methods (below).</p>
+ *
+ * <p>The order of attributes in the list is unspecified, and will
+ * vary from implementation to implementation.</p>
+ *
+ * @since SAX 2.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.helpers.AttributesImpl
+ * @see org.xml.sax.ext.DeclHandler#attributeDecl
+ */
+public interface Attributes
+{
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Indexed access.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Return the number of attributes in the list.
+     *
+     * <p>Once you know the number of attributes, you can iterate
+     * through the list.</p>
+     *
+     * @return The number of attributes in the list.
+     * @see #getURI(int)
+     * @see #getLocalName(int)
+     * @see #getQName(int)
+     * @see #getType(int)
+     * @see #getValue(int)
+     */
+    public abstract int getLength ();
+
+
+    /**
+     * Look up an attribute's Namespace URI by index.
+     *
+     * @param index The attribute index (zero-based).
+     * @return The Namespace URI, or the empty string if none
+     *         is available, or null if the index is out of
+     *         range.
+     * @see #getLength
+     */
+    public abstract String getURI (int index);
+
+
+    /**
+     * Look up an attribute's local name by index.
+     *
+     * @param index The attribute index (zero-based).
+     * @return The local name, or the empty string if Namespace
+     *         processing is not being performed, or null
+     *         if the index is out of range.
+     * @see #getLength
+     */
+    public abstract String getLocalName (int index);
+
+
+    /**
+     * Look up an attribute's XML qualified (prefixed) name by index.
+     *
+     * @param index The attribute index (zero-based).
+     * @return The XML qualified name, or the empty string
+     *         if none is available, or null if the index
+     *         is out of range.
+     * @see #getLength
+     */
+    public abstract String getQName (int index);
+
+
+    /**
+     * Look up an attribute's type by index.
+     *
+     * <p>The attribute type is one of the strings "CDATA", "ID",
+     * "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY", "ENTITIES",
+     * or "NOTATION" (always in upper case).</p>
+     *
+     * <p>If the parser has not read a declaration for the attribute,
+     * or if the parser does not report attribute types, then it must
+     * return the value "CDATA" as stated in the XML 1.0 Recommendation
+     * (clause 3.3.3, "Attribute-Value Normalization").</p>
+     *
+     * <p>For an enumerated attribute that is not a notation, the
+     * parser will report the type as "NMTOKEN".</p>
+     *
+     * @param index The attribute index (zero-based).
+     * @return The attribute's type as a string, or null if the
+     *         index is out of range.
+     * @see #getLength
+     */
+    public abstract String getType (int index);
+
+
+    /**
+     * Look up an attribute's value by index.
+     *
+     * <p>If the attribute value is a list of tokens (IDREFS,
+     * ENTITIES, or NMTOKENS), the tokens will be concatenated
+     * into a single string with each token separated by a
+     * single space.</p>
+     *
+     * @param index The attribute index (zero-based).
+     * @return The attribute's value as a string, or null if the
+     *         index is out of range.
+     * @see #getLength
+     */
+    public abstract String getValue (int index);
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Name-based query.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Look up the index of an attribute by Namespace name.
+     *
+     * @param uri The Namespace URI, or the empty string if
+     *        the name has no Namespace URI.
+     * @param localName The attribute's local name.
+     * @return The index of the attribute, or -1 if it does not
+     *         appear in the list.
+     */
+    public int getIndex (String uri, String localName);
+
+
+    /**
+     * Look up the index of an attribute by XML qualified (prefixed) name.
+     *
+     * @param qName The qualified (prefixed) name.
+     * @return The index of the attribute, or -1 if it does not
+     *         appear in the list.
+     */
+    public int getIndex (String qName);
+
+
+    /**
+     * Look up an attribute's type by Namespace name.
+     *
+     * <p>See {@link #getType(int) getType(int)} for a description
+     * of the possible types.</p>
+     *
+     * @param uri The Namespace URI, or the empty String if the
+     *        name has no Namespace URI.
+     * @param localName The local name of the attribute.
+     * @return The attribute type as a string, or null if the
+     *         attribute is not in the list or if Namespace
+     *         processing is not being performed.
+     */
+    public abstract String getType (String uri, String localName);
+
+
+    /**
+     * Look up an attribute's type by XML qualified (prefixed) name.
+     *
+     * <p>See {@link #getType(int) getType(int)} for a description
+     * of the possible types.</p>
+     *
+     * @param qName The XML qualified name.
+     * @return The attribute type as a string, or null if the
+     *         attribute is not in the list or if qualified names
+     *         are not available.
+     */
+    public abstract String getType (String qName);
+
+
+    /**
+     * Look up an attribute's value by Namespace name.
+     *
+     * <p>See {@link #getValue(int) getValue(int)} for a description
+     * of the possible values.</p>
+     *
+     * @param uri The Namespace URI, or the empty String if the
+     *        name has no Namespace URI.
+     * @param localName The local name of the attribute.
+     * @return The attribute value as a string, or null if the
+     *         attribute is not in the list.
+     */
+    public abstract String getValue (String uri, String localName);
+
+
+    /**
+     * Look up an attribute's value by XML qualified (prefixed) name.
+     *
+     * <p>See {@link #getValue(int) getValue(int)} for a description
+     * of the possible values.</p>
+     *
+     * @param qName The XML qualified name.
+     * @return The attribute value as a string, or null if the
+     *         attribute is not in the list or if qualified names
+     *         are not available.
+     */
+    public abstract String getValue (String qName);
+
+}
+
+// end of Attributes.java
diff --git a/xml/src/main/java/org/xml/sax/ContentHandler.java b/xml/src/main/java/org/xml/sax/ContentHandler.java
new file mode 100644
index 0000000..db66c0d
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/ContentHandler.java
@@ -0,0 +1,419 @@
+// ContentHandler.java - handle main document content.
+// http://www.saxproject.org
+// Written by David Megginson
+// NO WARRANTY!  This class is in the public domain.
+// $Id: ContentHandler.java,v 1.13 2004/04/26 17:50:49 dmegginson Exp $
+
+package org.xml.sax;
+
+
+/**
+ * Receive notification of the logical content of a document.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This is the main interface that most SAX applications
+ * implement: if the application needs to be informed of basic parsing 
+ * events, it implements this interface and registers an instance with 
+ * the SAX parser using the {@link org.xml.sax.XMLReader#setContentHandler 
+ * setContentHandler} method.  The parser uses the instance to report 
+ * basic document-related events like the start and end of elements 
+ * and character data.</p>
+ *
+ * <p>The order of events in this interface is very important, and
+ * mirrors the order of information in the document itself.  For
+ * example, all of an element's content (character data, processing
+ * instructions, and/or subelements) will appear, in order, between
+ * the startElement event and the corresponding endElement event.</p>
+ *
+ * <p>This interface is similar to the now-deprecated SAX 1.0
+ * DocumentHandler interface, but it adds support for Namespaces
+ * and for reporting skipped entities (in non-validating XML
+ * processors).</p>
+ *
+ * <p>Implementors should note that there is also a 
+ * <code>ContentHandler</code> class in the <code>java.net</code>
+ * package; that means that it's probably a bad idea to do</p>
+ *
+ * <pre>import java.net.*;
+ * import org.xml.sax.*;
+ * </pre>
+ *
+ * <p>In fact, "import ...*" is usually a sign of sloppy programming
+ * anyway, so the user should consider this a feature rather than a
+ * bug.</p>
+ *
+ * @since SAX 2.0
+ * @author David Megginson
+ * @version 2.0.1+ (sax2r3pre1)
+ * @see org.xml.sax.XMLReader
+ * @see org.xml.sax.DTDHandler
+ * @see org.xml.sax.ErrorHandler
+ */
+public interface ContentHandler
+{
+
+    /**
+     * Receive an object for locating the origin of SAX document events.
+     *
+     * <p>SAX parsers are strongly encouraged (though not absolutely
+     * required) to supply a locator: if it does so, it must supply
+     * the locator to the application by invoking this method before
+     * invoking any of the other methods in the ContentHandler
+     * interface.</p>
+     *
+     * <p>The locator allows the application to determine the end
+     * position of any document-related event, even if the parser is
+     * not reporting an error.  Typically, the application will
+     * use this information for reporting its own errors (such as
+     * character content that does not match an application's
+     * business rules).  The information returned by the locator
+     * is probably not sufficient for use with a search engine.</p>
+     *
+     * <p>Note that the locator will return correct information only
+     * during the invocation SAX event callbacks after
+     * {@link #startDocument startDocument} returns and before
+     * {@link #endDocument endDocument} is called.  The
+     * application should not attempt to use it at any other time.</p>
+     *
+     * @param locator an object that can return the location of
+     *                any SAX document event
+     * @see org.xml.sax.Locator
+     */
+    public void setDocumentLocator (Locator locator);
+
+
+    /**
+     * Receive notification of the beginning of a document.
+     *
+     * <p>The SAX parser will invoke this method only once, before any
+     * other event callbacks (except for {@link #setDocumentLocator 
+     * setDocumentLocator}).</p>
+     *
+     * @throws org.xml.sax.SAXException any SAX exception, possibly
+     *            wrapping another exception
+     * @see #endDocument
+     */
+    public void startDocument ()
+    throws SAXException;
+
+
+    /**
+     * Receive notification of the end of a document.
+     *
+     * <p><strong>There is an apparent contradiction between the
+     * documentation for this method and the documentation for {@link
+     * org.xml.sax.ErrorHandler#fatalError}.  Until this ambiguity is
+     * resolved in a future major release, clients should make no
+     * assumptions about whether endDocument() will or will not be
+     * invoked when the parser has reported a fatalError() or thrown
+     * an exception.</strong></p>
+     *
+     * <p>The SAX parser will invoke this method only once, and it will
+     * be the last method invoked during the parse.  The parser shall
+     * not invoke this method until it has either abandoned parsing
+     * (because of an unrecoverable error) or reached the end of
+     * input.</p>
+     *
+     * @throws org.xml.sax.SAXException any SAX exception, possibly
+     *            wrapping another exception
+     * @see #startDocument
+     */
+    public void endDocument()
+    throws SAXException;
+
+
+    /**
+     * Begin the scope of a prefix-URI Namespace mapping.
+     *
+     * <p>The information from this event is not necessary for
+     * normal Namespace processing: the SAX XML reader will 
+     * automatically replace prefixes for element and attribute
+     * names when the <code>http://xml.org/sax/features/namespaces</code>
+     * feature is <var>true</var> (the default).</p>
+     *
+     * <p>There are cases, however, when applications need to
+     * use prefixes in character data or in attribute values,
+     * where they cannot safely be expanded automatically; the
+     * start/endPrefixMapping event supplies the information
+     * to the application to expand prefixes in those contexts
+     * itself, if necessary.</p>
+     *
+     * <p>Note that start/endPrefixMapping events are not
+     * guaranteed to be properly nested relative to each other:
+     * all startPrefixMapping events will occur immediately before the
+     * corresponding {@link #startElement startElement} event, 
+     * and all {@link #endPrefixMapping endPrefixMapping}
+     * events will occur immediately after the corresponding
+     * {@link #endElement endElement} event,
+     * but their order is not otherwise 
+     * guaranteed.</p>
+     *
+     * <p>There should never be start/endPrefixMapping events for the
+     * "xml" prefix, since it is predeclared and immutable.</p>
+     *
+     * @param prefix the Namespace prefix being declared.
+     *    An empty string is used for the default element namespace,
+     *    which has no prefix.
+     * @param uri the Namespace URI the prefix is mapped to
+     * @throws org.xml.sax.SAXException the client may throw
+     *            an exception during processing
+     * @see #endPrefixMapping
+     * @see #startElement
+     */
+    public void startPrefixMapping (String prefix, String uri)
+    throws SAXException;
+
+
+    /**
+     * End the scope of a prefix-URI mapping.
+     *
+     * <p>See {@link #startPrefixMapping startPrefixMapping} for 
+     * details.  These events will always occur immediately after the
+     * corresponding {@link #endElement endElement} event, but the order of 
+     * {@link #endPrefixMapping endPrefixMapping} events is not otherwise
+     * guaranteed.</p>
+     *
+     * @param prefix the prefix that was being mapped.
+     *    This is the empty string when a default mapping scope ends.
+     * @throws org.xml.sax.SAXException the client may throw
+     *            an exception during processing
+     * @see #startPrefixMapping
+     * @see #endElement
+     */
+    public void endPrefixMapping (String prefix)
+    throws SAXException;
+
+
+    /**
+     * Receive notification of the beginning of an element.
+     *
+     * <p>The Parser will invoke this method at the beginning of every
+     * element in the XML document; there will be a corresponding
+     * {@link #endElement endElement} event for every startElement event
+     * (even when the element is empty). All of the element's content will be
+     * reported, in order, before the corresponding endElement
+     * event.</p>
+     *
+     * <p>This event allows up to three name components for each
+     * element:</p>
+     *
+     * <ol>
+     * <li>the Namespace URI;</li>
+     * <li>the local name; and</li>
+     * <li>the qualified (prefixed) name.</li>
+     * </ol>
+     *
+     * <p>Any or all of these may be provided, depending on the
+     * values of the <var>http://xml.org/sax/features/namespaces</var>
+     * and the <var>http://xml.org/sax/features/namespace-prefixes</var>
+     * properties:</p>
+     *
+     * <ul>
+     * <li>the Namespace URI and local name are required when 
+     * the namespaces property is <var>true</var> (the default), and are
+     * optional when the namespaces property is <var>false</var> (if one is
+     * specified, both must be);</li>
+     * <li>the qualified name is required when the namespace-prefixes property
+     * is <var>true</var>, and is optional when the namespace-prefixes property
+     * is <var>false</var> (the default).</li>
+     * </ul>
+     *
+     * <p>Note that the attribute list provided will contain only
+     * attributes with explicit values (specified or defaulted):
+     * #IMPLIED attributes will be omitted.  The attribute list
+     * will contain attributes used for Namespace declarations
+     * (xmlns* attributes) only if the
+     * <code>http://xml.org/sax/features/namespace-prefixes</code>
+     * property is true (it is false by default, and support for a 
+     * true value is optional).</p>
+     *
+     * <p>Like {@link #characters characters()}, attribute values may have
+     * characters that need more than one <code>char</code> value.  </p>
+     *
+     * @param uri the Namespace URI, or the empty string if the
+     *        element has no Namespace URI or if Namespace
+     *        processing is not being performed
+     * @param localName the local name (without prefix), or the
+     *        empty string if Namespace processing is not being
+     *        performed
+     * @param qName the qualified name (with prefix), or the
+     *        empty string if qualified names are not available
+     * @param atts the attributes attached to the element.  If
+     *        there are no attributes, it shall be an empty
+     *        Attributes object.  The value of this object after
+     *        startElement returns is undefined
+     * @throws org.xml.sax.SAXException any SAX exception, possibly
+     *            wrapping another exception
+     * @see #endElement
+     * @see org.xml.sax.Attributes
+     * @see org.xml.sax.helpers.AttributesImpl
+     */
+    public void startElement (String uri, String localName,
+                  String qName, Attributes atts)
+    throws SAXException;
+
+
+    /**
+     * Receive notification of the end of an element.
+     *
+     * <p>The SAX parser will invoke this method at the end of every
+     * element in the XML document; there will be a corresponding
+     * {@link #startElement startElement} event for every endElement 
+     * event (even when the element is empty).</p>
+     *
+     * <p>For information on the names, see startElement.</p>
+     *
+     * @param uri the Namespace URI, or the empty string if the
+     *        element has no Namespace URI or if Namespace
+     *        processing is not being performed
+     * @param localName the local name (without prefix), or the
+     *        empty string if Namespace processing is not being
+     *        performed
+     * @param qName the qualified XML name (with prefix), or the
+     *        empty string if qualified names are not available
+     * @throws org.xml.sax.SAXException any SAX exception, possibly
+     *            wrapping another exception
+     */
+    public void endElement (String uri, String localName,
+                String qName)
+    throws SAXException;
+
+
+    /**
+     * Receive notification of character data.
+     *
+     * <p>The Parser will call this method to report each chunk of
+     * character data.  SAX parsers may return all contiguous character
+     * data in a single chunk, or they may split it into several
+     * chunks; however, all of the characters in any single event
+     * must come from the same external entity so that the Locator
+     * provides useful information.</p>
+     *
+     * <p>The application must not attempt to read from the array
+     * outside of the specified range.</p>
+     *
+     * <p>Individual characters may consist of more than one Java
+     * <code>char</code> value.  There are two important cases where this
+     * happens, because characters can't be represented in just sixteen bits.
+     * In one case, characters are represented in a <em>Surrogate Pair</em>,
+     * using two special Unicode values. Such characters are in the so-called
+     * "Astral Planes", with a code point above U+FFFF.  A second case involves
+     * composite characters, such as a base character combining with one or
+     * more accent characters. </p>
+     *
+     * <p> Your code should not assume that algorithms using
+     * <code>char</code>-at-a-time idioms will be working in character
+     * units; in some cases they will split characters.  This is relevant
+     * wherever XML permits arbitrary characters, such as attribute values,
+     * processing instruction data, and comments as well as in data reported
+     * from this method.  It's also generally relevant whenever Java code
+     * manipulates internationalized text; the issue isn't unique to XML.</p>
+     *
+     * <p>Note that some parsers will report whitespace in element
+     * content using the {@link #ignorableWhitespace ignorableWhitespace}
+     * method rather than this one (validating parsers <em>must</em> 
+     * do so).</p>
+     *
+     * @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 org.xml.sax.SAXException any SAX exception, possibly
+     *            wrapping another exception
+     * @see #ignorableWhitespace 
+     * @see org.xml.sax.Locator
+     */
+    public void characters (char ch[], int start, int length)
+    throws SAXException;
+
+
+    /**
+     * Receive notification of ignorable whitespace in element content.
+     *
+     * <p>Validating Parsers must use this method to report each chunk
+     * of whitespace in element content (see the W3C XML 1.0
+     * recommendation, section 2.10): non-validating parsers may also
+     * use this method if they are capable of parsing and using
+     * content models.</p>
+     *
+     * <p>SAX parsers may return all contiguous whitespace in a single
+     * chunk, or they may split it into several chunks; however, all of
+     * the characters in any single event must come from the same
+     * external entity, so that the Locator provides useful
+     * information.</p>
+     *
+     * <p>The application must not attempt to read from the array
+     * outside of the specified range.</p>
+     *
+     * @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 org.xml.sax.SAXException any SAX exception, possibly
+     *            wrapping another exception
+     * @see #characters
+     */
+    public void ignorableWhitespace (char ch[], int start, int length)
+    throws SAXException;
+
+
+    /**
+     * Receive notification of a processing instruction.
+     *
+     * <p>The Parser will invoke this method once for each processing
+     * instruction found: note that processing instructions may occur
+     * before or after the main document element.</p>
+     *
+     * <p>A SAX parser must never report an XML declaration (XML 1.0,
+     * section 2.8) or a text declaration (XML 1.0, section 4.3.1)
+     * using this method.</p>
+     *
+     * <p>Like {@link #characters characters()}, processing instruction
+     * data may have characters that need more than one <code>char</code>
+     * value. </p>
+     *
+     * @param target the processing instruction target
+     * @param data the processing instruction data, or null if
+     *        none was supplied.  The data does not include any
+     *        whitespace separating it from the target
+     * @throws org.xml.sax.SAXException any SAX exception, possibly
+     *            wrapping another exception
+     */
+    public void processingInstruction (String target, String data)
+    throws SAXException;
+
+
+    /**
+     * Receive notification of a skipped entity.
+     * This is not called for entity references within markup constructs
+     * such as element start tags or markup declarations.  (The XML
+     * recommendation requires reporting skipped external entities.
+     * SAX also reports internal entity expansion/non-expansion, except
+     * within markup constructs.)
+     *
+     * <p>The Parser will invoke this method each time the entity is
+     * skipped.  Non-validating processors may skip entities if they
+     * have not seen the declarations (because, for example, the
+     * entity was declared in an external DTD subset).  All processors
+     * may skip external entities, depending on the values of the
+     * <code>http://xml.org/sax/features/external-general-entities</code>
+     * and the
+     * <code>http://xml.org/sax/features/external-parameter-entities</code>
+     * properties.</p>
+     *
+     * @param name the name of the skipped entity.  If it is a 
+     *        parameter entity, the name will begin with '%', and if
+     *        it is the external DTD subset, it will be the string
+     *        "[dtd]"
+     * @throws org.xml.sax.SAXException any SAX exception, possibly
+     *            wrapping another exception
+     */
+    public void skippedEntity (String name)
+    throws SAXException;
+}
+
+// end of ContentHandler.java
diff --git a/xml/src/main/java/org/xml/sax/DTDHandler.java b/xml/src/main/java/org/xml/sax/DTDHandler.java
new file mode 100644
index 0000000..13d5eee
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/DTDHandler.java
@@ -0,0 +1,117 @@
+// SAX DTD handler.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: DTDHandler.java,v 1.8 2002/01/30 21:13:43 dbrownell Exp $
+
+package org.xml.sax;
+
+/**
+ * Receive notification of basic DTD-related events.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>If a SAX application needs information about notations and
+ * unparsed entities, then the application implements this 
+ * interface and registers an instance with the SAX parser using 
+ * the parser's setDTDHandler method.  The parser uses the 
+ * instance to report notation and unparsed entity declarations to 
+ * the application.</p>
+ *
+ * <p>Note that this interface includes only those DTD events that
+ * the XML recommendation <em>requires</em> processors to report:
+ * notation and unparsed entity declarations.</p>
+ *
+ * <p>The SAX parser may report these events in any order, regardless
+ * of the order in which the notations and unparsed entities were
+ * declared; however, all DTD events must be reported after the
+ * document handler's startDocument event, and before the first
+ * startElement event.
+ * (If the {@link org.xml.sax.ext.LexicalHandler LexicalHandler} is
+ * used, these events must also be reported before the endDTD event.)
+ * </p>
+ *
+ * <p>It is up to the application to store the information for 
+ * future use (perhaps in a hash table or object tree).
+ * If the application encounters attributes of type "NOTATION",
+ * "ENTITY", or "ENTITIES", it can use the information that it
+ * obtained through this interface to find the entity and/or
+ * notation corresponding with the attribute value.</p>
+ *
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.XMLReader#setDTDHandler
+ */
+public interface DTDHandler {
+    
+    
+    /**
+     * Receive notification of a notation declaration event.
+     *
+     * <p>It is up to the application to record the notation for later
+     * reference, if necessary;
+     * notations may appear as attribute values and in unparsed entity
+     * declarations, and are sometime used with processing instruction
+     * target names.</p>
+     *
+     * <p>At least one of publicId and systemId must be non-null.
+     * If a system identifier is present, and it is a URL, the SAX
+     * parser must resolve it fully before passing it to the
+     * application through this event.</p>
+     *
+     * <p>There is no guarantee that the notation declaration will be
+     * reported before any unparsed entities that use it.</p>
+     *
+     * @param name The notation name.
+     * @param publicId The notation's public identifier, or null if
+     *        none was given.
+     * @param systemId The notation's system identifier, or null if
+     *        none was given.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see #unparsedEntityDecl
+     * @see org.xml.sax.Attributes
+     */
+    public abstract void notationDecl (String name,
+                       String publicId,
+                       String systemId)
+    throws SAXException;
+    
+    
+    /**
+     * Receive notification of an unparsed entity declaration event.
+     *
+     * <p>Note that the notation name corresponds to a notation
+     * reported by the {@link #notationDecl notationDecl} event.  
+     * It is up to the application to record the entity for later 
+     * reference, if necessary;
+     * unparsed entities may appear as attribute values. 
+     * </p>
+     *
+     * <p>If the system identifier is a URL, the parser must resolve it
+     * fully before passing it to the application.</p>
+     *
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @param name The unparsed entity's name.
+     * @param publicId The entity's public identifier, or null if none
+     *        was given.
+     * @param systemId The entity's system identifier.
+     * @param notationName The name of the associated notation.
+     * @see #notationDecl
+     * @see org.xml.sax.Attributes
+     */
+    public abstract void unparsedEntityDecl (String name,
+                         String publicId,
+                         String systemId,
+                         String notationName)
+    throws SAXException;
+    
+}
+
+// end of DTDHandler.java
diff --git a/xml/src/main/java/org/xml/sax/DocumentHandler.java b/xml/src/main/java/org/xml/sax/DocumentHandler.java
new file mode 100644
index 0000000..500fe4c
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/DocumentHandler.java
@@ -0,0 +1,232 @@
+// SAX document handler.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: DocumentHandler.java,v 1.6 2002/01/30 21:13:43 dbrownell Exp $
+
+package org.xml.sax;
+
+/**
+ * Receive notification of general document events.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This was the main event-handling interface for SAX1; in
+ * SAX2, it has been replaced by {@link org.xml.sax.ContentHandler
+ * ContentHandler}, which provides Namespace support and reporting
+ * of skipped entities.  This interface is included in SAX2 only
+ * to support legacy SAX1 applications.</p>
+ *
+ * <p>The order of events in this interface is very important, and
+ * mirrors the order of information in the document itself.  For
+ * example, all of an element's content (character data, processing
+ * instructions, and/or subelements) will appear, in order, between
+ * the startElement event and the corresponding endElement event.</p>
+ *
+ * <p>Application writers who do not want to implement the entire
+ * interface can derive a class from HandlerBase, which implements
+ * the default functionality; parser writers can instantiate
+ * HandlerBase to obtain a default handler.  The application can find
+ * the location of any document event using the Locator interface
+ * supplied by the Parser through the setDocumentLocator method.</p>
+ *
+ * @deprecated This interface has been replaced by the SAX2
+ *             {@link org.xml.sax.ContentHandler ContentHandler}
+ *             interface, which includes Namespace support.
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.Parser#setDocumentHandler
+ * @see org.xml.sax.Locator
+ * @see org.xml.sax.HandlerBase
+ */
+public interface DocumentHandler {
+    
+    
+    /**
+     * Receive an object for locating the origin of SAX document events.
+     *
+     * <p>SAX parsers are strongly encouraged (though not absolutely
+     * required) to supply a locator: if it does so, it must supply
+     * the locator to the application by invoking this method before
+     * invoking any of the other methods in the DocumentHandler
+     * interface.</p>
+     *
+     * <p>The locator allows the application to determine the end
+     * position of any document-related event, even if the parser is
+     * not reporting an error.  Typically, the application will
+     * use this information for reporting its own errors (such as
+     * character content that does not match an application's
+     * business rules).  The information returned by the locator
+     * is probably not sufficient for use with a search engine.</p>
+     *
+     * <p>Note that the locator will return correct information only
+     * during the invocation of the events in this interface.  The
+     * application should not attempt to use it at any other time.</p>
+     *
+     * @param locator An object that can return the location of
+     *                any SAX document event.
+     * @see org.xml.sax.Locator
+     */
+    public abstract void setDocumentLocator (Locator locator);
+    
+    
+    /**
+     * Receive notification of the beginning of a document.
+     *
+     * <p>The SAX parser will invoke this method only once, before any
+     * other methods in this interface or in DTDHandler (except for
+     * setDocumentLocator).</p>
+     *
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     */
+    public abstract void startDocument ()
+    throws SAXException;
+    
+    
+    /**
+     * Receive notification of the end of a document.
+     *
+     * <p>The SAX parser will invoke this method only once, and it will
+     * be the last method invoked during the parse.  The parser shall
+     * not invoke this method until it has either abandoned parsing
+     * (because of an unrecoverable error) or reached the end of
+     * input.</p>
+     *
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     */
+    public abstract void endDocument ()
+    throws SAXException;
+    
+    
+    /**
+     * Receive notification of the beginning of an element.
+     *
+     * <p>The Parser will invoke this method at the beginning of every
+     * element in the XML document; there will be a corresponding
+     * endElement() event for every startElement() event (even when the
+     * element is empty). All of the element's content will be
+     * reported, in order, before the corresponding endElement()
+     * event.</p>
+     *
+     * <p>If the element name has a namespace prefix, the prefix will
+     * still be attached.  Note that the attribute list provided will
+     * contain only attributes with explicit values (specified or
+     * defaulted): #IMPLIED attributes will be omitted.</p>
+     *
+     * @param name The element type name.
+     * @param atts The attributes attached to the element, if any.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see #endElement
+     * @see org.xml.sax.AttributeList 
+     */
+    public abstract void startElement (String name, AttributeList atts)
+    throws SAXException;
+    
+    
+    /**
+     * Receive notification of the end of an element.
+     *
+     * <p>The SAX parser will invoke this method at the end of every
+     * element in the XML document; there will be a corresponding
+     * startElement() event for every endElement() event (even when the
+     * element is empty).</p>
+     *
+     * <p>If the element name has a namespace prefix, the prefix will
+     * still be attached to the name.</p>
+     *
+     * @param name The element type name
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     */
+    public abstract void endElement (String name)
+    throws SAXException;
+    
+    
+    /**
+     * Receive notification of character data.
+     *
+     * <p>The Parser will call this method to report each chunk of
+     * character data.  SAX parsers may return all contiguous character
+     * data in a single chunk, or they may split it into several
+     * chunks; however, all of the characters in any single event
+     * must come from the same external entity, so that the Locator
+     * provides useful information.</p>
+     *
+     * <p>The application must not attempt to read from the array
+     * outside of the specified range.</p>
+     *
+     * <p>Note that some parsers will report whitespace using the
+     * ignorableWhitespace() method rather than this one (validating
+     * parsers must do so).</p>
+     *
+     * @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.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see #ignorableWhitespace 
+     * @see org.xml.sax.Locator
+     */
+    public abstract void characters (char ch[], int start, int length)
+    throws SAXException;
+    
+    
+    /**
+     * Receive notification of ignorable whitespace in element content.
+     *
+     * <p>Validating Parsers must use this method to report each chunk
+     * of ignorable whitespace (see the W3C XML 1.0 recommendation,
+     * section 2.10): non-validating parsers may also use this method
+     * if they are capable of parsing and using content models.</p>
+     *
+     * <p>SAX parsers may return all contiguous whitespace in a single
+     * chunk, or they may split it into several chunks; however, all of
+     * the characters in any single event must come from the same
+     * external entity, so that the Locator provides useful
+     * information.</p>
+     *
+     * <p>The application must not attempt to read from the array
+     * outside of the specified range.</p>
+     *
+     * @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.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see #characters
+     */
+    public abstract void ignorableWhitespace (char ch[], int start, int length)
+    throws SAXException;
+    
+    
+    /**
+     * Receive notification of a processing instruction.
+     *
+     * <p>The Parser will invoke this method once for each processing
+     * instruction found: note that processing instructions may occur
+     * before or after the main document element.</p>
+     *
+     * <p>A SAX parser should never report an XML declaration (XML 1.0,
+     * section 2.8) or a text declaration (XML 1.0, section 4.3.1)
+     * using this method.</p>
+     *
+     * @param target The processing instruction target.
+     * @param data The processing instruction data, or null if
+     *        none was supplied.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     */
+    public abstract void processingInstruction (String target, String data)
+    throws SAXException;
+    
+}
+
+// end of DocumentHandler.java
diff --git a/xml/src/main/java/org/xml/sax/EntityResolver.java b/xml/src/main/java/org/xml/sax/EntityResolver.java
new file mode 100644
index 0000000..06ac725
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/EntityResolver.java
@@ -0,0 +1,119 @@
+// SAX entity resolver.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: EntityResolver.java,v 1.10 2002/01/30 21:13:44 dbrownell Exp $
+
+package org.xml.sax;
+
+import java.io.IOException;
+
+
+/**
+ * Basic interface for resolving entities.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>If a SAX application needs to implement customized handling
+ * for external entities, it must implement this interface and
+ * register an instance with the SAX driver using the
+ * {@link org.xml.sax.XMLReader#setEntityResolver setEntityResolver}
+ * method.</p>
+ *
+ * <p>The XML reader will then allow the application to intercept any
+ * external entities (including the external DTD subset and external
+ * parameter entities, if any) before including them.</p>
+ *
+ * <p>Many SAX applications will not need to implement this interface,
+ * but it will be especially useful for applications that build
+ * XML documents from databases or other specialised input sources,
+ * or for applications that use URI types other than URLs.</p>
+ *
+ * <p>The following resolver would provide the application
+ * with a special character stream for the entity with the system
+ * identifier "http://www.myhost.com/today":</p>
+ *
+ * <pre>
+ * import org.xml.sax.EntityResolver;
+ * import org.xml.sax.InputSource;
+ *
+ * public class MyResolver implements EntityResolver {
+ *   public InputSource resolveEntity (String publicId, String systemId)
+ *   {
+ *     if (systemId.equals("http://www.myhost.com/today")) {
+ *              // return a special input source
+ *       MyReader reader = new MyReader();
+ *       return new InputSource(reader);
+ *     } else {
+ *              // use the default behaviour
+ *       return null;
+ *     }
+ *   }
+ * }
+ * </pre>
+ *
+ * <p>The application can also use this interface to redirect system
+ * identifiers to local URIs or to look up replacements in a catalog
+ * (possibly by using the public identifier).</p>
+ *
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.XMLReader#setEntityResolver
+ * @see org.xml.sax.InputSource
+ */
+public interface EntityResolver {
+    
+    
+    /**
+     * Allow the application to resolve external entities.
+     *
+     * <p>The parser will call this method before opening any external
+     * entity except the top-level document entity.  Such entities include
+     * the external DTD subset and external parameter entities referenced
+     * within the DTD (in either case, only if the parser reads external
+     * parameter entities), and external general entities referenced
+     * within the document element (if the parser reads external general
+     * entities).  The application may request that the parser locate
+     * the entity itself, that it use an alternative URI, or that it
+     * use data provided by the application (as a character or byte
+     * input stream).</p>
+     *
+     * <p>Application writers can use this method to redirect external
+     * system identifiers to secure and/or local URIs, to look up
+     * public identifiers in a catalogue, or to read an entity from a
+     * database or other input source (including, for example, a dialog
+     * box).  Neither XML nor SAX specifies a preferred policy for using
+     * public or system IDs to resolve resources.  However, SAX specifies
+     * how to interpret any InputSource returned by this method, and that
+     * if none is returned, then the system ID will be dereferenced as
+     * a URL.  </p>
+     *
+     * <p>If the system identifier is a URL, the SAX parser must
+     * resolve it fully before reporting it to the application.</p>
+     *
+     * @param publicId The public identifier of the external entity
+     *        being referenced, or null if none was supplied.
+     * @param systemId The system identifier of the external entity
+     *        being referenced.
+     * @return An InputSource object describing the new input source,
+     *         or null to request that the parser open a regular
+     *         URI connection to the system identifier.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @exception java.io.IOException A Java-specific IO exception,
+     *            possibly the result of creating a new InputStream
+     *            or Reader for the InputSource.
+     * @see org.xml.sax.InputSource
+     */
+    public abstract InputSource resolveEntity (String publicId,
+                           String systemId)
+    throws SAXException, IOException;
+    
+}
+
+// end of EntityResolver.java
diff --git a/xml/src/main/java/org/xml/sax/ErrorHandler.java b/xml/src/main/java/org/xml/sax/ErrorHandler.java
new file mode 100644
index 0000000..e4e4206
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/ErrorHandler.java
@@ -0,0 +1,139 @@
+// SAX error handler.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: ErrorHandler.java,v 1.10 2004/03/08 13:01:00 dmegginson Exp $
+
+package org.xml.sax;
+
+
+/**
+ * Basic interface for SAX error handlers.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>If a SAX application needs to implement customized error
+ * handling, it must implement this interface and then register an
+ * instance with the XML reader using the
+ * {@link org.xml.sax.XMLReader#setErrorHandler setErrorHandler}
+ * method.  The parser will then report all errors and warnings
+ * through this interface.</p>
+ *
+ * <p><strong>WARNING:</strong> If an application does <em>not</em>
+ * register an ErrorHandler, XML parsing errors will go unreported,
+ * except that <em>SAXParseException</em>s will be thrown for fatal errors.
+ * In order to detect validity errors, an ErrorHandler that does something
+ * with {@link #error error()} calls must be registered.</p>
+ *
+ * <p>For XML processing errors, a SAX driver must use this interface 
+ * in preference to throwing an exception: it is up to the application 
+ * to decide whether to throw an exception for different types of 
+ * errors and warnings.  Note, however, that there is no requirement that 
+ * the parser continue to report additional errors after a call to 
+ * {@link #fatalError fatalError}.  In other words, a SAX driver class 
+ * may throw an exception after reporting any fatalError.
+ * Also parsers may throw appropriate exceptions for non-XML errors.
+ * For example, {@link XMLReader#parse XMLReader.parse()} would throw
+ * an IOException for errors accessing entities or the document.</p>
+ *
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1+ (sax2r3pre1)
+ * @see org.xml.sax.XMLReader#setErrorHandler
+ * @see org.xml.sax.SAXParseException 
+ */
+public interface ErrorHandler {
+    
+    
+    /**
+     * Receive notification of a warning.
+     *
+     * <p>SAX parsers will use this method to report conditions that
+     * are not errors or fatal errors as defined by the XML
+     * recommendation.  The default behaviour is to take no
+     * action.</p>
+     *
+     * <p>The SAX parser must continue to provide normal parsing events
+     * after invoking this method: it should still be possible for the
+     * application to process the document through to the end.</p>
+     *
+     * <p>Filters may use this method to report other, non-XML warnings
+     * as well.</p>
+     *
+     * @param exception The warning information encapsulated in a
+     *                  SAX parse exception.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.SAXParseException 
+     */
+    public abstract void warning (SAXParseException exception)
+    throws SAXException;
+    
+    
+    /**
+     * Receive notification of a recoverable error.
+     *
+     * <p>This corresponds to the definition of "error" in section 1.2
+     * of the W3C XML 1.0 Recommendation.  For example, a validating
+     * parser would use this callback to report the violation of a
+     * validity constraint.  The default behaviour is to take no
+     * action.</p>
+     *
+     * <p>The SAX parser must continue to provide normal parsing
+     * events after invoking this method: it should still be possible
+     * for the application to process the document through to the end.
+     * If the application cannot do so, then the parser should report
+     * a fatal error even if the XML recommendation does not require
+     * it to do so.</p>
+     *
+     * <p>Filters may use this method to report other, non-XML errors
+     * as well.</p>
+     *
+     * @param exception The error information encapsulated in a
+     *                  SAX parse exception.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.SAXParseException 
+     */
+    public abstract void error (SAXParseException exception)
+    throws SAXException;
+    
+    
+    /**
+     * Receive notification of a non-recoverable error.
+     *
+     * <p><strong>There is an apparent contradiction between the
+     * documentation for this method and the documentation for {@link
+     * org.xml.sax.ContentHandler#endDocument}.  Until this ambiguity
+     * is resolved in a future major release, clients should make no
+     * assumptions about whether endDocument() will or will not be
+     * invoked when the parser has reported a fatalError() or thrown
+     * an exception.</strong></p>
+     *
+     * <p>This corresponds to the definition of "fatal error" in
+     * section 1.2 of the W3C XML 1.0 Recommendation.  For example, a
+     * parser would use this callback to report the violation of a
+     * well-formedness constraint.</p>
+     *
+     * <p>The application must assume that the document is unusable
+     * after the parser has invoked this method, and should continue
+     * (if at all) only for the sake of collecting additional error
+     * messages: in fact, SAX parsers are free to stop reporting any
+     * other events once this method has been invoked.</p>
+     *
+     * @param exception The error information encapsulated in a
+     *                  SAX parse exception.  
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.SAXParseException
+     */
+    public abstract void fatalError (SAXParseException exception)
+    throws SAXException;
+    
+}
+
+// end of ErrorHandler.java
diff --git a/xml/src/main/java/org/xml/sax/HandlerBase.java b/xml/src/main/java/org/xml/sax/HandlerBase.java
new file mode 100644
index 0000000..15ea2d4
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/HandlerBase.java
@@ -0,0 +1,369 @@
+// SAX default handler base class.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: HandlerBase.java,v 1.7 2004/04/26 17:34:34 dmegginson Exp $
+
+package org.xml.sax;
+
+/**
+ * Default base class for handlers.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This class implements the default behaviour for four SAX1
+ * interfaces: EntityResolver, DTDHandler, DocumentHandler,
+ * and ErrorHandler.  It is now obsolete, but is included in SAX2 to
+ * support legacy SAX1 applications.  SAX2 applications should use
+ * the {@link org.xml.sax.helpers.DefaultHandler DefaultHandler}
+ * class instead.</p>
+ *
+ * <p>Application writers can extend this class when they need to
+ * implement only part of an interface; parser writers can
+ * instantiate this class to provide default handlers when the
+ * application has not supplied its own.</p>
+ *
+ * <p>Note that the use of this class is optional.</p>
+ *
+ * @deprecated This class works with the deprecated
+ *             {@link org.xml.sax.DocumentHandler DocumentHandler}
+ *             interface.  It has been replaced by the SAX2
+ *             {@link org.xml.sax.helpers.DefaultHandler DefaultHandler}
+ *             class.
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.EntityResolver
+ * @see org.xml.sax.DTDHandler
+ * @see org.xml.sax.DocumentHandler
+ * @see org.xml.sax.ErrorHandler
+ */
+public class HandlerBase
+    implements EntityResolver, DTDHandler, DocumentHandler, ErrorHandler
+{
+    
+
+    ////////////////////////////////////////////////////////////////////
+    // Default implementation of the EntityResolver interface.
+    ////////////////////////////////////////////////////////////////////
+    
+    /**
+     * Resolve an external entity.
+     *
+     * <p>Always return null, so that the parser will use the system
+     * identifier provided in the XML document.  This method implements
+     * the SAX default behaviour: application writers can override it
+     * in a subclass to do special translations such as catalog lookups
+     * or URI redirection.</p>
+     *
+     * @param publicId The public identifer, or null if none is
+     *                 available.
+     * @param systemId The system identifier provided in the XML 
+     *                 document.
+     * @return The new input source, or null to require the
+     *         default behaviour.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.EntityResolver#resolveEntity
+     */
+    public InputSource resolveEntity (String publicId, String systemId)
+    throws SAXException
+    {
+    return null;
+    }
+    
+    
+
+    ////////////////////////////////////////////////////////////////////
+    // Default implementation of DTDHandler interface.
+    ////////////////////////////////////////////////////////////////////
+    
+    
+    /**
+     * Receive notification of a notation declaration.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass if they wish to keep track of the notations
+     * declared in a document.</p>
+     *
+     * @param name The notation name.
+     * @param publicId The notation public identifier, or null if not
+     *                 available.
+     * @param systemId The notation system identifier.
+     * @see org.xml.sax.DTDHandler#notationDecl
+     */
+    public void notationDecl (String name, String publicId, String systemId)
+    {
+    // no op
+    }
+    
+    
+    /**
+     * Receive notification of an unparsed entity declaration.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to keep track of the unparsed entities
+     * declared in a document.</p>
+     *
+     * @param name The entity name.
+     * @param publicId The entity public identifier, or null if not
+     *                 available.
+     * @param systemId The entity system identifier.
+     * @param notationName The name of the associated notation.
+     * @see org.xml.sax.DTDHandler#unparsedEntityDecl
+     */
+    public void unparsedEntityDecl (String name, String publicId,
+                    String systemId, String notationName)
+    {
+    // no op
+    }
+    
+    
+
+    ////////////////////////////////////////////////////////////////////
+    // Default implementation of DocumentHandler interface.
+    ////////////////////////////////////////////////////////////////////
+    
+    
+    /**
+     * Receive a Locator object for document events.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass if they wish to store the locator for use
+     * with other document events.</p>
+     *
+     * @param locator A locator for all SAX document events.
+     * @see org.xml.sax.DocumentHandler#setDocumentLocator
+     * @see org.xml.sax.Locator
+     */
+    public void setDocumentLocator (Locator locator)
+    {
+    // no op
+    }
+    
+    
+    /**
+     * Receive notification of the beginning of the document.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions at the beginning
+     * of a document (such as allocating the root node of a tree or
+     * creating an output file).</p>
+     *
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.DocumentHandler#startDocument
+     */
+    public void startDocument ()
+    throws SAXException
+    {
+    // no op
+    }
+    
+    
+    /**
+     * Receive notification of the end of the document.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions at the beginning
+     * of a document (such as finalising a tree or closing an output
+     * file).</p>
+     *
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.DocumentHandler#endDocument
+     */
+    public void endDocument ()
+    throws SAXException
+    {
+    // no op
+    }
+    
+    
+    /**
+     * Receive notification of the start of an element.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions at the start of
+     * each element (such as allocating a new tree node or writing
+     * output to a file).</p>
+     *
+     * @param name The element type name.
+     * @param attributes The specified or defaulted attributes.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.DocumentHandler#startElement
+     */
+    public void startElement (String name, AttributeList attributes)
+    throws SAXException
+    {
+    // no op
+    }
+    
+    
+    /**
+     * Receive notification of the end of an element.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions at the end of
+     * each element (such as finalising a tree node or writing
+     * output to a file).</p>
+     *
+     * @param name the element name
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.DocumentHandler#endElement
+     */
+    public void endElement (String name)
+    throws SAXException
+    {
+    // no op
+    }
+    
+    
+    /**
+     * Receive notification of character data inside an element.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method to take specific actions for each chunk of character data
+     * (such as adding the data to a node or buffer, or printing it to
+     * a file).</p>
+     *
+     * @param ch The characters.
+     * @param start The start position in the character array.
+     * @param length The number of characters to use from the
+     *               character array.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.DocumentHandler#characters
+     */
+    public void characters (char ch[], int start, int length)
+    throws SAXException
+    {
+    // no op
+    }
+    
+    
+    /**
+     * Receive notification of ignorable whitespace in element content.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method to take specific actions for each chunk of ignorable
+     * whitespace (such as adding data to a node or buffer, or printing
+     * it to a file).</p>
+     *
+     * @param ch The whitespace characters.
+     * @param start The start position in the character array.
+     * @param length The number of characters to use from the
+     *               character array.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.DocumentHandler#ignorableWhitespace
+     */
+    public void ignorableWhitespace (char ch[], int start, int length)
+    throws SAXException
+    {
+    // no op
+    }
+    
+    
+    /**
+     * Receive notification of a processing instruction.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions for each
+     * processing instruction, such as setting status variables or
+     * invoking other methods.</p>
+     *
+     * @param target The processing instruction target.
+     * @param data The processing instruction data, or null if
+     *             none is supplied.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.DocumentHandler#processingInstruction
+     */
+    public void processingInstruction (String target, String data)
+    throws SAXException
+    {
+    // no op
+    }
+    
+    
+
+    ////////////////////////////////////////////////////////////////////
+    // Default implementation of the ErrorHandler interface.
+    ////////////////////////////////////////////////////////////////////
+    
+    
+    /**
+     * Receive notification of a parser warning.
+     *
+     * <p>The default implementation does nothing.  Application writers
+     * may override this method in a subclass to take specific actions
+     * for each warning, such as inserting the message in a log file or
+     * printing it to the console.</p>
+     *
+     * @param e The warning information encoded as an exception.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ErrorHandler#warning
+     * @see org.xml.sax.SAXParseException
+     */
+    public void warning (SAXParseException e)
+    throws SAXException
+    {
+    // no op
+    }
+    
+    
+    /**
+     * Receive notification of a recoverable parser error.
+     *
+     * <p>The default implementation does nothing.  Application writers
+     * may override this method in a subclass to take specific actions
+     * for each error, such as inserting the message in a log file or
+     * printing it to the console.</p>
+     *
+     * @param e The warning information encoded as an exception.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ErrorHandler#warning
+     * @see org.xml.sax.SAXParseException
+     */
+    public void error (SAXParseException e)
+    throws SAXException
+    {
+    // no op
+    }
+    
+    
+    /**
+     * Report a fatal XML parsing error.
+     *
+     * <p>The default implementation throws a SAXParseException.
+     * Application writers may override this method in a subclass if
+     * they need to take specific actions for each fatal error (such as
+     * collecting all of the errors into a single report): in any case,
+     * the application must stop all regular processing when this
+     * method is invoked, since the document is no longer reliable, and
+     * the parser may no longer report parsing events.</p>
+     *
+     * @param e The error information encoded as an exception.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ErrorHandler#fatalError
+     * @see org.xml.sax.SAXParseException
+     */
+    public void fatalError (SAXParseException e)
+    throws SAXException
+    {
+    throw e;
+    }
+    
+}
+
+// end of HandlerBase.java
diff --git a/xml/src/main/java/org/xml/sax/InputSource.java b/xml/src/main/java/org/xml/sax/InputSource.java
new file mode 100644
index 0000000..b1342ee
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/InputSource.java
@@ -0,0 +1,337 @@
+// SAX input source.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: InputSource.java,v 1.9 2002/01/30 21:13:45 dbrownell Exp $
+
+package org.xml.sax;
+
+import java.io.Reader;
+import java.io.InputStream;
+
+/**
+ * A single input source for an XML entity.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This class allows a SAX application to encapsulate information
+ * about an input source in a single object, which may include
+ * a public identifier, a system identifier, a byte stream (possibly
+ * with a specified encoding), and/or a character stream.</p>
+ *
+ * <p>There are two places that the application can deliver an
+ * input source to the parser: as the argument to the Parser.parse
+ * method, or as the return value of the EntityResolver.resolveEntity
+ * method.</p>
+ *
+ * <p>The SAX parser will use the InputSource object to determine how
+ * to read XML input.  If there is a character stream available, the
+ * parser will read that stream directly, disregarding any text
+ * encoding declaration found in that stream.
+ * If there is no character stream, but there is
+ * a byte stream, the parser will use that byte stream, using the
+ * encoding specified in the InputSource or else (if no encoding is
+ * specified) autodetecting the character encoding using an algorithm
+ * such as the one in the XML specification.  If neither a character
+ * stream nor a
+ * byte stream is available, the parser will attempt to open a URI
+ * connection to the resource identified by the system
+ * identifier.</p>
+ *
+ * <p>An InputSource object belongs to the application: the SAX parser
+ * shall never modify it in any way (it may modify a copy if 
+ * necessary).  However, standard processing of both byte and
+ * character streams is to close them on as part of end-of-parse cleanup,
+ * so applications should not attempt to re-use such streams after they
+ * have been handed to a parser.  </p>
+ *
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.XMLReader#parse(org.xml.sax.InputSource)
+ * @see org.xml.sax.EntityResolver#resolveEntity
+ * @see java.io.InputStream
+ * @see java.io.Reader
+ */
+public class InputSource {
+    
+    /**
+     * Zero-argument default constructor.
+     *
+     * @see #setPublicId
+     * @see #setSystemId
+     * @see #setByteStream
+     * @see #setCharacterStream
+     * @see #setEncoding
+     */
+    public InputSource ()
+    {
+    }
+    
+    
+    /**
+     * Create a new input source with a system identifier.
+     *
+     * <p>Applications may use setPublicId to include a 
+     * public identifier as well, or setEncoding to specify
+     * the character encoding, if known.</p>
+     *
+     * <p>If the system identifier is a URL, it must be fully
+     * resolved (it may not be a relative URL).</p>
+     *
+     * @param systemId The system identifier (URI).
+     * @see #setPublicId
+     * @see #setSystemId
+     * @see #setByteStream
+     * @see #setEncoding
+     * @see #setCharacterStream
+     */
+    public InputSource (String systemId)
+    {
+    setSystemId(systemId);
+    }
+    
+    
+    /**
+     * Create a new input source with a byte stream.
+     *
+     * <p>Application writers should use setSystemId() to provide a base 
+     * for resolving relative URIs, may use setPublicId to include a 
+     * public identifier, and may use setEncoding to specify the object's
+     * character encoding.</p>
+     *
+     * @param byteStream The raw byte stream containing the document.
+     * @see #setPublicId
+     * @see #setSystemId
+     * @see #setEncoding
+     * @see #setByteStream
+     * @see #setCharacterStream
+     */
+    public InputSource (InputStream byteStream)
+    {
+    setByteStream(byteStream);
+    }
+    
+    
+    /**
+     * Create a new input source with a character stream.
+     *
+     * <p>Application writers should use setSystemId() to provide a base 
+     * for resolving relative URIs, and may use setPublicId to include a 
+     * public identifier.</p>
+     *
+     * <p>The character stream shall not include a byte order mark.</p>
+     *
+     * @param characterStream The raw character stream containing the document.
+     * @see #setPublicId
+     * @see #setSystemId
+     * @see #setByteStream
+     * @see #setCharacterStream
+     */
+    public InputSource (Reader characterStream)
+    {
+    setCharacterStream(characterStream);
+    }
+    
+    
+    /**
+     * Set the public identifier for this input source.
+     *
+     * <p>The public identifier is always optional: if the application
+     * writer includes one, it will be provided as part of the
+     * location information.</p>
+     *
+     * @param publicId The public identifier as a string.
+     * @see #getPublicId
+     * @see org.xml.sax.Locator#getPublicId
+     * @see org.xml.sax.SAXParseException#getPublicId
+     */
+    public void setPublicId (String publicId)
+    {
+    this.publicId = publicId;
+    }
+    
+    
+    /**
+     * Get the public identifier for this input source.
+     *
+     * @return The public identifier, or null if none was supplied.
+     * @see #setPublicId
+     */
+    public String getPublicId ()
+    {
+    return publicId;
+    }
+    
+    
+    /**
+     * Set the system identifier for this input source.
+     *
+     * <p>The system identifier is optional if there is a byte stream
+     * or a character stream, but it is still useful to provide one,
+     * since the application can use it to resolve relative URIs
+     * and can include it in error messages and warnings (the parser
+     * will attempt to open a connection to the URI only if
+     * there is no byte stream or character stream specified).</p>
+     *
+     * <p>If the application knows the character encoding of the
+     * object pointed to by the system identifier, it can register
+     * the encoding using the setEncoding method.</p>
+     *
+     * <p>If the system identifier is a URL, it must be fully
+     * resolved (it may not be a relative URL).</p>
+     *
+     * @param systemId The system identifier as a string.
+     * @see #setEncoding
+     * @see #getSystemId
+     * @see org.xml.sax.Locator#getSystemId
+     * @see org.xml.sax.SAXParseException#getSystemId
+     */
+    public void setSystemId (String systemId)
+    {
+    this.systemId = systemId;
+    }
+    
+    
+    /**
+     * Get the system identifier for this input source.
+     *
+     * <p>The getEncoding method will return the character encoding
+     * of the object pointed to, or null if unknown.</p>
+     *
+     * <p>If the system ID is a URL, it will be fully resolved.</p>
+     *
+     * @return The system identifier, or null if none was supplied.
+     * @see #setSystemId
+     * @see #getEncoding
+     */
+    public String getSystemId ()
+    {
+    return systemId;
+    }
+    
+    
+    /**
+     * Set the byte stream for this input source.
+     *
+     * <p>The SAX parser will ignore this if there is also a character
+     * stream specified, but it will use a byte stream in preference
+     * to opening a URI connection itself.</p>
+     *
+     * <p>If the application knows the character encoding of the
+     * byte stream, it should set it with the setEncoding method.</p>
+     *
+     * @param byteStream A byte stream containing an XML document or
+     *        other entity.
+     * @see #setEncoding
+     * @see #getByteStream
+     * @see #getEncoding
+     * @see java.io.InputStream
+     */
+    public void setByteStream (InputStream byteStream)
+    {
+    this.byteStream = byteStream;
+    }
+    
+    
+    /**
+     * Get the byte stream for this input source.
+     *
+     * <p>The getEncoding method will return the character
+     * encoding for this byte stream, or null if unknown.</p>
+     *
+     * @return The byte stream, or null if none was supplied.
+     * @see #getEncoding
+     * @see #setByteStream
+     */
+    public InputStream getByteStream ()
+    {
+    return byteStream;
+    }
+    
+    
+    /** 
+     * Set the character encoding, if known.
+     *
+     * <p>The encoding must be a string acceptable for an
+     * XML encoding declaration (see section 4.3.3 of the XML 1.0
+     * recommendation).</p>
+     *
+     * <p>This method has no effect when the application provides a
+     * character stream.</p>
+     *
+     * @param encoding A string describing the character encoding.
+     * @see #setSystemId
+     * @see #setByteStream
+     * @see #getEncoding
+     */
+    public void setEncoding (String encoding)
+    {
+    this.encoding = encoding;
+    }
+    
+    
+    /**
+     * Get the character encoding for a byte stream or URI.
+     * This value will be ignored when the application provides a
+     * character stream.
+     *
+     * @return The encoding, or null if none was supplied.
+     * @see #setByteStream
+     * @see #getSystemId
+     * @see #getByteStream
+     */
+    public String getEncoding ()
+    {
+    return encoding;
+    }
+    
+    
+    /**
+     * Set the character stream for this input source.
+     *
+     * <p>If there is a character stream specified, the SAX parser
+     * will ignore any byte stream and will not attempt to open
+     * a URI connection to the system identifier.</p>
+     *
+     * @param characterStream The character stream containing the
+     *        XML document or other entity.
+     * @see #getCharacterStream
+     * @see java.io.Reader
+     */
+    public void setCharacterStream (Reader characterStream)
+    {
+    this.characterStream = characterStream;
+    }
+    
+    
+    /**
+     * Get the character stream for this input source.
+     *
+     * @return The character stream, or null if none was supplied.
+     * @see #setCharacterStream
+     */
+    public Reader getCharacterStream ()
+    {
+    return characterStream;
+    }
+    
+    
+
+    ////////////////////////////////////////////////////////////////////
+    // Internal state.
+    ////////////////////////////////////////////////////////////////////
+    
+    private String publicId;
+    private String systemId;
+    private InputStream byteStream;
+    private String encoding;
+    private Reader characterStream;
+    
+}
+
+// end of InputSource.java
diff --git a/xml/src/main/java/org/xml/sax/Locator.java b/xml/src/main/java/org/xml/sax/Locator.java
new file mode 100644
index 0000000..f8f3484
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/Locator.java
@@ -0,0 +1,136 @@
+// SAX locator interface for document events.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: Locator.java,v 1.8 2002/01/30 21:13:47 dbrownell Exp $
+
+package org.xml.sax;
+
+
+/**
+ * Interface for associating a SAX event with a document location.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>If a SAX parser provides location information to the SAX
+ * application, it does so by implementing this interface and then
+ * passing an instance to the application using the content
+ * handler's {@link org.xml.sax.ContentHandler#setDocumentLocator
+ * setDocumentLocator} method.  The application can use the
+ * object to obtain the location of any other SAX event
+ * in the XML source document.</p>
+ *
+ * <p>Note that the results returned by the object will be valid only
+ * during the scope of each callback method: the application
+ * will receive unpredictable results if it attempts to use the
+ * locator at any other time, or after parsing completes.</p>
+ *
+ * <p>SAX parsers are not required to supply a locator, but they are
+ * very strongly encouraged to do so.  If the parser supplies a
+ * locator, it must do so before reporting any other document events.
+ * If no locator has been set by the time the application receives
+ * the {@link org.xml.sax.ContentHandler#startDocument startDocument}
+ * event, the application should assume that a locator is not 
+ * available.</p>
+ *
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.ContentHandler#setDocumentLocator 
+ */
+public interface Locator {
+    
+    
+    /**
+     * Return the public identifier for the current document event.
+     *
+     * <p>The return value is the public identifier of the document
+     * entity or of the external parsed entity in which the markup
+     * triggering the event appears.</p>
+     *
+     * @return A string containing the public identifier, or
+     *         null if none is available.
+     * @see #getSystemId
+     */
+    public abstract String getPublicId ();
+    
+    
+    /**
+     * Return the system identifier for the current document event.
+     *
+     * <p>The return value is the system identifier of the document
+     * entity or of the external parsed entity in which the markup
+     * triggering the event appears.</p>
+     *
+     * <p>If the system identifier is a URL, the parser must resolve it
+     * fully before passing it to the application.  For example, a file
+     * name must always be provided as a <em>file:...</em> URL, and other
+     * kinds of relative URI are also resolved against their bases.</p>
+     *
+     * @return A string containing the system identifier, or null
+     *         if none is available.
+     * @see #getPublicId
+     */
+    public abstract String getSystemId ();
+    
+    
+    /**
+     * Return the line number where the current document event ends.
+     * Lines are delimited by line ends, which are defined in
+     * the XML specification.
+     *
+     * <p><strong>Warning:</strong> The return value from the method
+     * is intended only as an approximation for the sake of diagnostics;
+     * it is not intended to provide sufficient information
+     * to edit the character content of the original XML document.
+     * In some cases, these "line" numbers match what would be displayed
+     * as columns, and in others they may not match the source text
+     * due to internal entity expansion.  </p>
+     *
+     * <p>The return value is an approximation of the line number
+     * in the document entity or external parsed entity where the
+     * markup triggering the event appears.</p>
+     *
+     * <p>If possible, the SAX driver should provide the line position 
+     * of the first character after the text associated with the document 
+     * event.  The first line is line 1.</p>
+     *
+     * @return The line number, or -1 if none is available.
+     * @see #getColumnNumber
+     */
+    public abstract int getLineNumber ();
+    
+    
+    /**
+     * Return the column number where the current document event ends.
+     * This is one-based number of Java <code>char</code> values since
+     * the last line end.
+     *
+     * <p><strong>Warning:</strong> The return value from the method
+     * is intended only as an approximation for the sake of diagnostics;
+     * it is not intended to provide sufficient information
+     * to edit the character content of the original XML document.
+     * For example, when lines contain combining character sequences, wide
+     * characters, surrogate pairs, or bi-directional text, the value may
+     * not correspond to the column in a text editor's display. </p>
+     *
+     * <p>The return value is an approximation of the column number
+     * in the document entity or external parsed entity where the
+     * markup triggering the event appears.</p>
+     *
+     * <p>If possible, the SAX driver should provide the line position 
+     * of the first character after the text associated with the document 
+     * event.  The first column in each line is column 1.</p>
+     *
+     * @return The column number, or -1 if none is available.
+     * @see #getLineNumber
+     */
+    public abstract int getColumnNumber ();
+    
+}
+
+// end of Locator.java
diff --git a/xml/src/main/java/org/xml/sax/Parser.java b/xml/src/main/java/org/xml/sax/Parser.java
new file mode 100644
index 0000000..67a5512
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/Parser.java
@@ -0,0 +1,209 @@
+// SAX parser interface.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: Parser.java,v 1.6 2002/01/30 21:13:47 dbrownell Exp $
+
+package org.xml.sax;
+
+import java.io.IOException;
+import java.util.Locale;
+
+
+/**
+ * Basic interface for SAX (Simple API for XML) parsers.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This was the main event supplier interface for SAX1; it has
+ * been replaced in SAX2 by {@link org.xml.sax.XMLReader XMLReader},
+ * which includes Namespace support and sophisticated configurability
+ * and extensibility.</p>
+ *
+ * <p>All SAX1 parsers must implement this basic interface: it allows
+ * applications to register handlers for different types of events
+ * and to initiate a parse from a URI, or a character stream.</p>
+ *
+ * <p>All SAX1 parsers must also implement a zero-argument constructor
+ * (though other constructors are also allowed).</p>
+ *
+ * <p>SAX1 parsers are reusable but not re-entrant: the application
+ * may reuse a parser object (possibly with a different input source)
+ * once the first parse has completed successfully, but it may not
+ * invoke the parse() methods recursively within a parse.</p>
+ *
+ * @deprecated This interface has been replaced by the SAX2
+ *             {@link org.xml.sax.XMLReader XMLReader}
+ *             interface, which includes Namespace support.
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.EntityResolver
+ * @see org.xml.sax.DTDHandler
+ * @see org.xml.sax.DocumentHandler
+ * @see org.xml.sax.ErrorHandler
+ * @see org.xml.sax.HandlerBase
+ * @see org.xml.sax.InputSource
+ */
+public interface Parser 
+{
+    
+    /**
+     * Allow an application to request a locale for errors and warnings.
+     *
+     * <p>SAX parsers are not required to provide localisation for errors
+     * and warnings; if they cannot support the requested locale,
+     * however, they must throw a SAX exception.  Applications may
+     * not request a locale change in the middle of a parse.</p>
+     *
+     * @param locale A Java Locale object.
+     * @exception org.xml.sax.SAXException Throws an exception
+     *            (using the previous or default locale) if the 
+     *            requested locale is not supported.
+     * @see org.xml.sax.SAXException
+     * @see org.xml.sax.SAXParseException
+     */
+    public abstract void setLocale (Locale locale)
+    throws SAXException;
+    
+    
+    /**
+     * Allow an application to register a custom entity resolver.
+     *
+     * <p>If the application does not register an entity resolver, the
+     * SAX parser will resolve system identifiers and open connections
+     * to entities itself (this is the default behaviour implemented in
+     * HandlerBase).</p>
+     *
+     * <p>Applications may register a new or different entity resolver
+     * in the middle of a parse, and the SAX parser must begin using
+     * the new resolver immediately.</p>
+     *
+     * @param resolver The object for resolving entities.
+     * @see EntityResolver
+     * @see HandlerBase
+     */
+    public abstract void setEntityResolver (EntityResolver resolver);
+    
+    
+    /**
+     * Allow an application to register a DTD event handler.
+     *
+     * <p>If the application does not register a DTD handler, all DTD
+     * events reported by the SAX parser will be silently
+     * ignored (this is the default behaviour implemented by
+     * HandlerBase).</p>
+     *
+     * <p>Applications may register a new or different
+     * handler in the middle of a parse, and the SAX parser must
+     * begin using the new handler immediately.</p>
+     *
+     * @param handler The DTD handler.
+     * @see DTDHandler
+     * @see HandlerBase
+     */
+    public abstract void setDTDHandler (DTDHandler handler);
+    
+    
+    /**
+     * Allow an application to register a document event handler.
+     *
+     * <p>If the application does not register a document handler, all
+     * document events reported by the SAX parser will be silently
+     * ignored (this is the default behaviour implemented by
+     * HandlerBase).</p>
+     *
+     * <p>Applications may register a new or different handler in the
+     * middle of a parse, and the SAX parser must begin using the new
+     * handler immediately.</p>
+     *
+     * @param handler The document handler.
+     * @see DocumentHandler
+     * @see HandlerBase
+     */
+    public abstract void setDocumentHandler (DocumentHandler handler);
+    
+    
+    /**
+     * Allow an application to register an error event handler.
+     *
+     * <p>If the application does not register an error event handler,
+     * all error events reported by the SAX parser will be silently
+     * ignored, except for fatalError, which will throw a SAXException
+     * (this is the default behaviour implemented by HandlerBase).</p>
+     *
+     * <p>Applications may register a new or different handler in the
+     * middle of a parse, and the SAX parser must begin using the new
+     * handler immediately.</p>
+     *
+     * @param handler The error handler.
+     * @see ErrorHandler
+     * @see SAXException
+     * @see HandlerBase
+     */
+    public abstract void setErrorHandler (ErrorHandler handler);
+    
+    
+    /**
+     * Parse an XML document.
+     *
+     * <p>The application can use this method to instruct the SAX parser
+     * to begin parsing an XML document from any valid input
+     * source (a character stream, a byte stream, or a URI).</p>
+     *
+     * <p>Applications may not invoke this method while a parse is in
+     * progress (they should create a new Parser instead for each
+     * additional XML document).  Once a parse is complete, an
+     * application may reuse the same Parser object, possibly with a
+     * different input source.</p>
+     *
+     * @param source The input source for the top-level of the
+     *        XML document.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @exception java.io.IOException An IO exception from the parser,
+     *            possibly from a byte stream or character stream
+     *            supplied by the application.
+     * @see org.xml.sax.InputSource
+     * @see #parse(java.lang.String)
+     * @see #setEntityResolver
+     * @see #setDTDHandler
+     * @see #setDocumentHandler
+     * @see #setErrorHandler
+     */
+    public abstract void parse (InputSource source)
+    throws SAXException, IOException;
+    
+    
+    /**
+     * Parse an XML document from a system identifier (URI).
+     *
+     * <p>This method is a shortcut for the common case of reading a
+     * document from a system identifier.  It is the exact
+     * equivalent of the following:</p>
+     *
+     * <pre>
+     * parse(new InputSource(systemId));
+     * </pre>
+     *
+     * <p>If the system identifier is a URL, it must be fully resolved
+     * by the application before it is passed to the parser.</p>
+     *
+     * @param systemId The system identifier (URI).
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @exception java.io.IOException An IO exception from the parser,
+     *            possibly from a byte stream or character stream
+     *            supplied by the application.
+     * @see #parse(org.xml.sax.InputSource)
+     */
+    public abstract void parse (String systemId)
+    throws SAXException, IOException;
+    
+}
+
+// end of Parser.java
diff --git a/xml/src/main/java/org/xml/sax/SAXException.java b/xml/src/main/java/org/xml/sax/SAXException.java
new file mode 100644
index 0000000..2e5b4cd
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/SAXException.java
@@ -0,0 +1,153 @@
+// SAX exception class.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: SAXException.java,v 1.7 2002/01/30 21:13:48 dbrownell Exp $
+
+package org.xml.sax;
+
+/**
+ * Encapsulate a general SAX error or warning.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This class can contain basic error or warning information from
+ * either the XML parser or the application: a parser writer or
+ * application writer can subclass it to provide additional
+ * functionality.  SAX handlers may throw this exception or
+ * any exception subclassed from it.</p>
+ *
+ * <p>If the application needs to pass through other types of
+ * exceptions, it must wrap those exceptions in a SAXException
+ * or an exception derived from a SAXException.</p>
+ *
+ * <p>If the parser or application needs to include information about a
+ * specific location in an XML document, it should use the
+ * {@link org.xml.sax.SAXParseException SAXParseException} subclass.</p>
+ *
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.SAXParseException
+ */
+public class SAXException extends Exception {
+
+
+    /**
+     * Create a new SAXException.
+     */
+    public SAXException ()
+    {
+    super();
+    this.exception = null;
+    }
+    
+    
+    /**
+     * Create a new SAXException.
+     *
+     * @param message The error or warning message.
+     */
+    public SAXException (String message) {
+    super(message);
+    this.exception = null;
+    }
+    
+    
+    /**
+     * Create a new SAXException wrapping an existing exception.
+     *
+     * <p>The existing exception will be embedded in the new
+     * one, and its message will become the default message for
+     * the SAXException.</p>
+     *
+     * @param e The exception to be wrapped in a SAXException.
+     */
+    public SAXException (Exception e)
+    {
+    super();
+    this.exception = e;
+    }
+    
+    
+    /**
+     * Create a new SAXException from an existing exception.
+     *
+     * <p>The existing exception will be embedded in the new
+     * one, but the new exception will have its own message.</p>
+     *
+     * @param message The detail message.
+     * @param e The exception to be wrapped in a SAXException.
+     */
+    public SAXException (String message, Exception e)
+    {
+    super(message);
+    this.exception = e;
+    }
+    
+    
+    /**
+     * Return a detail message for this exception.
+     *
+     * <p>If there is an embedded exception, and if the SAXException
+     * has no detail message of its own, this method will return
+     * the detail message from the embedded exception.</p>
+     *
+     * @return The error or warning message.
+     */
+    public String getMessage ()
+    {
+    String message = super.getMessage();
+    
+    if (message == null && exception != null) {
+        return exception.getMessage();
+    } else {
+        return message;
+    }
+    }
+    
+    
+    /**
+     * Return the embedded exception, if any.
+     *
+     * @return The embedded exception, or null if there is none.
+     */
+    public Exception getException ()
+    {
+    return exception;
+    }
+
+
+    /**
+     * Override toString to pick up any embedded exception.
+     *
+     * @return A string representation of this exception.
+     */
+    public String toString ()
+    {
+    if (exception != null) {
+        return exception.toString();
+    } else {
+        return super.toString();
+    }
+    }
+    
+    
+    
+    //////////////////////////////////////////////////////////////////////
+    // Internal state.
+    //////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * @serial The embedded exception if tunnelling, or null.
+     */    
+    private Exception exception;
+    
+}
+
+// end of SAXException.java
diff --git a/xml/src/main/java/org/xml/sax/SAXNotRecognizedException.java b/xml/src/main/java/org/xml/sax/SAXNotRecognizedException.java
new file mode 100644
index 0000000..69ba807
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/SAXNotRecognizedException.java
@@ -0,0 +1,53 @@
+// SAXNotRecognizedException.java - unrecognized feature or value.
+// http://www.saxproject.org
+// Written by David Megginson
+// NO WARRANTY!  This class is in the Public Domain.
+// $Id: SAXNotRecognizedException.java,v 1.7 2002/01/30 21:13:48 dbrownell Exp $
+
+package org.xml.sax;
+
+
+/**
+ * Exception class for an unrecognized identifier.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>An XMLReader will throw this exception when it finds an
+ * unrecognized feature or property identifier; SAX applications and
+ * extensions may use this class for other, similar purposes.</p>
+ *
+ * @since SAX 2.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.SAXNotSupportedException
+ */
+public class SAXNotRecognizedException extends SAXException
+{
+
+    /**
+     * Default constructor.
+     */
+    public SAXNotRecognizedException ()
+    {
+    super();
+    }
+
+
+    /**
+     * Construct a new exception with the given message.
+     *
+     * @param message The text message of the exception.
+     */
+    public SAXNotRecognizedException (String message)
+    {
+    super(message);
+    }
+
+}
+
+// end of SAXNotRecognizedException.java
diff --git a/xml/src/main/java/org/xml/sax/SAXNotSupportedException.java b/xml/src/main/java/org/xml/sax/SAXNotSupportedException.java
new file mode 100644
index 0000000..bd5b239
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/SAXNotSupportedException.java
@@ -0,0 +1,53 @@
+// SAXNotSupportedException.java - unsupported feature or value.
+// http://www.saxproject.org
+// Written by David Megginson
+// NO WARRANTY!  This class is in the Public Domain.
+// $Id: SAXNotSupportedException.java,v 1.7 2002/01/30 21:13:48 dbrownell Exp $
+
+package org.xml.sax;
+
+/**
+ * Exception class for an unsupported operation.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>An XMLReader will throw this exception when it recognizes a
+ * feature or property identifier, but cannot perform the requested
+ * operation (setting a state or value).  Other SAX2 applications and
+ * extensions may use this class for similar purposes.</p>
+ *
+ * @since SAX 2.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.SAXNotRecognizedException 
+ */
+public class SAXNotSupportedException extends SAXException
+{
+
+    /**
+     * Construct a new exception with no message.
+     */
+    public SAXNotSupportedException ()
+    {
+    super();
+    }
+
+
+    /**
+     * Construct a new exception with the given message.
+     *
+     * @param message The text message of the exception.
+     */
+    public SAXNotSupportedException (String message)
+    {
+    super(message);
+    }
+
+}
+
+// end of SAXNotSupportedException.java
diff --git a/xml/src/main/java/org/xml/sax/SAXParseException.java b/xml/src/main/java/org/xml/sax/SAXParseException.java
new file mode 100644
index 0000000..a6a93e9
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/SAXParseException.java
@@ -0,0 +1,269 @@
+// SAX exception class.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: SAXParseException.java,v 1.11 2004/04/21 13:05:02 dmegginson Exp $
+
+package org.xml.sax;
+
+/**
+ * Encapsulate an XML parse error or warning.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This exception may include information for locating the error
+ * in the original XML document, as if it came from a {@link Locator}
+ * object.  Note that although the application
+ * will receive a SAXParseException as the argument to the handlers
+ * in the {@link org.xml.sax.ErrorHandler ErrorHandler} interface, 
+ * the application is not actually required to throw the exception; 
+ * instead, it can simply read the information in it and take a 
+ * different action.</p>
+ *
+ * <p>Since this exception is a subclass of {@link org.xml.sax.SAXException 
+ * SAXException}, it inherits the ability to wrap another exception.</p>
+ *
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.SAXException
+ * @see org.xml.sax.Locator
+ * @see org.xml.sax.ErrorHandler
+ */
+public class SAXParseException extends SAXException {
+    
+    
+    //////////////////////////////////////////////////////////////////////
+    // Constructors.
+    //////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Create a new SAXParseException from a message and a Locator.
+     *
+     * <p>This constructor is especially useful when an application is
+     * creating its own exception from within a {@link org.xml.sax.ContentHandler
+     * ContentHandler} callback.</p>
+     *
+     * @param message The error or warning message.
+     * @param locator The locator object for the error or warning (may be
+     *        null).
+     * @see org.xml.sax.Locator
+     */
+    public SAXParseException (String message, Locator locator) {
+    super(message);
+    if (locator != null) {
+        init(locator.getPublicId(), locator.getSystemId(),
+         locator.getLineNumber(), locator.getColumnNumber());
+    } else {
+        init(null, null, -1, -1);
+    }
+    }
+    
+    
+    /**
+     * Wrap an existing exception in a SAXParseException.
+     *
+     * <p>This constructor is especially useful when an application is
+     * creating its own exception from within a {@link org.xml.sax.ContentHandler
+     * ContentHandler} callback, and needs to wrap an existing exception that is not a
+     * subclass of {@link org.xml.sax.SAXException SAXException}.</p>
+     *
+     * @param message The error or warning message, or null to
+     *                use the message from the embedded exception.
+     * @param locator The locator object for the error or warning (may be
+     *        null).
+     * @param e Any exception.
+     * @see org.xml.sax.Locator
+     */
+    public SAXParseException (String message, Locator locator,
+                  Exception e) {
+    super(message, e);
+    if (locator != null) {
+        init(locator.getPublicId(), locator.getSystemId(),
+         locator.getLineNumber(), locator.getColumnNumber());
+    } else {
+        init(null, null, -1, -1);
+    }
+    }
+    
+    
+    /**
+     * Create a new SAXParseException.
+     *
+     * <p>This constructor is most useful for parser writers.</p>
+     *
+     * <p>All parameters except the message are as if
+     * they were provided by a {@link Locator}.  For example, if the
+     * system identifier is a URL (including relative filename), the
+     * caller must resolve it fully before creating the exception.</p>
+     *
+     *
+     * @param message The error or warning message.
+     * @param publicId The public identifier of the entity that generated
+     *                 the error or warning.
+     * @param systemId The system identifier of the entity that generated
+     *                 the error or warning.
+     * @param lineNumber The line number of the end of the text that
+     *                   caused the error or warning.
+     * @param columnNumber The column number of the end of the text that
+     *                     cause the error or warning.
+     */
+    public SAXParseException (String message, String publicId, String systemId,
+                  int lineNumber, int columnNumber)
+    {
+    super(message);
+    init(publicId, systemId, lineNumber, columnNumber);
+    }
+    
+    
+    /**
+     * Create a new SAXParseException with an embedded exception.
+     *
+     * <p>This constructor is most useful for parser writers who
+     * need to wrap an exception that is not a subclass of
+     * {@link org.xml.sax.SAXException SAXException}.</p>
+     *
+     * <p>All parameters except the message and exception are as if
+     * they were provided by a {@link Locator}.  For example, if the
+     * system identifier is a URL (including relative filename), the
+     * caller must resolve it fully before creating the exception.</p>
+     *
+     * @param message The error or warning message, or null to use
+     *                the message from the embedded exception.
+     * @param publicId The public identifier of the entity that generated
+     *                 the error or warning.
+     * @param systemId The system identifier of the entity that generated
+     *                 the error or warning.
+     * @param lineNumber The line number of the end of the text that
+     *                   caused the error or warning.
+     * @param columnNumber The column number of the end of the text that
+     *                     cause the error or warning.
+     * @param e Another exception to embed in this one.
+     */
+    public SAXParseException (String message, String publicId, String systemId,
+                  int lineNumber, int columnNumber, Exception e)
+    {
+    super(message, e);
+    init(publicId, systemId, lineNumber, columnNumber);
+    }
+
+
+    /**
+     * Internal initialization method.
+     *
+     * @param publicId The public identifier of the entity which generated the exception,
+     *        or null.
+     * @param systemId The system identifier of the entity which generated the exception,
+     *        or null.
+     * @param lineNumber The line number of the error, or -1.
+     * @param columnNumber The column number of the error, or -1.
+     */
+    private void init (String publicId, String systemId,
+               int lineNumber, int columnNumber)
+    {
+    this.publicId = publicId;
+    this.systemId = systemId;
+    this.lineNumber = lineNumber;
+    this.columnNumber = columnNumber;
+    }
+    
+    
+    /**
+     * Get the public identifier of the entity where the exception occurred.
+     *
+     * @return A string containing the public identifier, or null
+     *         if none is available.
+     * @see org.xml.sax.Locator#getPublicId
+     */
+    public String getPublicId ()
+    {
+    return this.publicId;
+    }
+    
+    
+    /**
+     * Get the system identifier of the entity where the exception occurred.
+     *
+     * <p>If the system identifier is a URL, it will have been resolved
+     * fully.</p>
+     *
+     * @return A string containing the system identifier, or null
+     *         if none is available.
+     * @see org.xml.sax.Locator#getSystemId
+     */
+    public String getSystemId ()
+    {
+    return this.systemId;
+    }
+    
+    
+    /**
+     * The line number of the end of the text where the exception occurred.
+     *
+     * <p>The first line is line 1.</p>
+     *
+     * @return An integer representing the line number, or -1
+     *         if none is available.
+     * @see org.xml.sax.Locator#getLineNumber
+     */
+    public int getLineNumber ()
+    {
+    return this.lineNumber;
+    }
+    
+    
+    /**
+     * The column number of the end of the text where the exception occurred.
+     *
+     * <p>The first column in a line is position 1.</p>
+     *
+     * @return An integer representing the column number, or -1
+     *         if none is available.
+     * @see org.xml.sax.Locator#getColumnNumber
+     */
+    public int getColumnNumber ()
+    {
+    return this.columnNumber;
+    }
+    
+    
+    //////////////////////////////////////////////////////////////////////
+    // Internal state.
+    //////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * @serial The public identifier, or null.
+     * @see #getPublicId
+     */    
+    private String publicId;
+
+
+    /**
+     * @serial The system identifier, or null.
+     * @see #getSystemId
+     */
+    private String systemId;
+
+
+    /**
+     * @serial The line number, or -1.
+     * @see #getLineNumber
+     */
+    private int lineNumber;
+
+
+    /**
+     * @serial The column number, or -1.
+     * @see #getColumnNumber
+     */
+    private int columnNumber;
+    
+}
+
+// end of SAXParseException.java
diff --git a/xml/src/main/java/org/xml/sax/XMLFilter.java b/xml/src/main/java/org/xml/sax/XMLFilter.java
new file mode 100644
index 0000000..5a399fa
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/XMLFilter.java
@@ -0,0 +1,65 @@
+// XMLFilter.java - filter SAX2 events.
+// http://www.saxproject.org
+// Written by David Megginson
+// NO WARRANTY!  This class is in the Public Domain.
+// $Id: XMLFilter.java,v 1.6 2002/01/30 21:13:48 dbrownell Exp $
+
+package org.xml.sax;
+
+
+/**
+ * Interface for an XML filter.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>An XML filter is like an XML reader, except that it obtains its
+ * events from another XML reader rather than a primary source like
+ * an XML document or database.  Filters can modify a stream of
+ * events as they pass on to the final application.</p>
+ *
+ * <p>The XMLFilterImpl helper class provides a convenient base
+ * for creating SAX2 filters, by passing on all {@link org.xml.sax.EntityResolver
+ * EntityResolver}, {@link org.xml.sax.DTDHandler DTDHandler},
+ * {@link org.xml.sax.ContentHandler ContentHandler} and {@link org.xml.sax.ErrorHandler
+ * ErrorHandler} events automatically.</p>
+ *
+ * @since SAX 2.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.helpers.XMLFilterImpl
+ */
+public interface XMLFilter extends XMLReader
+{
+
+    /**
+     * Set the parent reader.
+     *
+     * <p>This method allows the application to link the filter to
+     * a parent reader (which may be another filter).  The argument
+     * may not be null.</p>
+     *
+     * @param parent The parent reader.
+     */
+    public abstract void setParent (XMLReader parent);
+
+
+    /**
+     * Get the parent reader.
+     *
+     * <p>This method allows the application to query the parent
+     * reader (which may be another filter).  It is generally a
+     * bad idea to perform any operations on the parent reader
+     * directly: they should all pass through this filter.</p>
+     *
+     * @return The parent filter, or null if none has been set.
+     */
+    public abstract XMLReader getParent ();
+
+}
+
+// end of XMLFilter.java
diff --git a/xml/src/main/java/org/xml/sax/XMLReader.java b/xml/src/main/java/org/xml/sax/XMLReader.java
new file mode 100644
index 0000000..d58a4bd
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/XMLReader.java
@@ -0,0 +1,404 @@
+// XMLReader.java - read an XML document.
+// http://www.saxproject.org
+// Written by David Megginson
+// NO WARRANTY!  This class is in the Public Domain.
+// $Id: XMLReader.java,v 1.9 2004/04/26 17:34:34 dmegginson Exp $
+
+package org.xml.sax;
+
+import java.io.IOException;
+
+
+/**
+ * Interface for reading an XML document using callbacks.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p><strong>Note:</strong> despite its name, this interface does 
+ * <em>not</em> extend the standard Java {@link java.io.Reader Reader} 
+ * interface, because reading XML is a fundamentally different activity 
+ * than reading character data.</p>
+ *
+ * <p>XMLReader is the interface that an XML parser's SAX2 driver must
+ * implement.  This interface allows an application to set and
+ * query features and properties in the parser, to register
+ * event handlers for document processing, and to initiate
+ * a document parse.</p>
+ *
+ * <p>All SAX interfaces are assumed to be synchronous: the
+ * {@link #parse parse} methods must not return until parsing
+ * is complete, and readers must wait for an event-handler callback
+ * to return before reporting the next event.</p>
+ *
+ * <p>This interface replaces the (now deprecated) SAX 1.0 {@link
+ * org.xml.sax.Parser Parser} interface.  The XMLReader interface
+ * contains two important enhancements over the old Parser
+ * interface (as well as some minor ones):</p>
+ *
+ * <ol>
+ * <li>it adds a standard way to query and set features and 
+ *  properties; and</li>
+ * <li>it adds Namespace support, which is required for many
+ *  higher-level XML standards.</li>
+ * </ol>
+ *
+ * <p>There are adapters available to convert a SAX1 Parser to
+ * a SAX2 XMLReader and vice-versa.</p>
+ *
+ * @since SAX 2.0
+ * @author David Megginson
+ * @version 2.0.1+ (sax2r3pre1)
+ * @see org.xml.sax.XMLFilter
+ * @see org.xml.sax.helpers.ParserAdapter
+ * @see org.xml.sax.helpers.XMLReaderAdapter 
+ */
+public interface XMLReader
+{
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Configuration.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Look up the value of a feature flag.
+     *
+     * <p>The feature name is any fully-qualified URI.  It is
+     * possible for an XMLReader to recognize a feature name but
+     * temporarily be unable to return its value.
+     * Some feature values may be available only in specific
+     * contexts, such as before, during, or after a parse.
+     * Also, some feature values may not be programmatically accessible.
+     * (In the case of an adapter for SAX1 {@link Parser}, there is no
+     * implementation-independent way to expose whether the underlying
+     * parser is performing validation, expanding external entities,
+     * and so forth.) </p>
+     *
+     * <p>All XMLReaders are required to recognize the
+     * http://xml.org/sax/features/namespaces and the
+     * http://xml.org/sax/features/namespace-prefixes feature names.</p>
+     *
+     * <p>Typical usage is something like this:</p>
+     *
+     * <pre>
+     * XMLReader r = new MySAXDriver();
+     *
+     *                         // try to activate validation
+     * try {
+     *   r.setFeature("http://xml.org/sax/features/validation", true);
+     * } catch (SAXException e) {
+     *   System.err.println("Cannot activate validation."); 
+     * }
+     *
+     *                         // register event handlers
+     * r.setContentHandler(new MyContentHandler());
+     * r.setErrorHandler(new MyErrorHandler());
+     *
+     *                         // parse the first document
+     * try {
+     *   r.parse("http://www.foo.com/mydoc.xml");
+     * } catch (IOException e) {
+     *   System.err.println("I/O exception reading XML document");
+     * } catch (SAXException e) {
+     *   System.err.println("XML exception reading document.");
+     * }
+     * </pre>
+     *
+     * <p>Implementors are free (and encouraged) to invent their own features,
+     * using names built on their own URIs.</p>
+     *
+     * @param name The feature name, which is a fully-qualified URI.
+     * @return The current value of the feature (true or false).
+     * @exception org.xml.sax.SAXNotRecognizedException If the feature
+     *            value can't be assigned or retrieved.
+     * @exception org.xml.sax.SAXNotSupportedException When the
+     *            XMLReader recognizes the feature name but 
+     *            cannot determine its value at this time.
+     * @see #setFeature
+     */
+    public boolean getFeature (String name)
+        throws SAXNotRecognizedException, SAXNotSupportedException;
+
+
+    /**
+     * Set the value of a feature flag.
+     *
+     * <p>The feature name is any fully-qualified URI.  It is
+     * possible for an XMLReader to expose a feature value but
+     * to be unable to change the current value.
+     * Some feature values may be immutable or mutable only 
+     * in specific contexts, such as before, during, or after 
+     * a parse.</p>
+     *
+     * <p>All XMLReaders are required to support setting
+     * http://xml.org/sax/features/namespaces to true and
+     * http://xml.org/sax/features/namespace-prefixes to false.</p>
+     *
+     * @param name The feature name, which is a fully-qualified URI.
+     * @param value The requested value of the feature (true or false).
+     * @exception org.xml.sax.SAXNotRecognizedException If the feature
+     *            value can't be assigned or retrieved.
+     * @exception org.xml.sax.SAXNotSupportedException When the
+     *            XMLReader recognizes the feature name but 
+     *            cannot set the requested value.
+     * @see #getFeature
+     */
+    public void setFeature (String name, boolean value)
+    throws SAXNotRecognizedException, SAXNotSupportedException;
+
+
+    /**
+     * Look up the value of a property.
+     *
+     * <p>The property name is any fully-qualified URI.  It is
+     * possible for an XMLReader to recognize a property name but
+     * temporarily be unable to return its value.
+     * Some property values may be available only in specific
+     * contexts, such as before, during, or after a parse.</p>
+     *
+     * <p>XMLReaders are not required to recognize any specific
+     * property names, though an initial core set is documented for
+     * SAX2.</p>
+     *
+     * <p>Implementors are free (and encouraged) to invent their own properties,
+     * using names built on their own URIs.</p>
+     *
+     * @param name The property name, which is a fully-qualified URI.
+     * @return The current value of the property.
+     * @exception org.xml.sax.SAXNotRecognizedException If the property
+     *            value can't be assigned or retrieved.
+     * @exception org.xml.sax.SAXNotSupportedException When the
+     *            XMLReader recognizes the property name but 
+     *            cannot determine its value at this time.
+     * @see #setProperty
+     */
+    public Object getProperty (String name)
+    throws SAXNotRecognizedException, SAXNotSupportedException;
+
+
+    /**
+     * Set the value of a property.
+     *
+     * <p>The property name is any fully-qualified URI.  It is
+     * possible for an XMLReader to recognize a property name but
+     * to be unable to change the current value.
+     * Some property values may be immutable or mutable only 
+     * in specific contexts, such as before, during, or after 
+     * a parse.</p>
+     *
+     * <p>XMLReaders are not required to recognize setting
+     * any specific property names, though a core set is defined by 
+     * SAX2.</p>
+     *
+     * <p>This method is also the standard mechanism for setting
+     * extended handlers.</p>
+     *
+     * @param name The property name, which is a fully-qualified URI.
+     * @param value The requested value for the property.
+     * @exception org.xml.sax.SAXNotRecognizedException If the property
+     *            value can't be assigned or retrieved.
+     * @exception org.xml.sax.SAXNotSupportedException When the
+     *            XMLReader recognizes the property name but 
+     *            cannot set the requested value.
+     */
+    public void setProperty (String name, Object value)
+    throws SAXNotRecognizedException, SAXNotSupportedException;
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Event handlers.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Allow an application to register an entity resolver.
+     *
+     * <p>If the application does not register an entity resolver,
+     * the XMLReader will perform its own default resolution.</p>
+     *
+     * <p>Applications may register a new or different resolver in the
+     * middle of a parse, and the SAX parser must begin using the new
+     * resolver immediately.</p>
+     *
+     * @param resolver The entity resolver.
+     * @see #getEntityResolver
+     */
+    public void setEntityResolver (EntityResolver resolver);
+
+
+    /**
+     * Return the current entity resolver.
+     *
+     * @return The current entity resolver, or null if none
+     *         has been registered.
+     * @see #setEntityResolver
+     */
+    public EntityResolver getEntityResolver ();
+
+
+    /**
+     * Allow an application to register a DTD event handler.
+     *
+     * <p>If the application does not register a DTD handler, all DTD
+     * events reported by the SAX parser will be silently ignored.</p>
+     *
+     * <p>Applications may register a new or different handler in the
+     * middle of a parse, and the SAX parser must begin using the new
+     * handler immediately.</p>
+     *
+     * @param handler The DTD handler.
+     * @see #getDTDHandler
+     */
+    public void setDTDHandler (DTDHandler handler);
+
+
+    /**
+     * Return the current DTD handler.
+     *
+     * @return The current DTD handler, or null if none
+     *         has been registered.
+     * @see #setDTDHandler
+     */
+    public DTDHandler getDTDHandler ();
+
+
+    /**
+     * Allow an application to register a content event handler.
+     *
+     * <p>If the application does not register a content handler, all
+     * content events reported by the SAX parser will be silently
+     * ignored.</p>
+     *
+     * <p>Applications may register a new or different handler in the
+     * middle of a parse, and the SAX parser must begin using the new
+     * handler immediately.</p>
+     *
+     * @param handler The content handler.
+     * @see #getContentHandler
+     */
+    public void setContentHandler (ContentHandler handler);
+
+
+    /**
+     * Return the current content handler.
+     *
+     * @return The current content handler, or null if none
+     *         has been registered.
+     * @see #setContentHandler
+     */
+    public ContentHandler getContentHandler ();
+
+
+    /**
+     * Allow an application to register an error event handler.
+     *
+     * <p>If the application does not register an error handler, all
+     * error events reported by the SAX parser will be silently
+     * ignored; however, normal processing may not continue.  It is
+     * highly recommended that all SAX applications implement an
+     * error handler to avoid unexpected bugs.</p>
+     *
+     * <p>Applications may register a new or different handler in the
+     * middle of a parse, and the SAX parser must begin using the new
+     * handler immediately.</p>
+     *
+     * @param handler The error handler.
+     * @see #getErrorHandler
+     */
+    public void setErrorHandler (ErrorHandler handler);
+
+
+    /**
+     * Return the current error handler.
+     *
+     * @return The current error handler, or null if none
+     *         has been registered.
+     * @see #setErrorHandler
+     */
+    public ErrorHandler getErrorHandler ();
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Parsing.
+    ////////////////////////////////////////////////////////////////////
+
+    /**
+     * Parse an XML document.
+     *
+     * <p>The application can use this method to instruct the XML
+     * reader to begin parsing an XML document from any valid input
+     * source (a character stream, a byte stream, or a URI).</p>
+     *
+     * <p>Applications may not invoke this method while a parse is in
+     * progress (they should create a new XMLReader instead for each
+     * nested XML document).  Once a parse is complete, an
+     * application may reuse the same XMLReader object, possibly with a
+     * different input source.
+     * Configuration of the XMLReader object (such as handler bindings and
+     * values established for feature flags and properties) is unchanged
+     * by completion of a parse, unless the definition of that aspect of
+     * the configuration explicitly specifies other behavior.
+     * (For example, feature flags or properties exposing
+     * characteristics of the document being parsed.)
+     * </p>
+     *
+     * <p>During the parse, the XMLReader will provide information
+     * about the XML document through the registered event
+     * handlers.</p>
+     *
+     * <p>This method is synchronous: it will not return until parsing
+     * has ended.  If a client application wants to terminate 
+     * parsing early, it should throw an exception.</p>
+     *
+     * @param input The input source for the top-level of the
+     *        XML document.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @exception java.io.IOException An IO exception from the parser,
+     *            possibly from a byte stream or character stream
+     *            supplied by the application.
+     * @see org.xml.sax.InputSource
+     * @see #parse(java.lang.String)
+     * @see #setEntityResolver
+     * @see #setDTDHandler
+     * @see #setContentHandler
+     * @see #setErrorHandler 
+     */
+    public void parse (InputSource input)
+    throws IOException, SAXException;
+
+
+    /**
+     * Parse an XML document from a system identifier (URI).
+     *
+     * <p>This method is a shortcut for the common case of reading a
+     * document from a system identifier.  It is the exact
+     * equivalent of the following:</p>
+     *
+     * <pre>
+     * parse(new InputSource(systemId));
+     * </pre>
+     *
+     * <p>If the system identifier is a URL, it must be fully resolved
+     * by the application before it is passed to the parser.</p>
+     *
+     * @param systemId The system identifier (URI).
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @exception java.io.IOException An IO exception from the parser,
+     *            possibly from a byte stream or character stream
+     *            supplied by the application.
+     * @see #parse(org.xml.sax.InputSource)
+     */
+    public void parse (String systemId)
+    throws IOException, SAXException;
+
+}
diff --git a/xml/src/main/java/org/xml/sax/ext/Attributes2.java b/xml/src/main/java/org/xml/sax/ext/Attributes2.java
new file mode 100644
index 0000000..45cd551
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/ext/Attributes2.java
@@ -0,0 +1,132 @@
+// Attributes2.java - extended Attributes
+// http://www.saxproject.org
+// Public Domain: no warranty.
+// $Id: Attributes2.java,v 1.6 2004/03/08 13:01:00 dmegginson Exp $
+
+package org.xml.sax.ext;
+
+import org.xml.sax.Attributes;
+
+
+/**
+ * SAX2 extension to augment the per-attribute information
+ * provided though {@link Attributes}.
+ * If an implementation supports this extension, the attributes
+ * provided in {@link org.xml.sax.ContentHandler#startElement
+ * ContentHandler.startElement() } will implement this interface,
+ * and the <em>http://xml.org/sax/features/use-attributes2</em>
+ * feature flag will have the value <em>true</em>.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * </blockquote>
+ *
+ * <p> XMLReader implementations are not required to support this
+ * information, and it is not part of core-only SAX2 distributions.</p>
+ *
+ * <p>Note that if an attribute was defaulted (<em>!isSpecified()</em>)
+ * it will of necessity also have been declared (<em>isDeclared()</em>)
+ * in the DTD.
+ * Similarly if an attribute's type is anything except CDATA, then it
+ * must have been declared.
+ * </p>
+ *
+ * @since SAX 2.0 (extensions 1.1 alpha)
+ * @author David Brownell
+ * @version TBS
+ */
+public interface Attributes2 extends Attributes
+{
+    /**
+     * Returns false unless the attribute was declared in the DTD.
+     * This helps distinguish two kinds of attributes that SAX reports
+     * as CDATA:  ones that were declared (and hence are usually valid),
+     * and those that were not (and which are never valid).
+     *
+     * @param index The attribute index (zero-based).
+     * @return true if the attribute was declared in the DTD,
+     *        false otherwise.
+     * @exception java.lang.ArrayIndexOutOfBoundsException When the
+     *            supplied index does not identify an attribute.
+     */
+    public boolean isDeclared (int index);
+
+    /**
+     * Returns false unless the attribute was declared in the DTD.
+     * This helps distinguish two kinds of attributes that SAX reports
+     * as CDATA:  ones that were declared (and hence are usually valid),
+     * and those that were not (and which are never valid).
+     *
+     * @param qName The XML qualified (prefixed) name.
+     * @return true if the attribute was declared in the DTD,
+     *        false otherwise.
+     * @exception java.lang.IllegalArgumentException When the
+     *            supplied name does not identify an attribute.
+     */
+    public boolean isDeclared (String qName);
+
+    /**
+     * Returns false unless the attribute was declared in the DTD.
+     * This helps distinguish two kinds of attributes that SAX reports
+     * as CDATA:  ones that were declared (and hence are usually valid),
+     * and those that were not (and which are never valid).
+     *
+     * <p>Remember that since DTDs do not "understand" namespaces, the
+     * namespace URI associated with an attribute may not have come from
+     * the DTD.  The declaration will have applied to the attribute's
+     * <em>qName</em>.
+     *
+     * @param uri The Namespace URI, or the empty string if
+     *        the name has no Namespace URI.
+     * @param localName The attribute's local name.
+     * @return true if the attribute was declared in the DTD,
+     *        false otherwise.
+     * @exception java.lang.IllegalArgumentException When the
+     *            supplied names do not identify an attribute.
+     */
+    public boolean isDeclared (String uri, String localName);
+
+    /**
+     * Returns true unless the attribute value was provided
+     * by DTD defaulting.
+     *
+     * @param index The attribute index (zero-based).
+     * @return true if the value was found in the XML text,
+     *        false if the value was provided by DTD defaulting.
+     * @exception java.lang.ArrayIndexOutOfBoundsException When the
+     *            supplied index does not identify an attribute.
+     */
+    public boolean isSpecified (int index);
+
+    /**
+     * Returns true unless the attribute value was provided
+     * by DTD defaulting.
+     *
+     * <p>Remember that since DTDs do not "understand" namespaces, the
+     * namespace URI associated with an attribute may not have come from
+     * the DTD.  The declaration will have applied to the attribute's
+     * <em>qName</em>.
+     *
+     * @param uri The Namespace URI, or the empty string if
+     *        the name has no Namespace URI.
+     * @param localName The attribute's local name.
+     * @return true if the value was found in the XML text,
+     *        false if the value was provided by DTD defaulting.
+     * @exception java.lang.IllegalArgumentException When the
+     *            supplied names do not identify an attribute.
+     */
+    public boolean isSpecified (String uri, String localName);
+
+    /**
+     * Returns true unless the attribute value was provided
+     * by DTD defaulting.
+     *
+     * @param qName The XML qualified (prefixed) name.
+     * @return true if the value was found in the XML text,
+     *        false if the value was provided by DTD defaulting.
+     * @exception java.lang.IllegalArgumentException When the
+     *            supplied name does not identify an attribute.
+     */
+    public boolean isSpecified (String qName);
+}
diff --git a/xml/src/main/java/org/xml/sax/ext/Attributes2Impl.java b/xml/src/main/java/org/xml/sax/ext/Attributes2Impl.java
new file mode 100644
index 0000000..fc36805
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/ext/Attributes2Impl.java
@@ -0,0 +1,320 @@
+// Attributes2Impl.java - extended AttributesImpl
+// http://www.saxproject.org
+// Public Domain: no warranty.
+// $Id: Attributes2Impl.java,v 1.5 2004/03/08 13:01:01 dmegginson Exp $
+
+package org.xml.sax.ext;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.helpers.AttributesImpl;
+
+
+/**
+ * SAX2 extension helper for additional Attributes information,
+ * implementing the {@link Attributes2} interface.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * </blockquote>
+ *
+ * <p>This is not part of core-only SAX2 distributions.</p>
+ *
+ * <p>The <em>specified</em> flag for each attribute will always
+ * be true, unless it has been set to false in the copy constructor
+ * or using {@link #setSpecified}.
+ * Similarly, the <em>declared</em> flag for each attribute will
+ * always be false, except for defaulted attributes (<em>specified</em>
+ * is false), non-CDATA attributes, or when it is set to true using
+ * {@link #setDeclared}.
+ * If you change an attribute's type by hand, you may need to modify
+ * its <em>declared</em> flag to match. 
+ * </p>
+ *
+ * @since SAX 2.0 (extensions 1.1 alpha)
+ * @author David Brownell
+ * @version TBS
+ */
+public class Attributes2Impl extends AttributesImpl implements Attributes2
+{
+    private boolean    declared [];
+    private boolean    specified [];
+
+
+    /**
+     * Construct a new, empty Attributes2Impl object.
+     */
+    public Attributes2Impl () {
+        // BEGIN android-added
+        declared = new boolean[0];
+        specified = new boolean[0];
+        // END android-added
+    }
+
+
+    /**
+     * Copy an existing Attributes or Attributes2 object.
+     * If the object implements Attributes2, values of the
+     * <em>specified</em> and <em>declared</em> flags for each
+     * attribute are copied.
+     * Otherwise the flag values are defaulted to assume no DTD was used,
+     * unless there is evidence to the contrary (such as attributes with
+     * type other than CDATA, which must have been <em>declared</em>).
+     *
+     * <p>This constructor is especially useful inside a
+     * {@link org.xml.sax.ContentHandler#startElement startElement} event.</p>
+     *
+     * @param atts The existing Attributes object.
+     */
+    public Attributes2Impl (Attributes atts)
+    {
+    super (atts);
+    }
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of Attributes2
+    ////////////////////////////////////////////////////////////////////
+
+
+    /*
+     * Returns the current value of the attribute's "declared" flag.
+     */
+    // javadoc mostly from interface
+    public boolean isDeclared (int index)
+    {
+    if (index < 0 || index >= getLength ())
+        throw new ArrayIndexOutOfBoundsException (
+        "No attribute at index: " + index);
+    return declared [index];
+    }
+
+
+    /*
+     * Returns the current value of the attribute's "declared" flag.
+     */
+    // javadoc mostly from interface
+    public boolean isDeclared (String uri, String localName)
+    {
+    int index = getIndex (uri, localName);
+
+    if (index < 0)
+        throw new IllegalArgumentException (
+        "No such attribute: local=" + localName
+        + ", namespace=" + uri);
+    return declared [index];
+    }
+
+
+    /*
+     * Returns the current value of the attribute's "declared" flag.
+     */
+    // javadoc mostly from interface
+    public boolean isDeclared (String qName)
+    {
+    int index = getIndex (qName);
+
+    if (index < 0)
+        throw new IllegalArgumentException (
+        "No such attribute: " + qName);
+    return declared [index];
+    }
+
+
+    /**
+     * Returns the current value of an attribute's "specified" flag.
+     *
+     * @param index The attribute index (zero-based).
+     * @return current flag value
+     * @exception java.lang.ArrayIndexOutOfBoundsException When the
+     *            supplied index does not identify an attribute.
+     */
+    public boolean isSpecified (int index)
+    {
+    if (index < 0 || index >= getLength ())
+        throw new ArrayIndexOutOfBoundsException (
+        "No attribute at index: " + index);
+    return specified [index];
+    }
+
+
+    /**
+     * Returns the current value of an attribute's "specified" flag.
+     *
+     * @param uri The Namespace URI, or the empty string if
+     *        the name has no Namespace URI.
+     * @param localName The attribute's local name.
+     * @return current flag value
+     * @exception java.lang.IllegalArgumentException When the
+     *            supplied names do not identify an attribute.
+     */
+    public boolean isSpecified (String uri, String localName)
+    {
+    int index = getIndex (uri, localName);
+
+    if (index < 0)
+        throw new IllegalArgumentException (
+        "No such attribute: local=" + localName
+        + ", namespace=" + uri);
+    return specified [index];
+    }
+
+
+    /**
+     * Returns the current value of an attribute's "specified" flag.
+     *
+     * @param qName The XML qualified (prefixed) name.
+     * @return current flag value
+     * @exception java.lang.IllegalArgumentException When the
+     *            supplied name does not identify an attribute.
+     */
+    public boolean isSpecified (String qName)
+    {
+    int index = getIndex (qName);
+
+    if (index < 0)
+        throw new IllegalArgumentException (
+        "No such attribute: " + qName);
+    return specified [index];
+    }
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Manipulators
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Copy an entire Attributes object.  The "specified" flags are
+     * assigned as true, and "declared" flags as false (except when
+     * an attribute's type is not CDATA),
+     * unless the object is an Attributes2 object.
+     * In that case those flag values are all copied.
+     *
+     * @param atts The attributes to copy.
+     * 
+     * @see AttributesImpl#setAttributes
+     */
+    public void setAttributes (Attributes atts)
+    {
+    int length = atts.getLength ();
+
+    super.setAttributes (atts);
+    declared = new boolean [length];
+    specified = new boolean [length];
+
+    if (atts instanceof Attributes2) {
+        Attributes2    a2 = (Attributes2) atts;
+        for (int i = 0; i < length; i++) {
+        declared [i] = a2.isDeclared (i);
+        specified [i] = a2.isSpecified (i);
+        }
+    } else {
+        for (int i = 0; i < length; i++) {
+        declared [i] = !"CDATA".equals (atts.getType (i));
+        specified [i] = true;
+        }
+    }
+    }
+
+
+    /**
+     * Add an attribute to the end of the list, setting its
+     * "specified" flag to true.  To set that flag's value
+     * to false, use {@link #setSpecified}.
+     *
+     * <p>Unless the attribute <em>type</em> is CDATA, this attribute
+     * is marked as being declared in the DTD.  To set that flag's value
+     * to true for CDATA attributes, use {@link #setDeclared}.
+     *
+     * @param uri The Namespace URI, or the empty string if
+     *        none is available or Namespace processing is not
+     *        being performed.
+     * @param localName The local name, or the empty string if
+     *        Namespace processing is not being performed.
+     * @param qName The qualified (prefixed) name, or the empty string
+     *        if qualified names are not available.
+     * @param type The attribute type as a string.
+     * @param value The attribute value.
+     * 
+     * @see AttributesImpl#addAttribute
+     */
+    public void addAttribute (String uri, String localName, String qName,
+                  String type, String value)
+    {
+    super.addAttribute (uri, localName, qName, type, value);
+
+    int length = getLength ();
+
+    // BEGIN android-changed
+    if (length > specified.length) {
+    // END android-changed
+        boolean    newFlags [];
+
+        newFlags = new boolean [length];
+        System.arraycopy (declared, 0, newFlags, 0, declared.length);
+        declared = newFlags;
+
+        newFlags = new boolean [length];
+        System.arraycopy (specified, 0, newFlags, 0, specified.length);
+        specified = newFlags;
+    }
+
+    specified [length - 1] = true;
+    declared [length - 1] = !"CDATA".equals (type);
+    }
+
+
+    // javadoc entirely from superclass
+    public void removeAttribute (int index)
+    {
+    int origMax = getLength () - 1;
+
+    super.removeAttribute (index);
+    if (index != origMax) {
+        System.arraycopy (declared, index + 1, declared, index,
+            origMax - index);
+        System.arraycopy (specified, index + 1, specified, index,
+            origMax - index);
+    }
+    }
+
+
+    /**
+     * Assign a value to the "declared" flag of a specific attribute.
+     * This is normally needed only for attributes of type CDATA,
+     * including attributes whose type is changed to or from CDATA.
+     *
+     * @param index The index of the attribute (zero-based).
+     * @param value The desired flag value.
+     * @exception java.lang.ArrayIndexOutOfBoundsException When the
+     *            supplied index does not identify an attribute.
+     * @see #setType
+     */
+    public void setDeclared (int index, boolean value)
+    {
+    if (index < 0 || index >= getLength ())
+        throw new ArrayIndexOutOfBoundsException (
+        "No attribute at index: " + index);
+    declared [index] = value;
+    }
+
+
+    /**
+     * Assign a value to the "specified" flag of a specific attribute.
+     * This is the only way this flag can be cleared, except clearing
+     * by initialization with the copy constructor.
+     *
+     * @param index The index of the attribute (zero-based).
+     * @param value The desired flag value.
+     * @exception java.lang.ArrayIndexOutOfBoundsException When the
+     *            supplied index does not identify an attribute.
+     */
+    public void setSpecified (int index, boolean value)
+    {
+    if (index < 0 || index >= getLength ())
+        throw new ArrayIndexOutOfBoundsException (
+        "No attribute at index: " + index);
+    specified [index] = value;
+    }
+}
diff --git a/xml/src/main/java/org/xml/sax/ext/DeclHandler.java b/xml/src/main/java/org/xml/sax/ext/DeclHandler.java
new file mode 100644
index 0000000..26471f3
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/ext/DeclHandler.java
@@ -0,0 +1,146 @@
+// DeclHandler.java - Optional handler for DTD declaration events.
+// http://www.saxproject.org
+// Public Domain: no warranty.
+// $Id: DeclHandler.java,v 1.6 2004/04/22 13:28:49 dmegginson Exp $
+
+package org.xml.sax.ext;
+
+import org.xml.sax.SAXException;
+
+
+/**
+ * SAX2 extension handler for DTD declaration events.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This is an optional extension handler for SAX2 to provide more
+ * complete information about DTD declarations in an XML document.
+ * XML readers are not required to recognize this handler, and it
+ * is not part of core-only SAX2 distributions.</p>
+ *
+ * <p>Note that data-related DTD declarations (unparsed entities and
+ * notations) are already reported through the {@link
+ * org.xml.sax.DTDHandler DTDHandler} interface.</p>
+ *
+ * <p>If you are using the declaration handler together with a lexical
+ * handler, all of the events will occur between the
+ * {@link org.xml.sax.ext.LexicalHandler#startDTD startDTD} and the
+ * {@link org.xml.sax.ext.LexicalHandler#endDTD endDTD} events.</p>
+ *
+ * <p>To set the DeclHandler for an XML reader, use the
+ * {@link org.xml.sax.XMLReader#setProperty setProperty} method
+ * with the property name
+ * <code>http://xml.org/sax/properties/declaration-handler</code>
+ * and an object implementing this interface (or null) as the value.
+ * If the reader does not report declaration events, it will throw a
+ * {@link org.xml.sax.SAXNotRecognizedException SAXNotRecognizedException}
+ * when you attempt to register the handler.</p>
+ *
+ * @since SAX 2.0 (extensions 1.0)
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ */
+public interface DeclHandler
+{
+
+    /**
+     * Report an element type declaration.
+     *
+     * <p>The content model will consist of the string "EMPTY", the
+     * string "ANY", or a parenthesised group, optionally followed
+     * by an occurrence indicator.  The model will be normalized so
+     * that all parameter entities are fully resolved and all whitespace 
+     * is removed,and will include the enclosing parentheses.  Other
+     * normalization (such as removing redundant parentheses or 
+     * simplifying occurrence indicators) is at the discretion of the
+     * parser.</p>
+     *
+     * @param name The element type name.
+     * @param model The content model as a normalized string.
+     * @exception SAXException The application may raise an exception.
+     */
+    public abstract void elementDecl (String name, String model)
+    throws SAXException;
+
+
+    /**
+     * Report an attribute type declaration.
+     *
+     * <p>Only the effective (first) declaration for an attribute will
+     * be reported.  The type will be one of the strings "CDATA",
+     * "ID", "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY",
+     * "ENTITIES", a parenthesized token group with 
+     * the separator "|" and all whitespace removed, or the word
+     * "NOTATION" followed by a space followed by a parenthesized
+     * token group with all whitespace removed.</p>
+     *
+     * <p>The value will be the value as reported to applications,
+     * appropriately normalized and with entity and character
+     * references expanded.  </p>
+     *
+     * @param eName The name of the associated element.
+     * @param aName The name of the attribute.
+     * @param type A string representing the attribute type.
+     * @param mode A string representing the attribute defaulting mode
+     *        ("#IMPLIED", "#REQUIRED", or "#FIXED") or null if
+     *        none of these applies.
+     * @param value A string representing the attribute's default value,
+     *        or null if there is none.
+     * @exception SAXException The application may raise an exception.
+     */
+    public abstract void attributeDecl (String eName,
+                    String aName,
+                    String type,
+                    String mode,
+                    String value)
+    throws SAXException;
+
+
+    /**
+     * Report an internal entity declaration.
+     *
+     * <p>Only the effective (first) declaration for each entity
+     * will be reported.  All parameter entities in the value
+     * will be expanded, but general entities will not.</p>
+     *
+     * @param name The name of the entity.  If it is a parameter
+     *        entity, the name will begin with '%'.
+     * @param value The replacement text of the entity.
+     * @exception SAXException The application may raise an exception.
+     * @see #externalEntityDecl
+     * @see org.xml.sax.DTDHandler#unparsedEntityDecl
+     */
+    public abstract void internalEntityDecl (String name, String value)
+    throws SAXException;
+
+
+    /**
+     * Report a parsed external entity declaration.
+     *
+     * <p>Only the effective (first) declaration for each entity
+     * will be reported.</p>
+     *
+     * <p>If the system identifier is a URL, the parser must resolve it
+     * fully before passing it to the application.</p>
+     *
+     * @param name The name of the entity.  If it is a parameter
+     *        entity, the name will begin with '%'.
+     * @param publicId The entity's public identifier, or null if none
+     *        was given.
+     * @param systemId The entity's system identifier.
+     * @exception SAXException The application may raise an exception.
+     * @see #internalEntityDecl
+     * @see org.xml.sax.DTDHandler#unparsedEntityDecl
+     */
+    public abstract void externalEntityDecl (String name, String publicId,
+                         String systemId)
+    throws SAXException;
+
+}
+
+// end of DeclHandler.java
diff --git a/xml/src/main/java/org/xml/sax/ext/DefaultHandler2.java b/xml/src/main/java/org/xml/sax/ext/DefaultHandler2.java
new file mode 100644
index 0000000..f26564f
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/ext/DefaultHandler2.java
@@ -0,0 +1,185 @@
+// DefaultHandler2.java - extended DefaultHandler
+// http://www.saxproject.org
+// Public Domain: no warranty.
+// $Id: DefaultHandler2.java,v 1.3 2002/01/12 19:04:19 dbrownell Exp $
+
+package org.xml.sax.ext;
+
+import java.io.IOException;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+
+/**
+ * This class extends the SAX2 base handler class to support the
+ * SAX2 {@link LexicalHandler}, {@link DeclHandler}, and
+ * {@link EntityResolver2} extensions.  Except for overriding the
+ * original SAX1 {@link DefaultHandler#resolveEntity resolveEntity()}
+ * method the added handler methods just return.  Subclassers may
+ * override everything on a method-by-method basis.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * </blockquote>
+ *
+ * <p> <em>Note:</em> this class might yet learn that the
+ * <em>ContentHandler.setDocumentLocator()</em> call might be passed a
+ * {@link Locator2} object, and that the
+ * <em>ContentHandler.startElement()</em> call might be passed a
+ * {@link Attributes2} object.
+ *
+ * @since SAX 2.0 (extensions 1.1 alpha)
+ * @author David Brownell
+ * @version TBS
+ */
+public class DefaultHandler2 extends DefaultHandler
+    implements LexicalHandler, DeclHandler, EntityResolver2
+{
+    /** Constructs a handler which ignores all parsing events. */
+    public DefaultHandler2 () { }
+
+
+    // SAX2 ext-1.0 LexicalHandler
+
+    public void startCDATA ()
+    throws SAXException
+    {}
+
+    public void endCDATA ()
+    throws SAXException
+    {}
+
+    public void startDTD (String name, String publicId, String systemId)
+    throws SAXException
+    {}
+
+    public void endDTD ()
+    throws SAXException
+    {}
+
+    public void startEntity (String name)
+    throws SAXException
+    {}
+
+    public void endEntity (String name)
+    throws SAXException
+    {}
+
+    public void comment (char ch [], int start, int length)
+    throws SAXException
+    { }
+
+
+    // SAX2 ext-1.0 DeclHandler
+
+    public void attributeDecl (String eName, String aName,
+        String type, String mode, String value)
+    throws SAXException
+    {}
+
+    public void elementDecl (String name, String model)
+    throws SAXException
+    {}
+
+    public void externalEntityDecl (String name,
+        String publicId, String systemId)
+    throws SAXException
+    {}
+
+    public void internalEntityDecl (String name, String value)
+    throws SAXException
+    {}
+
+    // SAX2 ext-1.1 EntityResolver2
+
+    /**
+     * Tells the parser that if no external subset has been declared
+     * in the document text, none should be used.
+     * 
+     * @param name Identifies the document root element.  This name comes
+     *    from a DOCTYPE declaration (where available) or from the actual
+     *    root element. The parameter is ignored.
+     * @param baseURI The document's base URI, serving as an additional
+     *    hint for selecting the external subset.  This is always an absolute
+     *    URI, unless it is null because the XMLReader was given an InputSource
+     *    without one. The parameter is ignored.
+     *    
+     * @return null (always).
+     * 
+     * @exception SAXException Any SAX exception, possibly wrapping
+     *    another exception.
+     * @exception IOException Probably indicating a failure to create
+     *    a new InputStream or Reader, or an illegal URL.
+     */
+    public InputSource getExternalSubset (String name, String baseURI)
+    throws SAXException, IOException
+    { return null; }
+
+    /**
+     * Tells the parser to resolve the systemId against the baseURI
+     * and read the entity text from that resulting absolute URI.
+     * Note that because the older
+     * {@link DefaultHandler#resolveEntity DefaultHandler.resolveEntity()},
+     * method is overridden to call this one, this method may sometimes 
+     * be invoked with null <em>name</em> and <em>baseURI</em>, and
+     * with the <em>systemId</em> already absolutized.
+     * 
+     * @param name Identifies the external entity being resolved.
+     *    Either "[dtd]" for the external subset, or a name starting
+     *    with "%" to indicate a parameter entity, or else the name of
+     *    a general entity.  This is never null when invoked by a SAX2
+     *    parser.
+     * @param publicId The public identifier of the external entity being
+     *    referenced (normalized as required by the XML specification), or
+     *    null if none was supplied.
+     * @param baseURI The URI with respect to which relative systemIDs
+     *    are interpreted.  This is always an absolute URI, unless it is
+     *    null (likely because the XMLReader was given an InputSource without
+     *  one).  This URI is defined by the XML specification to be the one
+     *    associated with the "&lt;" starting the relevant declaration.
+     * @param systemId The system identifier of the external entity
+     *    being referenced; either a relative or absolute URI.
+     *  This is never null when invoked by a SAX2 parser; only declared
+     *    entities, and any external subset, are resolved by such parsers.
+     *
+     * @return An InputSource object describing the new input source.
+     * 
+     * @exception SAXException Any SAX exception, possibly wrapping
+     *    another exception.
+     * @exception IOException Probably indicating a failure to create
+     *    a new InputStream or Reader, or an illegal URL.
+     */
+    public InputSource resolveEntity (String name, String publicId,
+        String baseURI, String systemId)
+    throws SAXException, IOException
+    { return null; }
+    
+    // SAX1 EntityResolver
+
+    /**
+     * Invokes
+     * {@link EntityResolver2#resolveEntity EntityResolver2.resolveEntity()}
+     * with null entity name and base URI.
+     * You only need to override that method to use this class.
+     * 
+     * @param publicId The public identifier of the external entity being
+     *    referenced (normalized as required by the XML specification), or
+     *    null if none was supplied.
+     * @param systemId The system identifier of the external entity
+     *    being referenced; either a relative or absolute URI.
+     *  This is never null when invoked by a SAX2 parser; only declared
+     *    entities, and any external subset, are resolved by such parsers.
+     *
+     * @return An InputSource object describing the new input source.
+     * 
+     * @exception SAXException Any SAX exception, possibly wrapping
+     *    another exception.
+     * @exception IOException Probably indicating a failure to create
+     *    a new InputStream or Reader, or an illegal URL.
+     */
+    public InputSource resolveEntity (String publicId, String systemId)
+    throws SAXException, IOException
+    { return resolveEntity (null, publicId, null, systemId); }
+}
diff --git a/xml/src/main/java/org/xml/sax/ext/EntityResolver2.java b/xml/src/main/java/org/xml/sax/ext/EntityResolver2.java
new file mode 100644
index 0000000..5437a9b
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/ext/EntityResolver2.java
@@ -0,0 +1,197 @@
+// EntityResolver2.java - Extended SAX entity resolver.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: EntityResolver2.java,v 1.2 2002/01/12 19:20:08 dbrownell Exp $
+
+package org.xml.sax.ext;
+
+import java.io.IOException;
+
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
+import org.xml.sax.SAXException;
+
+
+/**
+ * Extended interface for mapping external entity references to input
+ * sources, or providing a missing external subset.  The
+ * {@link XMLReader#setEntityResolver XMLReader.setEntityResolver()} method
+ * is used to provide implementations of this interface to parsers.
+ * When a parser uses the methods in this interface, the
+ * {@link EntityResolver2#resolveEntity EntityResolver2.resolveEntity()}
+ * method (in this interface) is used <em>instead of</em> the older (SAX 1.0)
+ * {@link EntityResolver#resolveEntity EntityResolver.resolveEntity()} method.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * </blockquote>
+ *
+ * <p>If a SAX application requires the customized handling which this
+ * interface defines for external entities, it must ensure that it uses
+ * an XMLReader with the
+ * <em>http://xml.org/sax/features/use-entity-resolver2</em> feature flag
+ * set to <em>true</em> (which is its default value when the feature is
+ * recognized).  If that flag is unrecognized, or its value is false,
+ * or the resolver does not implement this interface, then only the
+ * {@link EntityResolver} method will be used.
+ * </p>
+ *
+ * <p>That supports three categories of application that modify entity
+ * resolution.  <em>Old Style</em> applications won't know about this interface;
+ * they will provide an EntityResolver.
+ * <em>Transitional Mode</em> provide an EntityResolver2 and automatically
+ * get the benefit of its methods in any systems (parsers or other tools)
+ * supporting it, due to polymorphism.
+ * Both <em>Old Style</em> and <em>Transitional Mode</em> applications will
+ * work with any SAX2 parser.
+ * <em>New style</em> applications will fail to run except on SAX2 parsers
+ * that support this particular feature.
+ * They will insist that feature flag have a value of "true", and the
+ * EntityResolver2 implementation they provide  might throw an exception
+ * if the original SAX 1.0 style entity resolution method is invoked.
+ * </p>
+ *
+ * @see org.xml.sax.XMLReader#setEntityResolver
+ *
+ * @since SAX 2.0 (extensions 1.1 alpha)
+ * @author David Brownell
+ * @version TBD
+ */
+public interface EntityResolver2 extends EntityResolver
+{
+    /**
+     * Allows applications to provide an external subset for documents
+     * that don't explicitly define one.  Documents with DOCTYPE declarations
+     * that omit an external subset can thus augment the declarations
+     * available for validation, entity processing, and attribute processing
+     * (normalization, defaulting, and reporting types including ID).
+     * This augmentation is reported
+     * through the {@link LexicalHandler#startDTD startDTD()} method as if
+     * the document text had originally included the external subset;
+     * this callback is made before any internal subset data or errors
+     * are reported.</p>
+     *
+     * <p>This method can also be used with documents that have no DOCTYPE
+     * declaration.  When the root element is encountered,
+     * but no DOCTYPE declaration has been seen, this method is
+     * invoked.  If it returns a value for the external subset, that root
+     * element is declared to be the root element, giving the effect of
+     * splicing a DOCTYPE declaration at the end the prolog of a document
+     * that could not otherwise be valid.  The sequence of parser callbacks
+     * in that case logically resembles this:</p>
+     *
+     * <pre>
+     * ... comments and PIs from the prolog (as usual)
+     * startDTD ("rootName", source.getPublicId (), source.getSystemId ());
+     * startEntity ("[dtd]");
+     * ... declarations, comments, and PIs from the external subset
+     * endEntity ("[dtd]");
+     * endDTD ();
+     * ... then the rest of the document (as usual)
+     * startElement (..., "rootName", ...);
+     * </pre>
+     *
+     * <p>Note that the InputSource gets no further resolution.
+     * Implementations of this method may wish to invoke
+     * {@link #resolveEntity resolveEntity()} to gain benefits such as use
+     * of local caches of DTD entities.  Also, this method will never be
+     * used by a (non-validating) processor that is not including external
+     * parameter entities. </p>
+     *
+     * <p>Uses for this method include facilitating data validation when
+     * interoperating with XML processors that would always require
+     * undesirable network accesses for external entities, or which for
+     * other reasons adopt a "no DTDs" policy.
+     * Non-validation motives include forcing documents to include DTDs so
+     * that attributes are handled consistently.
+     * For example, an XPath processor needs to know which attibutes have
+     * type "ID" before it can process a widely used type of reference.</p>
+     * 
+     * <p><strong>Warning:</strong> Returning an external subset modifies
+     * the input document.  By providing definitions for general entities,
+     * it can make a malformed document appear to be well formed.
+     * </p>
+     *
+     * @param name Identifies the document root element.  This name comes
+     *    from a DOCTYPE declaration (where available) or from the actual
+     *    root element. 
+     * @param baseURI The document's base URI, serving as an additional
+     *    hint for selecting the external subset.  This is always an absolute
+     *    URI, unless it is null because the XMLReader was given an InputSource
+     *    without one.
+     *
+     * @return An InputSource object describing the new external subset
+     *    to be used by the parser, or null to indicate that no external
+     *    subset is provided.
+     *
+     * @exception SAXException Any SAX exception, possibly wrapping
+     *    another exception.
+     * @exception IOException Probably indicating a failure to create
+     *    a new InputStream or Reader, or an illegal URL.
+     */
+    public InputSource getExternalSubset (String name, String baseURI)
+    throws SAXException, IOException;
+
+    /**
+     * Allows applications to map references to external entities into input
+     * sources, or tell the parser it should use conventional URI resolution.
+     * This method is only called for external entities which have been
+     * properly declared.
+     * This method provides more flexibility than the {@link EntityResolver}
+     * interface, supporting implementations of more complex catalogue
+     * schemes such as the one defined by the <a href=
+    "http://www.oasis-open.org/committees/entity/spec-2001-08-06.html"
+    >OASIS XML Catalogs</a> specification.</p>
+     *
+     * <p>Parsers configured to use this resolver method will call it
+     * to determine the input source to use for any external entity
+     * being included because of a reference in the XML text.
+     * That excludes the document entity, and any external entity returned
+     * by {@link #getExternalSubset getExternalSubset()}.
+     * When a (non-validating) processor is configured not to include
+     * a class of entities (parameter or general) through use of feature
+     * flags, this method is not invoked for such entities.  </p>
+     *
+     * <p>Note that the entity naming scheme used here is the same one
+     * used in the {@link LexicalHandler}, or in the {@link
+    org.xml.sax.ContentHandler#skippedEntity
+    ContentHandler.skippedEntity()}
+     * method. </p>
+     *
+     * @param name Identifies the external entity being resolved.
+     *    Either "[dtd]" for the external subset, or a name starting
+     *    with "%" to indicate a parameter entity, or else the name of
+     *    a general entity.  This is never null when invoked by a SAX2
+     *    parser.
+     * @param publicId The public identifier of the external entity being
+     *    referenced (normalized as required by the XML specification), or
+     *    null if none was supplied.
+     * @param baseURI The URI with respect to which relative systemIDs
+     *    are interpreted.  This is always an absolute URI, unless it is
+     *    null (likely because the XMLReader was given an InputSource without
+     *  one).  This URI is defined by the XML specification to be the one
+     *    associated with the "&lt;" starting the relevant declaration.
+     * @param systemId The system identifier of the external entity
+     *    being referenced; either a relative or absolute URI.
+     *  This is never null when invoked by a SAX2 parser; only declared
+     *    entities, and any external subset, are resolved by such parsers.
+     *
+     * @return An InputSource object describing the new input source to
+     *    be used by the parser.  Returning null directs the parser to
+     *    resolve the system ID against the base URI and open a connection
+     *    to resulting URI.
+     *
+     * @exception SAXException Any SAX exception, possibly wrapping
+     *    another exception.
+     * @exception IOException Probably indicating a failure to create
+     *    a new InputStream or Reader, or an illegal URL.
+     */
+    public InputSource resolveEntity (
+        String name,
+        String publicId,
+        String baseURI,
+        String systemId
+    ) throws SAXException, IOException;
+}
diff --git a/xml/src/main/java/org/xml/sax/ext/LexicalHandler.java b/xml/src/main/java/org/xml/sax/ext/LexicalHandler.java
new file mode 100644
index 0000000..e551b61
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/ext/LexicalHandler.java
@@ -0,0 +1,212 @@
+// LexicalHandler.java - optional handler for lexical parse events.
+// http://www.saxproject.org
+// Public Domain: no warranty.
+// $Id: LexicalHandler.java,v 1.5 2002/01/30 21:00:44 dbrownell Exp $
+
+package org.xml.sax.ext;
+
+import org.xml.sax.SAXException;
+
+/**
+ * SAX2 extension handler for lexical events.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This is an optional extension handler for SAX2 to provide
+ * lexical information about an XML document, such as comments
+ * and CDATA section boundaries.
+ * XML readers are not required to recognize this handler, and it
+ * is not part of core-only SAX2 distributions.</p>
+ *
+ * <p>The events in the lexical handler apply to the entire document,
+ * not just to the document element, and all lexical handler events
+ * must appear between the content handler's startDocument and
+ * endDocument events.</p>
+ *
+ * <p>To set the LexicalHandler for an XML reader, use the
+ * {@link org.xml.sax.XMLReader#setProperty setProperty} method
+ * with the property name
+ * <code>http://xml.org/sax/properties/lexical-handler</code>
+ * and an object implementing this interface (or null) as the value.
+ * If the reader does not report lexical events, it will throw a
+ * {@link org.xml.sax.SAXNotRecognizedException SAXNotRecognizedException}
+ * when you attempt to register the handler.</p>
+ *
+ * @since SAX 2.0 (extensions 1.0)
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ */
+public interface LexicalHandler
+{
+
+    /**
+     * Report the start of DTD declarations, if any.
+     *
+     * <p>This method is intended to report the beginning of the
+     * DOCTYPE declaration; if the document has no DOCTYPE declaration,
+     * this method will not be invoked.</p>
+     *
+     * <p>All declarations reported through 
+     * {@link org.xml.sax.DTDHandler DTDHandler} or
+     * {@link org.xml.sax.ext.DeclHandler DeclHandler} events must appear
+     * between the startDTD and {@link #endDTD endDTD} events.
+     * Declarations are assumed to belong to the internal DTD subset
+     * unless they appear between {@link #startEntity startEntity}
+     * and {@link #endEntity endEntity} events.  Comments and
+     * processing instructions from the DTD should also be reported
+     * between the startDTD and endDTD events, in their original 
+     * order of (logical) occurrence; they are not required to
+     * appear in their correct locations relative to DTDHandler
+     * or DeclHandler events, however.</p>
+     *
+     * <p>Note that the start/endDTD events will appear within
+     * the start/endDocument events from ContentHandler and
+     * before the first 
+     * {@link org.xml.sax.ContentHandler#startElement startElement}
+     * event.</p>
+     *
+     * @param name The document type name.
+     * @param publicId The declared public identifier for the
+     *        external DTD subset, or null if none was declared.
+     * @param systemId The declared system identifier for the
+     *        external DTD subset, or null if none was declared.
+     *        (Note that this is not resolved against the document
+     *        base URI.)
+     * @exception SAXException The application may raise an
+     *            exception.
+     * @see #endDTD
+     * @see #startEntity
+     */
+    public abstract void startDTD (String name, String publicId,
+                   String systemId)
+    throws SAXException;
+
+
+    /**
+     * Report the end of DTD declarations.
+     *
+     * <p>This method is intended to report the end of the
+     * DOCTYPE declaration; if the document has no DOCTYPE declaration,
+     * this method will not be invoked.</p>
+     *
+     * @exception SAXException The application may raise an exception.
+     * @see #startDTD
+     */
+    public abstract void endDTD ()
+    throws SAXException;
+
+
+    /**
+     * Report the beginning of some internal and external XML entities.
+     *
+     * <p>The reporting of parameter entities (including
+     * the external DTD subset) is optional, and SAX2 drivers that
+     * report LexicalHandler events may not implement it; you can use the
+     * <code
+     * >http://xml.org/sax/features/lexical-handler/parameter-entities</code>
+     * feature to query or control the reporting of parameter entities.</p>
+     *
+     * <p>General entities are reported with their regular names,
+     * parameter entities have '%' prepended to their names, and 
+     * the external DTD subset has the pseudo-entity name "[dtd]".</p>
+     *
+     * <p>When a SAX2 driver is providing these events, all other 
+     * events must be properly nested within start/end entity 
+     * events.  There is no additional requirement that events from 
+     * {@link org.xml.sax.ext.DeclHandler DeclHandler} or
+     * {@link org.xml.sax.DTDHandler DTDHandler} be properly ordered.</p>
+     *
+     * <p>Note that skipped entities will be reported through the
+     * {@link org.xml.sax.ContentHandler#skippedEntity skippedEntity}
+     * event, which is part of the ContentHandler interface.</p>
+     *
+     * <p>Because of the streaming event model that SAX uses, some
+     * entity boundaries cannot be reported under any 
+     * circumstances:</p>
+     *
+     * <ul>
+     * <li>general entities within attribute values</li>
+     * <li>parameter entities within declarations</li>
+     * </ul>
+     *
+     * <p>These will be silently expanded, with no indication of where
+     * the original entity boundaries were.</p>
+     *
+     * <p>Note also that the boundaries of character references (which
+     * are not really entities anyway) are not reported.</p>
+     *
+     * <p>All start/endEntity events must be properly nested.
+     *
+     * @param name The name of the entity.  If it is a parameter
+     *        entity, the name will begin with '%', and if it is the
+     *        external DTD subset, it will be "[dtd]".
+     * @exception SAXException The application may raise an exception.
+     * @see #endEntity
+     * @see org.xml.sax.ext.DeclHandler#internalEntityDecl
+     * @see org.xml.sax.ext.DeclHandler#externalEntityDecl 
+     */
+    public abstract void startEntity (String name)
+    throws SAXException;
+
+
+    /**
+     * Report the end of an entity.
+     *
+     * @param name The name of the entity that is ending.
+     * @exception SAXException The application may raise an exception.
+     * @see #startEntity
+     */
+    public abstract void endEntity (String name)
+    throws SAXException;
+
+
+    /**
+     * Report the start of a CDATA section.
+     *
+     * <p>The contents of the CDATA section will be reported through
+     * the regular {@link org.xml.sax.ContentHandler#characters
+     * characters} event; this event is intended only to report
+     * the boundary.</p>
+     *
+     * @exception SAXException The application may raise an exception.
+     * @see #endCDATA
+     */
+    public abstract void startCDATA ()
+    throws SAXException;
+
+
+    /**
+     * Report the end of a CDATA section.
+     *
+     * @exception SAXException The application may raise an exception.
+     * @see #startCDATA
+     */
+    public abstract void endCDATA ()
+    throws SAXException;
+
+
+    /**
+     * Report an XML comment anywhere in the document.
+     *
+     * <p>This callback will be used for comments inside or outside the
+     * document element, including comments in the external DTD
+     * subset (if read).  Comments in the DTD must be properly
+     * nested inside start/endDTD and start/endEntity events (if
+     * used).</p>
+     *
+     * @param ch An array holding the characters in the comment.
+     * @param start The starting position in the array.
+     * @param length The number of characters to use from the array.
+     * @exception SAXException The application may raise an exception.
+     */
+    public abstract void comment (char ch[], int start, int length)
+    throws SAXException;
+
+}
+
+// end of LexicalHandler.java
diff --git a/xml/src/main/java/org/xml/sax/ext/Locator2.java b/xml/src/main/java/org/xml/sax/ext/Locator2.java
new file mode 100644
index 0000000..6de9a16
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/ext/Locator2.java
@@ -0,0 +1,75 @@
+// Locator2.java - extended Locator
+// http://www.saxproject.org
+// Public Domain: no warranty.
+// $Id: Locator2.java,v 1.5 2004/03/17 14:30:10 dmegginson Exp $
+
+package org.xml.sax.ext;
+
+import org.xml.sax.Locator;
+
+
+/**
+ * SAX2 extension to augment the entity information provided 
+ * though a {@link Locator}.
+ * If an implementation supports this extension, the Locator
+ * provided in {@link org.xml.sax.ContentHandler#setDocumentLocator
+ * ContentHandler.setDocumentLocator() } will implement this
+ * interface, and the
+ * <em>http://xml.org/sax/features/use-locator2</em> feature
+ * flag will have the value <em>true</em>.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * </blockquote>
+ *
+ * <p> XMLReader implementations are not required to support this
+ * information, and it is not part of core-only SAX2 distributions.</p>
+ *
+ * @since SAX 2.0 (extensions 1.1 alpha)
+ * @author David Brownell
+ * @version TBS
+ */
+public interface Locator2 extends Locator
+{
+    /**
+     * Returns the version of XML used for the entity.  This will
+     * normally be the identifier from the current entity's
+     * <em>&lt;?xml&nbsp;version='...'&nbsp;...?&gt;</em> declaration,
+     * or be defaulted by the parser.
+     *
+     * @return Identifier for the XML version being used to interpret
+     * the entity's text, or null if that information is not yet
+     * available in the current parsing state.
+     */
+    public String getXMLVersion ();
+
+    /**
+     * Returns the name of the character encoding for the entity.
+     * If the encoding was declared externally (for example, in a MIME
+     * Content-Type header), that will be the name returned.  Else if there
+     * was an <em>&lt;?xml&nbsp;...encoding='...'?&gt;</em> declaration at
+     * the start of the document, that encoding name will be returned.
+     * Otherwise the encoding will been inferred (normally to be UTF-8, or
+     * some UTF-16 variant), and that inferred name will be returned.
+     *
+     * <p>When an {@link org.xml.sax.InputSource InputSource} is used
+     * to provide an entity's character stream, this method returns the
+     * encoding provided in that input stream.
+     *
+     * <p> Note that some recent W3C specifications require that text
+     * in some encodings be normalized, using Unicode Normalization
+     * Form C, before processing.  Such normalization must be performed
+     * by applications, and would normally be triggered based on the
+     * value returned by this method.
+     *
+     * <p> Encoding names may be those used by the underlying JVM,
+     * and comparisons should be case-insensitive.
+     *
+     * @return Name of the character encoding being used to interpret
+     * * the entity's text, or null if this was not provided for a *
+     * character stream passed through an InputSource or is otherwise
+     * not yet available in the current parsing state.
+     */
+    public String getEncoding ();
+}
diff --git a/xml/src/main/java/org/xml/sax/ext/Locator2Impl.java b/xml/src/main/java/org/xml/sax/ext/Locator2Impl.java
new file mode 100644
index 0000000..91f912a
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/ext/Locator2Impl.java
@@ -0,0 +1,105 @@
+// Locator2Impl.java - extended LocatorImpl
+// http://www.saxproject.org
+// Public Domain: no warranty.
+// $Id: Locator2Impl.java,v 1.3 2004/04/26 17:34:35 dmegginson Exp $
+
+package org.xml.sax.ext;
+
+import org.xml.sax.Locator;
+import org.xml.sax.helpers.LocatorImpl;
+
+
+/**
+ * SAX2 extension helper for holding additional Entity information,
+ * implementing the {@link Locator2} interface.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * </blockquote>
+ *
+ * <p> This is not part of core-only SAX2 distributions.</p>
+ *
+ * @since SAX 2.0.2
+ * @author David Brownell
+ * @version TBS
+ */
+public class Locator2Impl extends LocatorImpl implements Locator2
+{
+    private String    encoding;
+    private String    version;
+
+
+    /**
+     * Construct a new, empty Locator2Impl object.
+     * This will not normally be useful, since the main purpose
+     * of this class is to make a snapshot of an existing Locator.
+     */
+    public Locator2Impl () { }
+
+    /**
+     * Copy an existing Locator or Locator2 object.
+     * If the object implements Locator2, values of the
+     * <em>encoding</em> and <em>version</em>strings are copied,
+     * otherwise they set to <em>null</em>. 
+     *
+     * @param locator The existing Locator object.
+     */
+    public Locator2Impl (Locator locator)
+    {
+    super (locator);
+    if (locator instanceof Locator2) {
+        Locator2    l2 = (Locator2) locator;
+
+        version = l2.getXMLVersion ();
+        encoding = l2.getEncoding ();
+    }
+    }
+
+    ////////////////////////////////////////////////////////////////////
+    // Locator2 method implementations
+    ////////////////////////////////////////////////////////////////////
+    
+    /**
+     * Returns the current value of the version property.
+     *
+     * @return the current value of the version property.
+     *
+     * @see #setXMLVersion
+     */
+    public String getXMLVersion ()
+    { return version; }
+
+    /**
+     * Returns the current value of the encoding property.
+     * 
+     * @return the current value of the encoding property.
+     *
+     * @see #setEncoding
+     */
+    public String getEncoding ()
+    { return encoding; }
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Setters 
+    ////////////////////////////////////////////////////////////////////
+    
+    /**
+     * Assigns the current value of the version property.
+     *
+     * @param version the new "version" value
+     * @see #getXMLVersion
+     */
+    public void setXMLVersion (String version)
+    { this.version = version; }
+
+    /**
+     * Assigns the current value of the encoding property.
+     *
+     * @param encoding the new "encoding" value
+     * @see #getEncoding
+     */
+    public void setEncoding (String encoding)
+    { this.encoding = encoding; }
+}
diff --git a/xml/src/main/java/org/xml/sax/ext/package.html b/xml/src/main/java/org/xml/sax/ext/package.html
new file mode 100644
index 0000000..9b79d77
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/ext/package.html
@@ -0,0 +1,48 @@
+<HTML><HEAD>
+<!-- $Id: package.html,v 1.8 2002/01/30 21:00:44 dbrownell Exp $ -->
+</HEAD><BODY>
+
+<p>
+This package contains interfaces to SAX2 facilities that
+conformant SAX drivers won't necessarily support.
+
+<p>See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+for more information about SAX.</p>
+
+<p> This package is independent of the SAX2 core, though the functionality
+exposed generally needs to be implemented within a parser core.
+That independence has several consequences:</p>
+
+<ul>
+
+<li>SAX2 drivers are <em>not</em> required to recognize these handlers.
+</li>
+
+<li>You cannot assume that the class files will be present in every SAX2
+installation.</li>
+
+<li>This package may be updated independently of SAX2 (i.e. new
+handlers and classes may be added without updating SAX2 itself).</li>
+
+<li>The new handlers are not implemented by the SAX2
+<code>org.xml.sax.helpers.DefaultHandler</code> or
+<code>org.xml.sax.helpers.XMLFilterImpl</code> classes.
+You can subclass these if you need such behavior, or
+use the helper classes found here.</li>
+
+<li>The handlers need to be registered differently than core SAX2
+handlers.</li>
+
+</ul>
+
+<p>This package, SAX2-ext, is a standardized extension to SAX2.  It is
+designed both to allow SAX parsers to pass certain types of information
+to applications, and to serve as a simple model for other SAX2 parser
+extension packages.  Not all such extension packages should need to
+be recognized directly by parsers, however.
+As an example, most validation systems can be cleanly layered on top
+of parsers supporting the standardized SAX2 interfaces.  </p>
+
+@since Android 1.0
+
+</BODY></HTML>
diff --git a/xml/src/main/java/org/xml/sax/helpers/AttributeListImpl.java b/xml/src/main/java/org/xml/sax/helpers/AttributeListImpl.java
new file mode 100644
index 0000000..fb4aee3
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/helpers/AttributeListImpl.java
@@ -0,0 +1,314 @@
+// SAX default implementation for AttributeList.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: AttributeListImpl.java,v 1.6 2002/01/30 20:52:22 dbrownell Exp $
+
+package org.xml.sax.helpers;
+
+import org.xml.sax.AttributeList;
+
+import java.util.Vector;
+
+
+/**
+ * Default implementation for AttributeList.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>AttributeList implements the deprecated SAX1 {@link
+ * org.xml.sax.AttributeList AttributeList} interface, and has been
+ * replaced by the new SAX2 {@link org.xml.sax.helpers.AttributesImpl
+ * AttributesImpl} interface.</p>
+ *
+ * <p>This class provides a convenience implementation of the SAX
+ * {@link org.xml.sax.AttributeList AttributeList} interface.  This 
+ * implementation is useful both for SAX parser writers, who can use 
+ * it to provide attributes to the application, and for SAX application 
+ * writers, who can use it to create a persistent copy of an element's 
+ * attribute specifications:</p>
+ *
+ * <pre>
+ * private AttributeList myatts;
+ *
+ * public void startElement (String name, AttributeList atts)
+ * {
+ *              // create a persistent copy of the attribute list
+ *              // for use outside this method
+ *   myatts = new AttributeListImpl(atts);
+ *   [...]
+ * }
+ * </pre>
+ *
+ * <p>Please note that SAX parsers are not required to use this
+ * class to provide an implementation of AttributeList; it is
+ * supplied only as an optional convenience.  In particular, 
+ * parser writers are encouraged to invent more efficient
+ * implementations.</p>
+ *
+ * @deprecated This class implements a deprecated interface,
+ *             {@link org.xml.sax.AttributeList AttributeList};
+ *             that interface has been replaced by
+ *             {@link org.xml.sax.Attributes Attributes},
+ *             which is implemented in the
+ *             {@link org.xml.sax.helpers.AttributesImpl 
+ *            AttributesImpl} helper class.
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.AttributeList
+ * @see org.xml.sax.DocumentHandler#startElement 
+ */
+public class AttributeListImpl implements AttributeList
+{
+    
+    /**
+     * Create an empty attribute list.
+     *
+     * <p>This constructor is most useful for parser writers, who
+     * will use it to create a single, reusable attribute list that
+     * can be reset with the clear method between elements.</p>
+     *
+     * @see #addAttribute
+     * @see #clear
+     */
+    public AttributeListImpl ()
+    {
+    }
+    
+    
+    /**
+     * Construct a persistent copy of an existing attribute list.
+     *
+     * <p>This constructor is most useful for application writers,
+     * who will use it to create a persistent copy of an existing
+     * attribute list.</p>
+     *
+     * @param atts The attribute list to copy
+     * @see org.xml.sax.DocumentHandler#startElement
+     */
+    public AttributeListImpl (AttributeList atts)
+    {
+    setAttributeList(atts);
+    }
+    
+    
+
+    ////////////////////////////////////////////////////////////////////
+    // Methods specific to this class.
+    ////////////////////////////////////////////////////////////////////
+    
+    
+    /**
+     * Set the attribute list, discarding previous contents.
+     *
+     * <p>This method allows an application writer to reuse an
+     * attribute list easily.</p>
+     *
+     * @param atts The attribute list to copy.
+     */
+    public void setAttributeList (AttributeList atts)
+    {
+    int count = atts.getLength();
+    
+    clear();
+    
+    for (int i = 0; i < count; i++) {
+        addAttribute(atts.getName(i), atts.getType(i), atts.getValue(i));
+    }
+    }
+    
+    
+    /**
+     * Add an attribute to an attribute list.
+     *
+     * <p>This method is provided for SAX parser writers, to allow them
+     * to build up an attribute list incrementally before delivering
+     * it to the application.</p>
+     *
+     * @param name The attribute name.
+     * @param type The attribute type ("NMTOKEN" for an enumeration).
+     * @param value The attribute value (must not be null).
+     * @see #removeAttribute
+     * @see org.xml.sax.DocumentHandler#startElement
+     */
+    public void addAttribute (String name, String type, String value)
+    {
+    names.addElement(name);
+    types.addElement(type);
+    values.addElement(value);
+    }
+    
+    
+    /**
+     * Remove an attribute from the list.
+     *
+     * <p>SAX application writers can use this method to filter an
+     * attribute out of an AttributeList.  Note that invoking this
+     * method will change the length of the attribute list and
+     * some of the attribute's indices.</p>
+     *
+     * <p>If the requested attribute is not in the list, this is
+     * a no-op.</p>
+     *
+     * @param name The attribute name.
+     * @see #addAttribute
+     */
+    public void removeAttribute (String name)
+    {
+    int i = names.indexOf(name);
+    
+    if (i >= 0) {
+        names.removeElementAt(i);
+        types.removeElementAt(i);
+        values.removeElementAt(i);
+    }
+    }
+    
+    
+    /**
+     * Clear the attribute list.
+     *
+     * <p>SAX parser writers can use this method to reset the attribute
+     * list between DocumentHandler.startElement events.  Normally,
+     * it will make sense to reuse the same AttributeListImpl object
+     * rather than allocating a new one each time.</p>
+     *
+     * @see org.xml.sax.DocumentHandler#startElement
+     */
+    public void clear ()
+    {
+    names.removeAllElements();
+    types.removeAllElements();
+    values.removeAllElements();
+    }
+    
+    
+
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.AttributeList
+    ////////////////////////////////////////////////////////////////////
+    
+    
+    /**
+     * Return the number of attributes in the list.
+     *
+     * @return The number of attributes in the list.
+     * @see org.xml.sax.AttributeList#getLength
+     */
+    public int getLength ()
+    {
+    return names.size();
+    }
+    
+    
+    /**
+     * Get the name of an attribute (by position).
+     *
+     * @param i The position of the attribute in the list.
+     * @return The attribute name as a string, or null if there
+     *         is no attribute at that position.
+     * @see org.xml.sax.AttributeList#getName(int)
+     */
+    public String getName (int i)
+    {
+    if (i < 0) {
+        return null;
+    }
+    try {
+        return (String)names.elementAt(i);
+    } catch (ArrayIndexOutOfBoundsException e) {
+        return null;
+    }
+    }
+    
+    
+    /**
+     * Get the type of an attribute (by position).
+     *
+     * @param i The position of the attribute in the list.
+     * @return The attribute type as a string ("NMTOKEN" for an
+     *         enumeration, and "CDATA" if no declaration was
+     *         read), or null if there is no attribute at
+     *         that position.
+     * @see org.xml.sax.AttributeList#getType(int)
+     */
+    public String getType (int i)
+    {
+    if (i < 0) {
+        return null;
+    }
+    try {
+        return (String)types.elementAt(i);
+    } catch (ArrayIndexOutOfBoundsException e) {
+        return null;
+    }
+    }
+    
+    
+    /**
+     * Get the value of an attribute (by position).
+     *
+     * @param i The position of the attribute in the list.
+     * @return The attribute value as a string, or null if
+     *         there is no attribute at that position.
+     * @see org.xml.sax.AttributeList#getValue(int)
+     */
+    public String getValue (int i)
+    {
+    if (i < 0) {
+        return null;
+    }
+    try {
+        return (String)values.elementAt(i);
+    } catch (ArrayIndexOutOfBoundsException e) {
+        return null;
+    }
+    }
+    
+    
+    /**
+     * Get the type of an attribute (by name).
+     *
+     * @param name The attribute name.
+     * @return The attribute type as a string ("NMTOKEN" for an
+     *         enumeration, and "CDATA" if no declaration was
+     *         read).
+     * @see org.xml.sax.AttributeList#getType(java.lang.String)
+     */
+    public String getType (String name)
+    {
+    return getType(names.indexOf(name));
+    }
+    
+    
+    /**
+     * Get the value of an attribute (by name).
+     *
+     * @param name The attribute name.
+     * @return the named attribute's value or null, if the attribute does not
+     *         exist.
+     * @see org.xml.sax.AttributeList#getValue(java.lang.String)
+     */
+    public String getValue (String name)
+    {
+    return getValue(names.indexOf(name));
+    }
+    
+    
+
+    ////////////////////////////////////////////////////////////////////
+    // Internal state.
+    ////////////////////////////////////////////////////////////////////
+
+    Vector names = new Vector();
+    Vector types = new Vector();
+    Vector values = new Vector();
+
+}
+
+// end of AttributeListImpl.java
diff --git a/xml/src/main/java/org/xml/sax/helpers/AttributesImpl.java b/xml/src/main/java/org/xml/sax/helpers/AttributesImpl.java
new file mode 100644
index 0000000..b740e23
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/helpers/AttributesImpl.java
@@ -0,0 +1,618 @@
+// AttributesImpl.java - default implementation of Attributes.
+// http://www.saxproject.org
+// Written by David Megginson
+// NO WARRANTY!  This class is in the public domain.
+// $Id: AttributesImpl.java,v 1.9 2002/01/30 20:52:24 dbrownell Exp $
+
+package org.xml.sax.helpers;
+
+import org.xml.sax.Attributes;
+
+
+/**
+ * Default implementation of the Attributes interface.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This class provides a default implementation of the SAX2
+ * {@link org.xml.sax.Attributes Attributes} interface, with the 
+ * addition of manipulators so that the list can be modified or 
+ * reused.</p>
+ *
+ * <p>There are two typical uses of this class:</p>
+ *
+ * <ol>
+ * <li>to take a persistent snapshot of an Attributes object
+ *  in a {@link org.xml.sax.ContentHandler#startElement startElement} event; or</li>
+ * <li>to construct or modify an Attributes object in a SAX2 driver or filter.</li>
+ * </ol>
+ *
+ * <p>This class replaces the now-deprecated SAX1 {@link 
+ * org.xml.sax.helpers.AttributeListImpl AttributeListImpl}
+ * class; in addition to supporting the updated Attributes
+ * interface rather than the deprecated {@link org.xml.sax.AttributeList
+ * AttributeList} interface, it also includes a much more efficient 
+ * implementation using a single array rather than a set of Vectors.</p>
+ *
+ * @since SAX 2.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ */
+public class AttributesImpl implements Attributes
+{
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Constructors.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Construct a new, empty AttributesImpl object.
+     */
+    public AttributesImpl ()
+    {
+    length = 0;
+    data = null;
+    }
+
+
+    /**
+     * Copy an existing Attributes object.
+     *
+     * <p>This constructor is especially useful inside a
+     * {@link org.xml.sax.ContentHandler#startElement startElement} event.</p>
+     *
+     * @param atts The existing Attributes object.
+     */
+    public AttributesImpl (Attributes atts)
+    {
+    setAttributes(atts);
+    }
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.Attributes.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Return the number of attributes in the list.
+     *
+     * @return The number of attributes in the list.
+     * @see org.xml.sax.Attributes#getLength
+     */
+    public int getLength ()
+    {
+    return length;
+    }
+
+
+    /**
+     * Return an attribute's Namespace URI.
+     *
+     * @param index The attribute's index (zero-based).
+     * @return The Namespace URI, the empty string if none is
+     *         available, or null if the index is out of range.
+     * @see org.xml.sax.Attributes#getURI
+     */
+    public String getURI (int index)
+    {
+    if (index >= 0 && index < length) {
+        return data[index*5];
+    } else {
+        return null;
+    }
+    }
+
+
+    /**
+     * Return an attribute's local name.
+     *
+     * @param index The attribute's index (zero-based).
+     * @return The attribute's local name, the empty string if 
+     *         none is available, or null if the index if out of range.
+     * @see org.xml.sax.Attributes#getLocalName
+     */
+    public String getLocalName (int index)
+    {
+    if (index >= 0 && index < length) {
+        return data[index*5+1];
+    } else {
+        return null;
+    }
+    }
+
+
+    /**
+     * Return an attribute's qualified (prefixed) name.
+     *
+     * @param index The attribute's index (zero-based).
+     * @return The attribute's qualified name, the empty string if 
+     *         none is available, or null if the index is out of bounds.
+     * @see org.xml.sax.Attributes#getQName
+     */
+    public String getQName (int index)
+    {
+    if (index >= 0 && index < length) {
+        return data[index*5+2];
+    } else {
+        return null;
+    }
+    }
+
+
+    /**
+     * Return an attribute's type by index.
+     *
+     * @param index The attribute's index (zero-based).
+     * @return The attribute's type, "CDATA" if the type is unknown, or null
+     *         if the index is out of bounds.
+     * @see org.xml.sax.Attributes#getType(int)
+     */
+    public String getType (int index)
+    {
+    if (index >= 0 && index < length) {
+        return data[index*5+3];
+    } else {
+        return null;
+    }
+    }
+
+
+    /**
+     * Return an attribute's value by index.
+     *
+     * @param index The attribute's index (zero-based).
+     * @return The attribute's value or null if the index is out of bounds.
+     * @see org.xml.sax.Attributes#getValue(int)
+     */
+    public String getValue (int index)
+    {
+    if (index >= 0 && index < length) {
+        return data[index*5+4];
+    } else {
+        return null;
+    }
+    }
+
+
+    /**
+     * Look up an attribute's index by Namespace name.
+     *
+     * <p>In many cases, it will be more efficient to look up the name once and
+     * use the index query methods rather than using the name query methods
+     * repeatedly.</p>
+     *
+     * @param uri The attribute's Namespace URI, or the empty
+     *        string if none is available.
+     * @param localName The attribute's local name.
+     * @return The attribute's index, or -1 if none matches.
+     * @see org.xml.sax.Attributes#getIndex(java.lang.String,java.lang.String)
+     */
+    public int getIndex (String uri, String localName)
+    {
+    int max = length * 5;
+    for (int i = 0; i < max; i += 5) {
+        if (data[i].equals(uri) && data[i+1].equals(localName)) {
+        return i / 5;
+        }
+    } 
+    return -1;
+    }
+
+
+    /**
+     * Look up an attribute's index by qualified (prefixed) name.
+     *
+     * @param qName The qualified name.
+     * @return The attribute's index, or -1 if none matches.
+     * @see org.xml.sax.Attributes#getIndex(java.lang.String)
+     */
+    public int getIndex (String qName)
+    {
+    int max = length * 5;
+    for (int i = 0; i < max; i += 5) {
+        if (data[i+2].equals(qName)) {
+        return i / 5;
+        }
+    } 
+    return -1;
+    }
+
+
+    /**
+     * Look up an attribute's type by Namespace-qualified name.
+     *
+     * @param uri The Namespace URI, or the empty string for a name
+     *        with no explicit Namespace URI.
+     * @param localName The local name.
+     * @return The attribute's type, or null if there is no
+     *         matching attribute.
+     * @see org.xml.sax.Attributes#getType(java.lang.String,java.lang.String)
+     */
+    public String getType (String uri, String localName)
+    {
+    int max = length * 5;
+    for (int i = 0; i < max; i += 5) {
+        if (data[i].equals(uri) && data[i+1].equals(localName)) {
+        return data[i+3];
+        }
+    } 
+    return null;
+    }
+
+
+    /**
+     * Look up an attribute's type by qualified (prefixed) name.
+     *
+     * @param qName The qualified name.
+     * @return The attribute's type, or null if there is no
+     *         matching attribute.
+     * @see org.xml.sax.Attributes#getType(java.lang.String)
+     */
+    public String getType (String qName)
+    {
+    int max = length * 5;
+    for (int i = 0; i < max; i += 5) {
+        if (data[i+2].equals(qName)) {
+        return data[i+3];
+        }
+    }
+    return null;
+    }
+
+
+    /**
+     * Look up an attribute's value by Namespace-qualified name.
+     *
+     * @param uri The Namespace URI, or the empty string for a name
+     *        with no explicit Namespace URI.
+     * @param localName The local name.
+     * @return The attribute's value, or null if there is no
+     *         matching attribute.
+     * @see org.xml.sax.Attributes#getValue(java.lang.String,java.lang.String)
+     */
+    public String getValue (String uri, String localName)
+    {
+    int max = length * 5;
+    for (int i = 0; i < max; i += 5) {
+        if (data[i].equals(uri) && data[i+1].equals(localName)) {
+        return data[i+4];
+        }
+    }
+    return null;
+    }
+
+
+    /**
+     * Look up an attribute's value by qualified (prefixed) name.
+     *
+     * @param qName The qualified name.
+     * @return The attribute's value, or null if there is no
+     *         matching attribute.
+     * @see org.xml.sax.Attributes#getValue(java.lang.String)
+     */
+    public String getValue (String qName)
+    {
+    int max = length * 5;
+    for (int i = 0; i < max; i += 5) {
+        if (data[i+2].equals(qName)) {
+        return data[i+4];
+        }
+    }
+    return null;
+    }
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Manipulators.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Clear the attribute list for reuse.
+     *
+     * <p>Note that little memory is freed by this call:
+     * the current array is kept so it can be 
+     * reused.</p>
+     */
+    public void clear ()
+    {
+    if (data != null) {
+        for (int i = 0; i < (length * 5); i++)
+        data [i] = null;
+    }
+    length = 0;
+    }
+
+
+    /**
+     * Copy an entire Attributes object.
+     *
+     * <p>It may be more efficient to reuse an existing object
+     * rather than constantly allocating new ones.</p>
+     * 
+     * @param atts The attributes to copy.
+     */
+    public void setAttributes (Attributes atts)
+    {
+        clear();
+        length = atts.getLength();
+        if (length > 0) {
+            data = new String[length*5];
+            for (int i = 0; i < length; i++) {
+                data[i*5] = atts.getURI(i);
+                data[i*5+1] = atts.getLocalName(i);
+                data[i*5+2] = atts.getQName(i);
+                data[i*5+3] = atts.getType(i);
+                data[i*5+4] = atts.getValue(i);
+            }
+    }
+    }
+
+
+    /**
+     * Add an attribute to the end of the list.
+     *
+     * <p>For the sake of speed, this method does no checking
+     * to see if the attribute is already in the list: that is
+     * the responsibility of the application.</p>
+     *
+     * @param uri The Namespace URI, or the empty string if
+     *        none is available or Namespace processing is not
+     *        being performed.
+     * @param localName The local name, or the empty string if
+     *        Namespace processing is not being performed.
+     * @param qName The qualified (prefixed) name, or the empty string
+     *        if qualified names are not available.
+     * @param type The attribute type as a string.
+     * @param value The attribute value.
+     */
+    public void addAttribute (String uri, String localName, String qName,
+                  String type, String value)
+    {
+    ensureCapacity(length+1);
+    data[length*5] = uri;
+    data[length*5+1] = localName;
+    data[length*5+2] = qName;
+    data[length*5+3] = type;
+    data[length*5+4] = value;
+    length++;
+    }
+
+
+    /**
+     * Set an attribute in the list.
+     *
+     * <p>For the sake of speed, this method does no checking
+     * for name conflicts or well-formedness: such checks are the
+     * responsibility of the application.</p>
+     *
+     * @param index The index of the attribute (zero-based).
+     * @param uri The Namespace URI, or the empty string if
+     *        none is available or Namespace processing is not
+     *        being performed.
+     * @param localName The local name, or the empty string if
+     *        Namespace processing is not being performed.
+     * @param qName The qualified name, or the empty string
+     *        if qualified names are not available.
+     * @param type The attribute type as a string.
+     * @param value The attribute value.
+     * @exception java.lang.ArrayIndexOutOfBoundsException When the
+     *            supplied index does not point to an attribute
+     *            in the list.
+     */
+    public void setAttribute (int index, String uri, String localName,
+                  String qName, String type, String value)
+    {
+    if (index >= 0 && index < length) {
+        data[index*5] = uri;
+        data[index*5+1] = localName;
+        data[index*5+2] = qName;
+        data[index*5+3] = type;
+        data[index*5+4] = value;
+    } else {
+        badIndex(index);
+    }
+    }
+
+
+    /**
+     * Remove an attribute from the list.
+     *
+     * @param index The index of the attribute (zero-based).
+     * @exception java.lang.ArrayIndexOutOfBoundsException When the
+     *            supplied index does not point to an attribute
+     *            in the list.
+     */
+    public void removeAttribute (int index)
+    {
+    if (index >= 0 && index < length) {
+        if (index < length - 1) {
+        System.arraycopy(data, (index+1)*5, data, index*5,
+                 (length-index-1)*5);
+        }
+        index = (length - 1) * 5;
+        data [index++] = null;
+        data [index++] = null;
+        data [index++] = null;
+        data [index++] = null;
+        data [index] = null;
+        length--;
+    } else {
+        badIndex(index);
+    }
+    }
+
+
+    /**
+     * Set the Namespace URI of a specific attribute.
+     *
+     * @param index The index of the attribute (zero-based).
+     * @param uri The attribute's Namespace URI, or the empty
+     *        string for none.
+     * @exception java.lang.ArrayIndexOutOfBoundsException When the
+     *            supplied index does not point to an attribute
+     *            in the list.
+     */
+    public void setURI (int index, String uri)
+    {
+    if (index >= 0 && index < length) {
+        data[index*5] = uri;
+    } else {
+        badIndex(index);
+    }
+    }
+
+
+    /**
+     * Set the local name of a specific attribute.
+     *
+     * @param index The index of the attribute (zero-based).
+     * @param localName The attribute's local name, or the empty
+     *        string for none.
+     * @exception java.lang.ArrayIndexOutOfBoundsException When the
+     *            supplied index does not point to an attribute
+     *            in the list.
+     */
+    public void setLocalName (int index, String localName)
+    {
+    if (index >= 0 && index < length) {
+        data[index*5+1] = localName;
+    } else {
+        badIndex(index);
+    }
+    }
+
+
+    /**
+     * Set the qualified name of a specific attribute.
+     *
+     * @param index The index of the attribute (zero-based).
+     * @param qName The attribute's qualified name, or the empty
+     *        string for none.
+     * @exception java.lang.ArrayIndexOutOfBoundsException When the
+     *            supplied index does not point to an attribute
+     *            in the list.
+     */
+    public void setQName (int index, String qName)
+    {
+    if (index >= 0 && index < length) {
+        data[index*5+2] = qName;
+    } else {
+        badIndex(index);
+    }
+    }
+
+
+    /**
+     * Set the type of a specific attribute.
+     *
+     * @param index The index of the attribute (zero-based).
+     * @param type The attribute's type.
+     * @exception java.lang.ArrayIndexOutOfBoundsException When the
+     *            supplied index does not point to an attribute
+     *            in the list.
+     */
+    public void setType (int index, String type)
+    {
+    if (index >= 0 && index < length) {
+        data[index*5+3] = type;
+    } else {
+        badIndex(index);
+    }
+    }
+
+
+    /**
+     * Set the value of a specific attribute.
+     *
+     * @param index The index of the attribute (zero-based).
+     * @param value The attribute's value.
+     * @exception java.lang.ArrayIndexOutOfBoundsException When the
+     *            supplied index does not point to an attribute
+     *            in the list.
+     */
+    public void setValue (int index, String value)
+    {
+    if (index >= 0 && index < length) {
+        data[index*5+4] = value;
+    } else {
+        badIndex(index);
+    }
+    }
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Internal methods.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Ensure the internal array's capacity.
+     *
+     * @param n The minimum number of attributes that the array must
+     *        be able to hold.
+     */
+    private void ensureCapacity (int n)    {
+        if (n <= 0) {
+            return;
+        }
+        int max;
+        if (data == null || data.length == 0) {
+            max = 25;
+        }
+        else if (data.length >= n * 5) {
+            return;
+        }
+        else {
+            max = data.length;
+        }
+        while (max < n * 5) {
+            max *= 2;
+        }
+
+        String newData[] = new String[max];
+        if (length > 0) {
+            System.arraycopy(data, 0, newData, 0, length*5);
+        }
+        data = newData;
+    }
+
+
+    /**
+     * Report a bad array index in a manipulator.
+     *
+     * @param index The index to report.
+     * @exception java.lang.ArrayIndexOutOfBoundsException Always.
+     */
+    private void badIndex (int index)
+    throws ArrayIndexOutOfBoundsException
+    {
+    String msg =
+        "Attempt to modify attribute at illegal index: " + index;
+    throw new ArrayIndexOutOfBoundsException(msg);
+    }
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Internal state.
+    ////////////////////////////////////////////////////////////////////
+
+    int length;
+    String data [];
+
+}
+
+// end of AttributesImpl.java
+
diff --git a/xml/src/main/java/org/xml/sax/helpers/DefaultHandler.java b/xml/src/main/java/org/xml/sax/helpers/DefaultHandler.java
new file mode 100644
index 0000000..8308be7
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/helpers/DefaultHandler.java
@@ -0,0 +1,467 @@
+// DefaultHandler.java - default implementation of the core handlers.
+// http://www.saxproject.org
+// Written by David Megginson
+// NO WARRANTY!  This class is in the public domain.
+// $Id: DefaultHandler.java,v 1.9 2004/04/26 17:34:35 dmegginson Exp $
+
+package org.xml.sax.helpers;
+
+import java.io.IOException;
+
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.Attributes;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+
+/**
+ * Default base class for SAX2 event handlers.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This class is available as a convenience base class for SAX2
+ * applications: it provides default implementations for all of the
+ * callbacks in the four core SAX2 handler classes:</p>
+ *
+ * <ul>
+ * <li>{@link org.xml.sax.EntityResolver EntityResolver}</li>
+ * <li>{@link org.xml.sax.DTDHandler DTDHandler}</li>
+ * <li>{@link org.xml.sax.ContentHandler ContentHandler}</li>
+ * <li>{@link org.xml.sax.ErrorHandler ErrorHandler}</li>
+ * </ul>
+ *
+ * <p>Application writers can extend this class when they need to
+ * implement only part of an interface; parser writers can
+ * instantiate this class to provide default handlers when the
+ * application has not supplied its own.</p>
+ *
+ * <p>This class replaces the deprecated SAX1
+ * {@link org.xml.sax.HandlerBase HandlerBase} class.</p>
+ *
+ * @since SAX 2.0
+ * @author David Megginson,
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.EntityResolver
+ * @see org.xml.sax.DTDHandler
+ * @see org.xml.sax.ContentHandler
+ * @see org.xml.sax.ErrorHandler
+ */
+public class DefaultHandler
+    implements EntityResolver, DTDHandler, ContentHandler, ErrorHandler
+{
+    
+
+    ////////////////////////////////////////////////////////////////////
+    // Default implementation of the EntityResolver interface.
+    ////////////////////////////////////////////////////////////////////
+    
+    /**
+     * Resolve an external entity.
+     *
+     * <p>Always return null, so that the parser will use the system
+     * identifier provided in the XML document.  This method implements
+     * the SAX default behaviour: application writers can override it
+     * in a subclass to do special translations such as catalog lookups
+     * or URI redirection.</p>
+     *
+     * @param publicId The public identifer, or null if none is
+     *                 available.
+     * @param systemId The system identifier provided in the XML 
+     *                 document.
+     * @return The new input source, or null to require the
+     *         default behaviour.
+     * @exception java.io.IOException If there is an error setting
+     *            up the new input source.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.EntityResolver#resolveEntity
+     */
+    public InputSource resolveEntity (String publicId, String systemId)
+    throws IOException, SAXException
+    {
+    return null;
+    }
+    
+    
+
+    ////////////////////////////////////////////////////////////////////
+    // Default implementation of DTDHandler interface.
+    ////////////////////////////////////////////////////////////////////
+    
+    
+    /**
+     * Receive notification of a notation declaration.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass if they wish to keep track of the notations
+     * declared in a document.</p>
+     *
+     * @param name The notation name.
+     * @param publicId The notation public identifier, or null if not
+     *                 available.
+     * @param systemId The notation system identifier.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.DTDHandler#notationDecl
+     */
+    public void notationDecl (String name, String publicId, String systemId)
+    throws SAXException
+    {
+    // no op
+    }
+    
+    
+    /**
+     * Receive notification of an unparsed entity declaration.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to keep track of the unparsed entities
+     * declared in a document.</p>
+     *
+     * @param name The entity name.
+     * @param publicId The entity public identifier, or null if not
+     *                 available.
+     * @param systemId The entity system identifier.
+     * @param notationName The name of the associated notation.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.DTDHandler#unparsedEntityDecl
+     */
+    public void unparsedEntityDecl (String name, String publicId,
+                    String systemId, String notationName)
+    throws SAXException
+    {
+    // no op
+    }
+    
+    
+
+    ////////////////////////////////////////////////////////////////////
+    // Default implementation of ContentHandler interface.
+    ////////////////////////////////////////////////////////////////////
+    
+    
+    /**
+     * Receive a Locator object for document events.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass if they wish to store the locator for use
+     * with other document events.</p>
+     *
+     * @param locator A locator for all SAX document events.
+     * @see org.xml.sax.ContentHandler#setDocumentLocator
+     * @see org.xml.sax.Locator
+     */
+    public void setDocumentLocator (Locator locator)
+    {
+    // no op
+    }
+    
+    
+    /**
+     * Receive notification of the beginning of the document.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions at the beginning
+     * of a document (such as allocating the root node of a tree or
+     * creating an output file).</p>
+     *
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ContentHandler#startDocument
+     */
+    public void startDocument ()
+    throws SAXException
+    {
+    // no op
+    }
+    
+    
+    /**
+     * Receive notification of the end of the document.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions at the end
+     * of a document (such as finalising a tree or closing an output
+     * file).</p>
+     *
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ContentHandler#endDocument
+     */
+    public void endDocument ()
+    throws SAXException
+    {
+    // no op
+    }
+
+
+    /**
+     * Receive notification of the start of a Namespace mapping.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions at the start of
+     * each Namespace prefix scope (such as storing the prefix mapping).</p>
+     *
+     * @param prefix The Namespace prefix being declared.
+     * @param uri The Namespace URI mapped to the prefix.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ContentHandler#startPrefixMapping
+     */
+    public void startPrefixMapping (String prefix, String uri)
+    throws SAXException
+    {
+    // no op
+    }
+
+
+    /**
+     * Receive notification of the end of a Namespace mapping.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions at the end of
+     * each prefix mapping.</p>
+     *
+     * @param prefix The Namespace prefix being declared.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ContentHandler#endPrefixMapping
+     */
+    public void endPrefixMapping (String prefix)
+    throws SAXException
+    {
+    // no op
+    }
+    
+    
+    /**
+     * Receive notification of the start of an element.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions at the start of
+     * each element (such as allocating a new tree node or writing
+     * output to a file).</p>
+     *
+     * @param uri The Namespace URI, or the empty string if the
+     *        element has no Namespace URI or if Namespace
+     *        processing is not being performed.
+     * @param localName The local name (without prefix), or the
+     *        empty string if Namespace processing is not being
+     *        performed.
+     * @param qName The qualified name (with prefix), or the
+     *        empty string if qualified names are not available.
+     * @param attributes The attributes attached to the element.  If
+     *        there are no attributes, it shall be an empty
+     *        Attributes object.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ContentHandler#startElement
+     */
+    public void startElement (String uri, String localName,
+                  String qName, Attributes attributes)
+    throws SAXException
+    {
+    // no op
+    }
+    
+    
+    /**
+     * Receive notification of the end of an element.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions at the end of
+     * each element (such as finalising a tree node or writing
+     * output to a file).</p>
+     *
+     * @param uri The Namespace URI, or the empty string if the
+     *        element has no Namespace URI or if Namespace
+     *        processing is not being performed.
+     * @param localName The local name (without prefix), or the
+     *        empty string if Namespace processing is not being
+     *        performed.
+     * @param qName The qualified name (with prefix), or the
+     *        empty string if qualified names are not available.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ContentHandler#endElement
+     */
+    public void endElement (String uri, String localName, String qName)
+    throws SAXException
+    {
+    // no op
+    }
+    
+    
+    /**
+     * Receive notification of character data inside an element.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method to take specific actions for each chunk of character data
+     * (such as adding the data to a node or buffer, or printing it to
+     * a file).</p>
+     *
+     * @param ch The characters.
+     * @param start The start position in the character array.
+     * @param length The number of characters to use from the
+     *               character array.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ContentHandler#characters
+     */
+    public void characters (char ch[], int start, int length)
+    throws SAXException
+    {
+    // no op
+    }
+    
+    
+    /**
+     * Receive notification of ignorable whitespace in element content.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method to take specific actions for each chunk of ignorable
+     * whitespace (such as adding data to a node or buffer, or printing
+     * it to a file).</p>
+     *
+     * @param ch The whitespace characters.
+     * @param start The start position in the character array.
+     * @param length The number of characters to use from the
+     *               character array.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ContentHandler#ignorableWhitespace
+     */
+    public void ignorableWhitespace (char ch[], int start, int length)
+    throws SAXException
+    {
+    // no op
+    }
+    
+    
+    /**
+     * Receive notification of a processing instruction.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions for each
+     * processing instruction, such as setting status variables or
+     * invoking other methods.</p>
+     *
+     * @param target The processing instruction target.
+     * @param data The processing instruction data, or null if
+     *             none is supplied.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ContentHandler#processingInstruction
+     */
+    public void processingInstruction (String target, String data)
+    throws SAXException
+    {
+    // no op
+    }
+
+
+    /**
+     * Receive notification of a skipped entity.
+     *
+     * <p>By default, do nothing.  Application writers may override this
+     * method in a subclass to take specific actions for each
+     * processing instruction, such as setting status variables or
+     * invoking other methods.</p>
+     *
+     * @param name The name of the skipped entity.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ContentHandler#processingInstruction
+     */
+    public void skippedEntity (String name)
+    throws SAXException
+    {
+    // no op
+    }
+    
+    
+
+    ////////////////////////////////////////////////////////////////////
+    // Default implementation of the ErrorHandler interface.
+    ////////////////////////////////////////////////////////////////////
+    
+    
+    /**
+     * Receive notification of a parser warning.
+     *
+     * <p>The default implementation does nothing.  Application writers
+     * may override this method in a subclass to take specific actions
+     * for each warning, such as inserting the message in a log file or
+     * printing it to the console.</p>
+     *
+     * @param e The warning information encoded as an exception.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ErrorHandler#warning
+     * @see org.xml.sax.SAXParseException
+     */
+    public void warning (SAXParseException e)
+    throws SAXException
+    {
+    // no op
+    }
+    
+    
+    /**
+     * Receive notification of a recoverable parser error.
+     *
+     * <p>The default implementation does nothing.  Application writers
+     * may override this method in a subclass to take specific actions
+     * for each error, such as inserting the message in a log file or
+     * printing it to the console.</p>
+     *
+     * @param e The warning information encoded as an exception.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ErrorHandler#warning
+     * @see org.xml.sax.SAXParseException
+     */
+    public void error (SAXParseException e)
+    throws SAXException
+    {
+    // no op
+    }
+    
+    
+    /**
+     * Report a fatal XML parsing error.
+     *
+     * <p>The default implementation throws a SAXParseException.
+     * Application writers may override this method in a subclass if
+     * they need to take specific actions for each fatal error (such as
+     * collecting all of the errors into a single report): in any case,
+     * the application must stop all regular processing when this
+     * method is invoked, since the document is no longer reliable, and
+     * the parser may no longer report parsing events.</p>
+     *
+     * @param e The error information encoded as an exception.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see org.xml.sax.ErrorHandler#fatalError
+     * @see org.xml.sax.SAXParseException
+     */
+    public void fatalError (SAXParseException e)
+    throws SAXException
+    {
+    throw e;
+    }
+    
+}
+
+// end of DefaultHandler.java
diff --git a/xml/src/main/java/org/xml/sax/helpers/LocatorImpl.java b/xml/src/main/java/org/xml/sax/helpers/LocatorImpl.java
new file mode 100644
index 0000000..18445bc
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/helpers/LocatorImpl.java
@@ -0,0 +1,214 @@
+// SAX default implementation for Locator.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: LocatorImpl.java,v 1.6 2002/01/30 20:52:27 dbrownell Exp $
+
+package org.xml.sax.helpers;
+
+import org.xml.sax.Locator;
+
+
+/**
+ * Provide an optional convenience implementation of Locator.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This class is available mainly for application writers, who
+ * can use it to make a persistent snapshot of a locator at any
+ * point during a document parse:</p>
+ *
+ * <pre>
+ * Locator locator;
+ * Locator startloc;
+ *
+ * public void setLocator (Locator locator)
+ * {
+ *         // note the locator
+ *   this.locator = locator;
+ * }
+ *
+ * public void startDocument ()
+ * {
+ *         // save the location of the start of the document
+ *         // for future use.
+ *   Locator startloc = new LocatorImpl(locator);
+ * }
+ *</pre>
+ *
+ * <p>Normally, parser writers will not use this class, since it
+ * is more efficient to provide location information only when
+ * requested, rather than constantly updating a Locator object.</p>
+ *
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.Locator Locator
+ */
+public class LocatorImpl implements Locator
+{
+    
+    
+    /**
+     * Zero-argument constructor.
+     *
+     * <p>This will not normally be useful, since the main purpose
+     * of this class is to make a snapshot of an existing Locator.</p>
+     */
+    public LocatorImpl ()
+    {
+    }
+    
+    
+    /**
+     * Copy constructor.
+     *
+     * <p>Create a persistent copy of the current state of a locator.
+     * When the original locator changes, this copy will still keep
+     * the original values (and it can be used outside the scope of
+     * DocumentHandler methods).</p>
+     *
+     * @param locator The locator to copy.
+     */
+    public LocatorImpl (Locator locator)
+    {
+    setPublicId(locator.getPublicId());
+    setSystemId(locator.getSystemId());
+    setLineNumber(locator.getLineNumber());
+    setColumnNumber(locator.getColumnNumber());
+    }
+    
+    
+
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.Locator
+    ////////////////////////////////////////////////////////////////////
+    
+    
+    /**
+     * Return the saved public identifier.
+     *
+     * @return The public identifier as a string, or null if none
+     *         is available.
+     * @see org.xml.sax.Locator#getPublicId
+     * @see #setPublicId
+     */
+    public String getPublicId ()
+    {
+    return publicId;
+    }
+    
+    
+    /**
+     * Return the saved system identifier.
+     *
+     * @return The system identifier as a string, or null if none
+     *         is available.
+     * @see org.xml.sax.Locator#getSystemId
+     * @see #setSystemId
+     */
+    public String getSystemId ()
+    {
+    return systemId;
+    }
+    
+    
+    /**
+     * Return the saved line number (1-based).
+     *
+     * @return The line number as an integer, or -1 if none is available.
+     * @see org.xml.sax.Locator#getLineNumber
+     * @see #setLineNumber
+     */
+    public int getLineNumber ()
+    {
+    return lineNumber;
+    }
+    
+    
+    /**
+     * Return the saved column number (1-based).
+     *
+     * @return The column number as an integer, or -1 if none is available.
+     * @see org.xml.sax.Locator#getColumnNumber
+     * @see #setColumnNumber
+     */
+    public int getColumnNumber ()
+    {
+    return columnNumber;
+    }
+    
+    
+
+    ////////////////////////////////////////////////////////////////////
+    // Setters for the properties (not in org.xml.sax.Locator)
+    ////////////////////////////////////////////////////////////////////
+    
+    
+    /**
+     * Set the public identifier for this locator.
+     *
+     * @param publicId The new public identifier, or null 
+     *        if none is available.
+     * @see #getPublicId
+     */
+    public void setPublicId (String publicId)
+    {
+    this.publicId = publicId;
+    }
+    
+    
+    /**
+     * Set the system identifier for this locator.
+     *
+     * @param systemId The new system identifier, or null 
+     *        if none is available.
+     * @see #getSystemId
+     */
+    public void setSystemId (String systemId)
+    {
+    this.systemId = systemId;
+    }
+    
+    
+    /**
+     * Set the line number for this locator (1-based).
+     *
+     * @param lineNumber The line number, or -1 if none is available.
+     * @see #getLineNumber
+     */
+    public void setLineNumber (int lineNumber)
+    {
+    this.lineNumber = lineNumber;
+    }
+    
+    
+    /**
+     * Set the column number for this locator (1-based).
+     *
+     * @param columnNumber The column number, or -1 if none is available.
+     * @see #getColumnNumber
+     */
+    public void setColumnNumber (int columnNumber)
+    {
+    this.columnNumber = columnNumber;
+    }
+    
+    
+
+    ////////////////////////////////////////////////////////////////////
+    // Internal state.
+    ////////////////////////////////////////////////////////////////////
+    
+    private String publicId;
+    private String systemId;
+    private int lineNumber;
+    private int columnNumber;
+    
+}
+
+// end of LocatorImpl.java
diff --git a/xml/src/main/java/org/xml/sax/helpers/NamespaceSupport.java b/xml/src/main/java/org/xml/sax/helpers/NamespaceSupport.java
new file mode 100644
index 0000000..a737d1d
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/helpers/NamespaceSupport.java
@@ -0,0 +1,840 @@
+// NamespaceSupport.java - generic Namespace support for SAX.
+// http://www.saxproject.org
+// Written by David Megginson
+// This class is in the Public Domain.  NO WARRANTY!
+// $Id: NamespaceSupport.java,v 1.15 2004/04/26 17:34:35 dmegginson Exp $
+
+package org.xml.sax.helpers;
+
+import java.util.EmptyStackException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+
+/**
+ * Encapsulate Namespace logic for use by applications using SAX,
+ * or internally by SAX drivers.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This class encapsulates the logic of Namespace processing: it
+ * tracks the declarations currently in force for each context and
+ * automatically processes qualified XML names into their Namespace
+ * parts; it can also be used in reverse for generating XML qnames
+ * from Namespaces.</p>
+ *
+ * <p>Namespace support objects are reusable, but the reset method
+ * must be invoked between each session.</p>
+ *
+ * <p>Here is a simple session:</p>
+ *
+ * <pre>
+ * String parts[] = new String[3];
+ * NamespaceSupport support = new NamespaceSupport();
+ *
+ * support.pushContext();
+ * support.declarePrefix("", "http://www.w3.org/1999/xhtml");
+ * support.declarePrefix("dc", "http://www.purl.org/dc#");
+ *
+ * parts = support.processName("p", parts, false);
+ * System.out.println("Namespace URI: " + parts[0]);
+ * System.out.println("Local name: " + parts[1]);
+ * System.out.println("Raw name: " + parts[2]);
+ *
+ * parts = support.processName("dc:title", parts, false);
+ * System.out.println("Namespace URI: " + parts[0]);
+ * System.out.println("Local name: " + parts[1]);
+ * System.out.println("Raw name: " + parts[2]);
+ *
+ * support.popContext();
+ * </pre>
+ *
+ * <p>Note that this class is optimized for the use case where most
+ * elements do not contain Namespace declarations: if the same
+ * prefix/URI mapping is repeated for each context (for example), this
+ * class will be somewhat less efficient.</p>
+ *
+ * <p>Although SAX drivers (parsers) may choose to use this class to
+ * implement namespace handling, they are not required to do so.
+ * Applications must track namespace information themselves if they
+ * want to use namespace information.
+ *
+ * @since SAX 2.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ */
+public class NamespaceSupport
+{
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Constants.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * The XML Namespace URI as a constant.
+     * The value is <code>http://www.w3.org/XML/1998/namespace</code>
+     * as defined in the "Namespaces in XML" * recommendation.
+     *
+     * <p>This is the Namespace URI that is automatically mapped
+     * to the "xml" prefix.</p>
+     */
+    public final static String XMLNS =
+    "http://www.w3.org/XML/1998/namespace";
+
+
+    /**
+     * The namespace declaration URI as a constant.
+     * The value is <code>http://www.w3.org/xmlns/2000/</code>, as defined
+     * in a backwards-incompatible erratum to the "Namespaces in XML"
+     * recommendation.  Because that erratum postdated SAX2, SAX2 defaults 
+     * to the original recommendation, and does not normally use this URI.
+     * 
+     *
+     * <p>This is the Namespace URI that is optionally applied to
+     * <em>xmlns</em> and <em>xmlns:*</em> attributes, which are used to
+     * declare namespaces.  </p>
+     *
+     * @since SAX 2.1alpha
+     * @see #setNamespaceDeclUris
+     * @see #isNamespaceDeclUris
+     */
+    public final static String NSDECL =
+    "http://www.w3.org/xmlns/2000/";
+
+
+    /**
+     * An empty enumeration.
+     */
+    private final static Enumeration EMPTY_ENUMERATION =
+    new Vector().elements();
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Constructor.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Create a new Namespace support object.
+     */
+    public NamespaceSupport ()
+    {
+    reset();
+    }
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Context management.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Reset this Namespace support object for reuse.
+     *
+     * <p>It is necessary to invoke this method before reusing the
+     * Namespace support object for a new session.  If namespace
+     * declaration URIs are to be supported, that flag must also
+     * be set to a non-default value.
+     * </p>
+     *
+     * @see #setNamespaceDeclUris
+     */
+    public void reset ()
+    {
+    contexts = new Context[32];
+    namespaceDeclUris = false;
+    contextPos = 0;
+    contexts[contextPos] = currentContext = new Context();
+    currentContext.declarePrefix("xml", XMLNS);
+    }
+
+
+    /**
+     * Start a new Namespace context.
+     * The new context will automatically inherit
+     * the declarations of its parent context, but it will also keep
+     * track of which declarations were made within this context.
+     *
+     * <p>Event callback code should start a new context once per element.
+     * This means being ready to call this in either of two places.
+     * For elements that don't include namespace declarations, the
+     * <em>ContentHandler.startElement()</em> callback is the right place.
+     * For elements with such a declaration, it'd done in the first
+     * <em>ContentHandler.startPrefixMapping()</em> callback.
+     * A boolean flag can be used to
+     * track whether a context has been started yet.  When either of
+     * those methods is called, it checks the flag to see if a new context
+     * needs to be started.  If so, it starts the context and sets the
+     * flag.  After <em>ContentHandler.startElement()</em>
+     * does that, it always clears the flag.
+     *
+     * <p>Normally, SAX drivers would push a new context at the beginning
+     * of each XML element.  Then they perform a first pass over the
+     * attributes to process all namespace declarations, making
+     * <em>ContentHandler.startPrefixMapping()</em> callbacks.
+     * Then a second pass is made, to determine the namespace-qualified
+     * names for all attributes and for the element name.
+     * Finally all the information for the
+     * <em>ContentHandler.startElement()</em> callback is available,
+     * so it can then be made.
+     *
+     * <p>The Namespace support object always starts with a base context
+     * already in force: in this context, only the "xml" prefix is
+     * declared.</p>
+     *
+     * @see org.xml.sax.ContentHandler
+     * @see #popContext
+     */
+    public void pushContext ()
+    {
+    int max = contexts.length;
+
+    contexts [contextPos].declsOK = false;
+    contextPos++;
+
+                // Extend the array if necessary
+    if (contextPos >= max) {
+        Context newContexts[] = new Context[max*2];
+        System.arraycopy(contexts, 0, newContexts, 0, max);
+        max *= 2;
+        contexts = newContexts;
+    }
+
+                // Allocate the context if necessary.
+    currentContext = contexts[contextPos];
+    if (currentContext == null) {
+        contexts[contextPos] = currentContext = new Context();
+    }
+
+                // Set the parent, if any.
+    if (contextPos > 0) {
+        currentContext.setParent(contexts[contextPos - 1]);
+    }
+    }
+
+
+    /**
+     * Revert to the previous Namespace context.
+     *
+     * <p>Normally, you should pop the context at the end of each
+     * XML element.  After popping the context, all Namespace prefix
+     * mappings that were previously in force are restored.</p>
+     *
+     * <p>You must not attempt to declare additional Namespace
+     * prefixes after popping a context, unless you push another
+     * context first.</p>
+     *
+     * @see #pushContext
+     */
+    public void popContext ()
+    {
+    contexts[contextPos].clear();
+    contextPos--;
+    if (contextPos < 0) {
+        throw new EmptyStackException();
+    }
+    currentContext = contexts[contextPos];
+    }
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Operations within a context.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Declare a Namespace prefix.  All prefixes must be declared
+     * before they are referenced.  For example, a SAX driver (parser)
+     * would scan an element's attributes
+     * in two passes:  first for namespace declarations,
+     * then a second pass using {@link #processName processName()} to
+     * interpret prefixes against (potentially redefined) prefixes.
+     *
+     * <p>This method declares a prefix in the current Namespace
+     * context; the prefix will remain in force until this context
+     * is popped, unless it is shadowed in a descendant context.</p>
+     *
+     * <p>To declare the default element Namespace, use the empty string as
+     * the prefix.</p>
+     *
+     * <p>Note that you must <em>not</em> declare a prefix after
+     * you've pushed and popped another Namespace context, or
+     * treated the declarations phase as complete by processing
+     * a prefixed name.</p>
+     *
+     * <p>Note that there is an asymmetry in this library: {@link
+     * #getPrefix getPrefix} will not return the "" prefix,
+     * even if you have declared a default element namespace.
+     * To check for a default namespace,
+     * you have to look it up explicitly using {@link #getURI getURI}.
+     * This asymmetry exists to make it easier to look up prefixes
+     * for attribute names, where the default prefix is not allowed.</p>
+     *
+     * @param prefix The prefix to declare, or the empty string to
+     *    indicate the default element namespace.  This may never have
+     *    the value "xml" or "xmlns".
+     * @param uri The Namespace URI to associate with the prefix.
+     * @return true if the prefix was legal, false otherwise
+     *
+     * @see #processName
+     * @see #getURI
+     * @see #getPrefix
+     */
+    public boolean declarePrefix (String prefix, String uri)
+    {
+    if (prefix.equals("xml") || prefix.equals("xmlns")) {
+        return false;
+    } else {
+        currentContext.declarePrefix(prefix, uri);
+        return true;
+    }
+    }
+
+
+    /**
+     * Process a raw XML qualified name, after all declarations in the
+     * current context have been handled by {@link #declarePrefix
+     * declarePrefix()}.
+     *
+     * <p>This method processes a raw XML qualified name in the
+     * current context by removing the prefix and looking it up among
+     * the prefixes currently declared.  The return value will be the
+     * array supplied by the caller, filled in as follows:</p>
+     *
+     * <dl>
+     * <dt>parts[0]</dt>
+     * <dd>The Namespace URI, or an empty string if none is
+     *  in use.</dd>
+     * <dt>parts[1]</dt>
+     * <dd>The local name (without prefix).</dd>
+     * <dt>parts[2]</dt>
+     * <dd>The original raw name.</dd>
+     * </dl>
+     *
+     * <p>All of the strings in the array will be internalized.  If
+     * the raw name has a prefix that has not been declared, then
+     * the return value will be null.</p>
+     *
+     * <p>Note that attribute names are processed differently than
+     * element names: an unprefixed element name will receive the
+     * default Namespace (if any), while an unprefixed attribute name
+     * will not.</p>
+     *
+     * @param qName The XML qualified name to be processed.
+     * @param parts An array supplied by the caller, capable of
+     *        holding at least three members.
+     * @param isAttribute A flag indicating whether this is an
+     *        attribute name (true) or an element name (false).
+     * @return The supplied array holding three internalized strings 
+     *        representing the Namespace URI (or empty string), the
+     *        local name, and the XML qualified name; or null if there
+     *        is an undeclared prefix.
+     * @see #declarePrefix
+     * @see java.lang.String#intern */
+    public String [] processName (String qName, String parts[],
+                  boolean isAttribute)
+    {
+    String myParts[] = currentContext.processName(qName, isAttribute);
+    if (myParts == null) {
+        return null;
+    } else {
+        parts[0] = myParts[0];
+        parts[1] = myParts[1];
+        parts[2] = myParts[2];
+        return parts;
+    }
+    }
+
+
+    /**
+     * Look up a prefix and get the currently-mapped Namespace URI.
+     *
+     * <p>This method looks up the prefix in the current context.
+     * Use the empty string ("") for the default Namespace.</p>
+     *
+     * @param prefix The prefix to look up.
+     * @return The associated Namespace URI, or null if the prefix
+     *         is undeclared in this context.
+     * @see #getPrefix
+     * @see #getPrefixes
+     */
+    public String getURI (String prefix)
+    {
+    return currentContext.getURI(prefix);
+    }
+
+
+    /**
+     * Return an enumeration of all prefixes whose declarations are
+     * active in the current context.
+     * This includes declarations from parent contexts that have
+     * not been overridden.
+     *
+     * <p><strong>Note:</strong> if there is a default prefix, it will not be
+     * returned in this enumeration; check for the default prefix
+     * using the {@link #getURI getURI} with an argument of "".</p>
+     *
+     * @return An enumeration of prefixes (never empty).
+     * @see #getDeclaredPrefixes
+     * @see #getURI
+     */
+    public Enumeration getPrefixes ()
+    {
+    return currentContext.getPrefixes();
+    }
+
+
+    /**
+     * Return one of the prefixes mapped to a Namespace URI.
+     *
+     * <p>If more than one prefix is currently mapped to the same
+     * URI, this method will make an arbitrary selection; if you
+     * want all of the prefixes, use the {@link #getPrefixes}
+     * method instead.</p>
+     *
+     * <p><strong>Note:</strong> this will never return the empty (default) prefix;
+     * to check for a default prefix, use the {@link #getURI getURI}
+     * method with an argument of "".</p>
+     *
+     * @param uri the namespace URI
+     * @return one of the prefixes currently mapped to the URI supplied,
+     *         or null if none is mapped or if the URI is assigned to
+     *         the default namespace
+     * @see #getPrefixes(java.lang.String)
+     * @see #getURI
+     */
+    public String getPrefix (String uri)
+    {
+    return currentContext.getPrefix(uri);
+    }
+
+
+    /**
+     * Return an enumeration of all prefixes for a given URI whose
+     * declarations are active in the current context.
+     * This includes declarations from parent contexts that have
+     * not been overridden.
+     *
+     * <p>This method returns prefixes mapped to a specific Namespace
+     * URI.  The xml: prefix will be included.  If you want only one
+     * prefix that's mapped to the Namespace URI, and you don't care 
+     * which one you get, use the {@link #getPrefix getPrefix}
+     *  method instead.</p>
+     *
+     * <p><strong>Note:</strong> the empty (default) prefix is <em>never</em> included
+     * in this enumeration; to check for the presence of a default
+     * Namespace, use the {@link #getURI getURI} method with an
+     * argument of "".</p>
+     *
+     * @param uri The Namespace URI.
+     * @return An enumeration of prefixes (never empty).
+     * @see #getPrefix
+     * @see #getDeclaredPrefixes
+     * @see #getURI
+     */
+    public Enumeration getPrefixes (String uri)
+    {
+    Vector prefixes = new Vector();
+    Enumeration allPrefixes = getPrefixes();
+    while (allPrefixes.hasMoreElements()) {
+        String prefix = (String)allPrefixes.nextElement();
+        if (uri.equals(getURI(prefix))) {
+        prefixes.addElement(prefix);
+        }
+    }
+    return prefixes.elements();
+    }
+
+
+    /**
+     * Return an enumeration of all prefixes declared in this context.
+     *
+     * <p>The empty (default) prefix will be included in this 
+     * enumeration; note that this behaviour differs from that of
+     * {@link #getPrefix} and {@link #getPrefixes}.</p>
+     *
+     * @return An enumeration of all prefixes declared in this
+     *         context.
+     * @see #getPrefixes
+     * @see #getURI
+     */
+    public Enumeration getDeclaredPrefixes ()
+    {
+    return currentContext.getDeclaredPrefixes();
+    }
+
+    /**
+     * Controls whether namespace declaration attributes are placed
+     * into the {@link #NSDECL NSDECL} namespace
+     * by {@link #processName processName()}.  This may only be
+     * changed before any contexts have been pushed.
+     * 
+     * @param value the namespace declaration attribute state. A value of true
+     *              enables this feature, a value of false disables it.
+     *
+     * @since SAX 2.1alpha
+     *
+     * @exception IllegalStateException when attempting to set this
+     *    after any context has been pushed.
+     */
+    public void setNamespaceDeclUris (boolean value)
+    {
+    if (contextPos != 0)
+        throw new IllegalStateException ();
+    if (value == namespaceDeclUris)
+        return;
+    namespaceDeclUris = value;
+    if (value)
+        currentContext.declarePrefix ("xmlns", NSDECL);
+    else {
+        contexts[contextPos] = currentContext = new Context();
+        currentContext.declarePrefix("xml", XMLNS);
+    }
+    }
+
+    /**
+     * Returns true if namespace declaration attributes are placed into
+     * a namespace.  This behavior is not the default.
+     *
+     * @return true if namespace declaration attributes are enabled, false
+     *         otherwise.
+     * @since SAX 2.1alpha
+     */
+    public boolean isNamespaceDeclUris ()
+    { return namespaceDeclUris; }
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Internal state.
+    ////////////////////////////////////////////////////////////////////
+
+    private Context contexts[];
+    private Context currentContext;
+    private int contextPos;
+    private boolean namespaceDeclUris;
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Internal classes.
+    ////////////////////////////////////////////////////////////////////
+
+    /**
+     * Internal class for a single Namespace context.
+     *
+     * <p>This module caches and reuses Namespace contexts,
+     * so the number allocated
+     * will be equal to the element depth of the document, not to the total
+     * number of elements (i.e. 5-10 rather than tens of thousands).
+     * Also, data structures used to represent contexts are shared when
+     * possible (child contexts without declarations) to further reduce
+     * the amount of memory that's consumed.
+     * </p>
+     */
+    final class Context {
+
+    /**
+     * Create the root-level Namespace context.
+     */
+    Context ()
+    {
+        copyTables();
+    }
+    
+    
+    /**
+     * (Re)set the parent of this Namespace context.
+     * The context must either have been freshly constructed,
+     * or must have been cleared.
+     *
+     * @param context The parent Namespace context object.
+     */
+    void setParent (Context parent)
+    {
+        this.parent = parent;
+        declarations = null;
+        prefixTable = parent.prefixTable;
+        uriTable = parent.uriTable;
+        elementNameTable = parent.elementNameTable;
+        attributeNameTable = parent.attributeNameTable;
+        defaultNS = parent.defaultNS;
+        declSeen = false;
+        declsOK = true;
+    }
+
+    /**
+     * Makes associated state become collectible,
+     * invalidating this context.
+     * {@link #setParent} must be called before
+     * this context may be used again.
+     */
+    void clear ()
+    {
+        parent = null;
+        prefixTable = null;
+        uriTable = null;
+        elementNameTable = null;
+        attributeNameTable = null;
+        defaultNS = null;
+    }
+    
+    
+    /**
+     * Declare a Namespace prefix for this context.
+     *
+     * @param prefix The prefix to declare.
+     * @param uri The associated Namespace URI.
+     * @see org.xml.sax.helpers.NamespaceSupport#declarePrefix
+     */
+    void declarePrefix (String prefix, String uri)
+    {
+                // Lazy processing...
+        if (!declsOK)
+        throw new IllegalStateException (
+            "can't declare any more prefixes in this context");
+        if (!declSeen) {
+        copyTables();
+        }
+        if (declarations == null) {
+        declarations = new Vector();
+        }
+        
+        prefix = prefix.intern();
+        uri = uri.intern();
+        if ("".equals(prefix)) {
+        if ("".equals(uri)) {
+            defaultNS = null;
+        } else {
+            defaultNS = uri;
+        }
+        } else {
+        prefixTable.put(prefix, uri);
+        uriTable.put(uri, prefix); // may wipe out another prefix
+        }
+        declarations.addElement(prefix);
+    }
+
+
+    /**
+     * Process an XML qualified name in this context.
+     *
+     * @param qName The XML qualified name.
+     * @param isAttribute true if this is an attribute name.
+     * @return An array of three strings containing the
+     *         URI part (or empty string), the local part,
+     *         and the raw name, all internalized, or null
+     *         if there is an undeclared prefix.
+     * @see org.xml.sax.helpers.NamespaceSupport#processName
+     */
+    String [] processName (String qName, boolean isAttribute)
+    {
+        String name[];
+        Hashtable table;
+        
+                    // detect errors in call sequence
+        declsOK = false;
+
+                // Select the appropriate table.
+        if (isAttribute) {
+        table = attributeNameTable;
+        } else {
+        table = elementNameTable;
+        }
+        
+                // Start by looking in the cache, and
+                // return immediately if the name
+                // is already known in this content
+        name = (String[])table.get(qName);
+        if (name != null) {
+        return name;
+        }
+        
+                // We haven't seen this name in this
+                // context before.  Maybe in the parent
+                // context, but we can't assume prefix
+                // bindings are the same.
+        name = new String[3];
+        name[2] = qName.intern();
+        int index = qName.indexOf(':');
+        
+        
+                // No prefix.
+        if (index == -1) {
+        if (isAttribute) {
+            if (qName == "xmlns" && namespaceDeclUris)
+            name[0] = NSDECL;
+            else
+            name[0] = "";
+        } else if (defaultNS == null) {
+            name[0] = "";
+        } else {
+            name[0] = defaultNS;
+        }
+        name[1] = name[2];
+        }
+        
+                // Prefix
+        else {
+        String prefix = qName.substring(0, index);
+        String local = qName.substring(index+1);
+        String uri;
+        if ("".equals(prefix)) {
+            uri = defaultNS;
+        } else {
+            uri = (String)prefixTable.get(prefix);
+        }
+        if (uri == null
+            || (!isAttribute && "xmlns".equals (prefix))) {
+            return null;
+        }
+        name[0] = uri;
+        name[1] = local.intern();
+        }
+        
+                // Save in the cache for future use.
+                // (Could be shared with parent context...)
+        table.put(name[2], name);
+        return name;
+    }
+    
+
+    /**
+     * Look up the URI associated with a prefix in this context.
+     *
+     * @param prefix The prefix to look up.
+     * @return The associated Namespace URI, or null if none is
+     *         declared.    
+     * @see org.xml.sax.helpers.NamespaceSupport#getURI
+     */
+    String getURI (String prefix)
+    {
+        if ("".equals(prefix)) {
+        return defaultNS;
+        } else if (prefixTable == null) {
+        return null;
+        } else {
+        return (String)prefixTable.get(prefix);
+        }
+    }
+
+
+    /**
+     * Look up one of the prefixes associated with a URI in this context.
+     *
+     * <p>Since many prefixes may be mapped to the same URI,
+     * the return value may be unreliable.</p>
+     *
+     * @param uri The URI to look up.
+     * @return The associated prefix, or null if none is declared.
+     * @see org.xml.sax.helpers.NamespaceSupport#getPrefix
+     */
+    String getPrefix (String uri)
+    {
+        if (uriTable == null) {
+        return null;
+        } else {
+        return (String)uriTable.get(uri);
+        }
+    }
+    
+    
+    /**
+     * Return an enumeration of prefixes declared in this context.
+     *
+     * @return An enumeration of prefixes (possibly empty).
+     * @see org.xml.sax.helpers.NamespaceSupport#getDeclaredPrefixes
+     */
+    Enumeration getDeclaredPrefixes ()
+    {
+        if (declarations == null) {
+        return EMPTY_ENUMERATION;
+        } else {
+        return declarations.elements();
+        }
+    }
+    
+    
+    /**
+     * Return an enumeration of all prefixes currently in force.
+     *
+     * <p>The default prefix, if in force, is <em>not</em>
+     * returned, and will have to be checked for separately.</p>
+     *
+     * @return An enumeration of prefixes (never empty).
+     * @see org.xml.sax.helpers.NamespaceSupport#getPrefixes
+     */
+    Enumeration getPrefixes ()
+    {
+        if (prefixTable == null) {
+        return EMPTY_ENUMERATION;
+        } else {
+        return prefixTable.keys();
+        }
+    }
+    
+    
+
+    ////////////////////////////////////////////////////////////////
+    // Internal methods.
+    ////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Copy on write for the internal tables in this context.
+     *
+     * <p>This class is optimized for the normal case where most
+     * elements do not contain Namespace declarations.</p>
+     */    
+    private void copyTables ()
+    {
+        if (prefixTable != null) {
+        prefixTable = (Hashtable)prefixTable.clone();
+        } else {
+        prefixTable = new Hashtable();
+        }
+        if (uriTable != null) {
+        uriTable = (Hashtable)uriTable.clone();
+        } else {
+        uriTable = new Hashtable();
+        }
+        elementNameTable = new Hashtable();
+        attributeNameTable = new Hashtable();
+        declSeen = true;
+    }
+
+
+
+    ////////////////////////////////////////////////////////////////
+    // Protected state.
+    ////////////////////////////////////////////////////////////////
+    
+    Hashtable prefixTable;
+    Hashtable uriTable;
+    Hashtable elementNameTable;
+    Hashtable attributeNameTable;
+    String defaultNS = null;
+    boolean declsOK = true;
+    
+
+
+    ////////////////////////////////////////////////////////////////
+    // Internal state.
+    ////////////////////////////////////////////////////////////////
+    
+    private Vector declarations = null;
+    private boolean declSeen = false;
+    private Context parent = null;
+    }
+}
+
+// end of NamespaceSupport.java
diff --git a/xml/src/main/java/org/xml/sax/helpers/NewInstance.java b/xml/src/main/java/org/xml/sax/helpers/NewInstance.java
new file mode 100644
index 0000000..e590192
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/helpers/NewInstance.java
@@ -0,0 +1,79 @@
+// NewInstance.java - create a new instance of a class by name.
+// http://www.saxproject.org
+// Written by Edwin Goei, edwingo@apache.org
+// and by David Brownell, dbrownell@users.sourceforge.net
+// NO WARRANTY!  This class is in the Public Domain.
+// $Id: NewInstance.java,v 1.4 2002/01/30 20:52:27 dbrownell Exp $
+
+package org.xml.sax.helpers;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * Create a new instance of a class by name.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This class contains a static method for creating an instance of a
+ * class from an explicit class name.  It tries to use the thread's context
+ * ClassLoader if possible and falls back to using
+ * Class.forName(String).</p>
+ *
+ * <p>This code is designed to compile and run on JDK version 1.1 and later
+ * including versions of Java 2.</p>
+ *
+ * @author Edwin Goei, David Brownell
+ * @version 2.0.1 (sax2r2)
+ */
+class NewInstance {
+
+    /**
+     * Creates a new instance of the specified class name
+     *
+     * Package private so this code is not exposed at the API level.
+     */
+    static Object newInstance (ClassLoader classLoader, String className)
+        throws ClassNotFoundException, IllegalAccessException,
+            InstantiationException
+    {
+        Class driverClass;
+        if (classLoader == null) {
+            driverClass = Class.forName(className);
+        } else {
+            driverClass = classLoader.loadClass(className);
+        }
+        return driverClass.newInstance();
+    }
+
+    /**
+     * Figure out which ClassLoader to use.  For JDK 1.2 and later use
+     * the context ClassLoader.
+     */           
+    static ClassLoader getClassLoader ()
+    {
+        Method m = null;
+
+        try {
+            m = Thread.class.getMethod("getContextClassLoader");
+        } catch (NoSuchMethodException e) {
+            // Assume that we are running JDK 1.1, use the current ClassLoader
+            return NewInstance.class.getClassLoader();
+        }
+
+        try {
+            return (ClassLoader) m.invoke(Thread.currentThread());
+        } catch (IllegalAccessException e) {
+            // assert(false)
+            throw new UnknownError(e.getMessage());
+        } catch (InvocationTargetException e) {
+            // assert(e.getTargetException() instanceof SecurityException)
+            throw new UnknownError(e.getMessage());
+        }
+    }
+}
diff --git a/xml/src/main/java/org/xml/sax/helpers/ParserAdapter.java b/xml/src/main/java/org/xml/sax/helpers/ParserAdapter.java
new file mode 100644
index 0000000..7fc3813
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/helpers/ParserAdapter.java
@@ -0,0 +1,1046 @@
+// ParserAdapter.java - adapt a SAX1 Parser to a SAX2 XMLReader.
+// http://www.saxproject.org
+// Written by David Megginson
+// NO WARRANTY!  This class is in the public domain.
+// $Id: ParserAdapter.java,v 1.16 2004/04/26 17:34:35 dmegginson Exp $
+
+package org.xml.sax.helpers;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.xml.sax.Parser;    // deprecated
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.AttributeList; // deprecated
+import org.xml.sax.EntityResolver;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.DocumentHandler; // deprecated
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import org.xml.sax.XMLReader;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+
+
+/**
+ * Adapt a SAX1 Parser as a SAX2 XMLReader.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This class wraps a SAX1 {@link org.xml.sax.Parser Parser}
+ * and makes it act as a SAX2 {@link org.xml.sax.XMLReader XMLReader},
+ * with feature, property, and Namespace support.  Note
+ * that it is not possible to report {@link org.xml.sax.ContentHandler#skippedEntity
+ * skippedEntity} events, since SAX1 does not make that information available.</p>
+ *
+ * <p>This adapter does not test for duplicate Namespace-qualified
+ * attribute names.</p>
+ *
+ * @since SAX 2.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.helpers.XMLReaderAdapter
+ * @see org.xml.sax.XMLReader
+ * @see org.xml.sax.Parser
+ */
+public class ParserAdapter implements XMLReader, DocumentHandler
+{
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Constructors.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Construct a new parser adapter.
+     *
+     * <p>Use the "org.xml.sax.parser" property to locate the
+     * embedded SAX1 driver.</p>
+     *
+     * @exception SAXException If the embedded driver
+     *            cannot be instantiated or if the
+     *            org.xml.sax.parser property is not specified.
+     */
+    public ParserAdapter ()
+      throws SAXException
+    {
+    super();
+
+    String driver = System.getProperty("org.xml.sax.parser");
+
+    try {
+        setup(ParserFactory.makeParser());
+    } catch (ClassNotFoundException e1) {
+        throw new
+        SAXException("Cannot find SAX1 driver class " +
+                 driver, e1);
+    } catch (IllegalAccessException e2) {
+        throw new
+        SAXException("SAX1 driver class " +
+                 driver +
+                 " found but cannot be loaded", e2);
+    } catch (InstantiationException e3) {
+        throw new
+        SAXException("SAX1 driver class " +
+                 driver +
+                 " loaded but cannot be instantiated", e3);
+    } catch (ClassCastException e4) {
+        throw new
+        SAXException("SAX1 driver class " +
+                 driver +
+                 " does not implement org.xml.sax.Parser");
+    } catch (NullPointerException e5) {
+        throw new 
+        SAXException("System property org.xml.sax.parser not specified");
+    }
+    }
+
+
+    /**
+     * Construct a new parser adapter.
+     *
+     * <p>Note that the embedded parser cannot be changed once the
+     * adapter is created; to embed a different parser, allocate
+     * a new ParserAdapter.</p>
+     *
+     * @param parser The SAX1 parser to embed.
+     * @exception java.lang.NullPointerException If the parser parameter
+     *            is null.
+     */
+    public ParserAdapter (Parser parser)
+    {
+    super();
+    setup(parser);
+    }
+
+
+    /**
+     * Internal setup method.
+     *
+     * @param parser The embedded parser.
+     * @exception java.lang.NullPointerException If the parser parameter
+     *            is null.
+     */
+    private void setup (Parser parser)
+    {
+    if (parser == null) {
+        throw new
+        NullPointerException("Parser argument must not be null");
+    }
+    this.parser = parser;
+    atts = new AttributesImpl();
+    nsSupport = new NamespaceSupport();
+    attAdapter = new AttributeListAdapter();
+    }
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.XMLReader.
+    ////////////////////////////////////////////////////////////////////
+
+
+    //
+    // Internal constants for the sake of convenience.
+    //
+    private final static String FEATURES = "http://xml.org/sax/features/";
+    private final static String NAMESPACES = FEATURES + "namespaces";
+    private final static String NAMESPACE_PREFIXES = FEATURES + "namespace-prefixes";
+    private final static String XMLNS_URIs = FEATURES + "xmlns-uris";
+
+
+    /**
+     * Set a feature flag for the parser.
+     *
+     * <p>The only features recognized are namespaces and 
+     * namespace-prefixes.</p>
+     *
+     * @param name The feature name, as a complete URI.
+     * @param value The requested feature value.
+     * @exception SAXNotRecognizedException If the feature
+     *            can't be assigned or retrieved.
+     * @exception SAXNotSupportedException If the feature
+     *            can't be assigned that value.
+     * @see org.xml.sax.XMLReader#setFeature
+     */
+    public void setFeature (String name, boolean value)
+    throws SAXNotRecognizedException, SAXNotSupportedException
+    {
+    if (name.equals(NAMESPACES)) {
+        checkNotParsing("feature", name);
+        namespaces = value;
+        if (!namespaces && !prefixes) {
+        prefixes = true;
+        }
+    } else if (name.equals(NAMESPACE_PREFIXES)) {
+        checkNotParsing("feature", name);
+        prefixes = value;
+        if (!prefixes && !namespaces) {
+        namespaces = true;
+        }
+    } else if (name.equals(XMLNS_URIs)) {
+        checkNotParsing("feature", name);
+        uris = value;
+    } else {
+        throw new SAXNotRecognizedException("Feature: " + name);
+    }
+    }
+
+
+    /**
+     * Check a parser feature flag.
+     *
+     * <p>The only features recognized are namespaces and 
+     * namespace-prefixes.</p>
+     *
+     * @param name The feature name, as a complete URI.
+     * @return The current feature value.
+     * @exception SAXNotRecognizedException If the feature
+     *            value can't be assigned or retrieved.
+     * @exception SAXNotSupportedException If the
+     *            feature is not currently readable.
+     * @see org.xml.sax.XMLReader#setFeature
+     */
+    public boolean getFeature (String name)
+    throws SAXNotRecognizedException, SAXNotSupportedException
+    {
+    if (name.equals(NAMESPACES)) {
+        return namespaces;
+    } else if (name.equals(NAMESPACE_PREFIXES)) {
+        return prefixes;
+    } else if (name.equals(XMLNS_URIs)) {
+        return uris;
+    } else {
+        throw new SAXNotRecognizedException("Feature: " + name);
+    }
+    }
+
+
+    /**
+     * Set a parser property.
+     *
+     * <p>No properties are currently recognized.</p>
+     *
+     * @param name The property name.
+     * @param value The property value.
+     * @exception SAXNotRecognizedException If the property
+     *            value can't be assigned or retrieved.
+     * @exception SAXNotSupportedException If the property
+     *            can't be assigned that value.
+     * @see org.xml.sax.XMLReader#setProperty
+     */
+    public void setProperty (String name, Object value)
+    throws SAXNotRecognizedException, SAXNotSupportedException
+    {
+    throw new SAXNotRecognizedException("Property: " + name);
+    }
+
+
+    /**
+     * Get a parser property.
+     *
+     * <p>No properties are currently recognized.</p>
+     *
+     * @param name The property name.
+     * @return The property value.
+     * @exception SAXNotRecognizedException If the property
+     *            value can't be assigned or retrieved.
+     * @exception SAXNotSupportedException If the property
+     *            value is not currently readable.
+     * @see org.xml.sax.XMLReader#getProperty
+     */
+    public Object getProperty (String name)
+    throws SAXNotRecognizedException, SAXNotSupportedException
+    {
+    throw new SAXNotRecognizedException("Property: " + name);
+    }
+
+
+    /**
+     * Set the entity resolver.
+     *
+     * @param resolver The new entity resolver.
+     * @see org.xml.sax.XMLReader#setEntityResolver
+     */
+    public void setEntityResolver (EntityResolver resolver)
+    {
+    entityResolver = resolver;
+    }
+
+
+    /**
+     * Return the current entity resolver.
+     *
+     * @return The current entity resolver, or null if none was supplied.
+     * @see org.xml.sax.XMLReader#getEntityResolver
+     */
+    public EntityResolver getEntityResolver ()
+    {
+    return entityResolver;
+    }
+
+
+    /**
+     * Set the DTD handler.
+     *
+     * @param handler the new DTD handler
+     * @see org.xml.sax.XMLReader#setEntityResolver
+     */
+    public void setDTDHandler (DTDHandler handler)
+    {
+    dtdHandler = handler;
+    }
+
+
+    /**
+     * Return the current DTD handler.
+     *
+     * @return the current DTD handler, or null if none was supplied
+     * @see org.xml.sax.XMLReader#getEntityResolver
+     */
+    public DTDHandler getDTDHandler ()
+    {
+    return dtdHandler;
+    }
+
+
+    /**
+     * Set the content handler.
+     *
+     * @param handler the new content handler
+     * @see org.xml.sax.XMLReader#setEntityResolver
+     */
+    public void setContentHandler (ContentHandler handler)
+    {
+    contentHandler = handler;
+    }
+
+
+    /**
+     * Return the current content handler.
+     *
+     * @return The current content handler, or null if none was supplied.
+     * @see org.xml.sax.XMLReader#getEntityResolver
+     */
+    public ContentHandler getContentHandler ()
+    {
+    return contentHandler;
+    }
+
+
+    /**
+     * Set the error handler.
+     *
+     * @param handler The new error handler.
+     * @see org.xml.sax.XMLReader#setEntityResolver
+     */
+    public void setErrorHandler (ErrorHandler handler)
+    {
+    errorHandler = handler;
+    }
+
+
+    /**
+     * Return the current error handler.
+     *
+     * @return The current error handler, or null if none was supplied.
+     * @see org.xml.sax.XMLReader#getEntityResolver
+     */
+    public ErrorHandler getErrorHandler ()
+    {
+    return errorHandler;
+    }
+
+
+    /**
+     * Parse an XML document.
+     *
+     * @param systemId The absolute URL of the document.
+     * @exception java.io.IOException If there is a problem reading
+     *            the raw content of the document.
+     * @exception SAXException If there is a problem
+     *            processing the document.
+     * @see #parse(org.xml.sax.InputSource)
+     * @see org.xml.sax.Parser#parse(java.lang.String)
+     */
+    public void parse (String systemId)
+    throws IOException, SAXException
+    {
+    parse(new InputSource(systemId));
+    }
+
+
+    /**
+     * Parse an XML document.
+     *
+     * @param input An input source for the document.
+     * @exception java.io.IOException If there is a problem reading
+     *            the raw content of the document.
+     * @exception SAXException If there is a problem
+     *            processing the document.
+     * @see #parse(java.lang.String)
+     * @see org.xml.sax.Parser#parse(org.xml.sax.InputSource)
+     */
+    public void parse (InputSource input)
+    throws IOException, SAXException
+    {
+    if (parsing) {
+        throw new SAXException("Parser is already in use");
+    }
+    setupParser();
+    parsing = true;
+    try {
+        parser.parse(input);
+    } finally {
+        parsing = false;
+    }
+    parsing = false;
+    }
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.DocumentHandler.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Adapter implementation method; do not call.
+     * Adapt a SAX1 document locator event.
+     *
+     * @param locator A document locator.
+     * @see org.xml.sax.ContentHandler#setDocumentLocator
+     */
+    public void setDocumentLocator (Locator locator)
+    {
+    this.locator = locator;
+    if (contentHandler != null) {
+        contentHandler.setDocumentLocator(locator);
+    }
+    }
+
+
+    /**
+     * Adapter implementation method; do not call.
+     * Adapt a SAX1 start document event.
+     *
+     * @exception SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.DocumentHandler#startDocument
+     */
+    public void startDocument ()
+    throws SAXException
+    {
+    if (contentHandler != null) {
+        contentHandler.startDocument();
+    }
+    }
+
+
+    /**
+     * Adapter implementation method; do not call.
+     * Adapt a SAX1 end document event.
+     *
+     * @exception SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.DocumentHandler#endDocument
+     */
+    public void endDocument ()
+    throws SAXException
+    {
+    if (contentHandler != null) {
+        contentHandler.endDocument();
+    }
+    }
+
+
+    /**
+     * Adapter implementation method; do not call.
+     * Adapt a SAX1 startElement event.
+     *
+     * <p>If necessary, perform Namespace processing.</p>
+     *
+     * @param qName The qualified (prefixed) name.
+     * @param qAtts The XML attribute list (with qnames).
+     * @exception SAXException The client may raise a
+     *            processing exception.
+     */
+    public void startElement (String qName, AttributeList qAtts)
+    throws SAXException
+    {
+                // These are exceptions from the
+                // first pass; they should be
+                // ignored if there's a second pass,
+                // but reported otherwise.
+    Vector exceptions = null;
+
+                // If we're not doing Namespace
+                // processing, dispatch this quickly.
+    if (!namespaces) {
+        if (contentHandler != null) {
+        attAdapter.setAttributeList(qAtts);
+        contentHandler.startElement("", "", qName.intern(),
+                        attAdapter);
+        }
+        return;
+    }
+
+
+                // OK, we're doing Namespace processing.
+    nsSupport.pushContext();
+    int length = qAtts.getLength();
+    
+                // First pass:  handle NS decls
+    for (int i = 0; i < length; i++) {
+        String attQName = qAtts.getName(i);
+
+        if (!attQName.startsWith("xmlns"))
+        continue;
+                // Could be a declaration...
+        String prefix;
+        int n = attQName.indexOf(':');
+
+                    // xmlns=...
+        if (n == -1 && attQName.length () == 5) {
+        prefix = "";
+        } else if (n != 5) {
+        // XML namespaces spec doesn't discuss "xmlnsf:oo"
+        // (and similarly named) attributes ... at most, warn
+        continue;
+        } else         // xmlns:foo=...
+        prefix = attQName.substring(n+1);
+
+        String value = qAtts.getValue(i);
+        if (!nsSupport.declarePrefix(prefix, value)) {
+        reportError("Illegal Namespace prefix: " + prefix);
+        continue;
+        }
+        if (contentHandler != null)
+        contentHandler.startPrefixMapping(prefix, value);
+    }
+    
+                // Second pass: copy all relevant
+                // attributes into the SAX2 AttributeList
+                // using updated prefix bindings
+    atts.clear();
+    for (int i = 0; i < length; i++) {
+        String attQName = qAtts.getName(i);
+        String type = qAtts.getType(i);
+        String value = qAtts.getValue(i);
+
+                // Declaration?
+        if (attQName.startsWith("xmlns")) {
+        String prefix;
+        int n = attQName.indexOf(':');
+
+        if (n == -1 && attQName.length () == 5) {
+            prefix = "";
+        } else if (n != 5) {
+            // XML namespaces spec doesn't discuss "xmlnsf:oo"
+            // (and similarly named) attributes ... ignore
+            prefix = null;
+        } else {
+            prefix = attQName.substring(6);
+        }
+                // Yes, decl:  report or prune
+        if (prefix != null) {
+            if (prefixes) {
+            if (uris)
+                // note funky case:  localname can be null
+                // when declaring the default prefix, and
+                // yet the uri isn't null.
+                atts.addAttribute (nsSupport.XMLNS, prefix,
+                    attQName.intern(), type, value);
+            else
+                atts.addAttribute ("", "",
+                    attQName.intern(), type, value);
+            }
+            continue;
+        }
+        } 
+
+                // Not a declaration -- report
+        try {
+        String attName[] = processName(attQName, true, true);
+        atts.addAttribute(attName[0], attName[1], attName[2],
+                  type, value);
+        } catch (SAXException e) {
+        if (exceptions == null)
+            exceptions = new Vector();
+        exceptions.addElement(e);
+        atts.addAttribute("", attQName, attQName, type, value);
+        }
+    }
+    
+    // now handle the deferred exception reports
+    if (exceptions != null && errorHandler != null) {
+        for (int i = 0; i < exceptions.size(); i++)
+        errorHandler.error((SAXParseException)
+                (exceptions.elementAt(i)));
+    }
+
+                // OK, finally report the event.
+    if (contentHandler != null) {
+        String name[] = processName(qName, false, false);
+        contentHandler.startElement(name[0], name[1], name[2], atts);
+    }
+    }
+
+
+    /**
+     * Adapter implementation method; do not call.
+     * Adapt a SAX1 end element event.
+     *
+     * @param qName The qualified (prefixed) name.
+     * @exception SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.DocumentHandler#endElement
+     */
+    public void endElement (String qName)
+    throws SAXException
+    {
+                // If we're not doing Namespace
+                // processing, dispatch this quickly.
+    if (!namespaces) {
+        if (contentHandler != null) {
+        contentHandler.endElement("", "", qName.intern());
+        }
+        return;
+    }
+
+                // Split the name.
+    String names[] = processName(qName, false, false);
+    if (contentHandler != null) {
+        contentHandler.endElement(names[0], names[1], names[2]);
+        Enumeration prefixes = nsSupport.getDeclaredPrefixes();
+        while (prefixes.hasMoreElements()) {
+        String prefix = (String)prefixes.nextElement();
+        contentHandler.endPrefixMapping(prefix);
+        }
+    }
+    nsSupport.popContext();
+    }
+
+
+    /**
+     * Adapter implementation method; do not call.
+     * Adapt a SAX1 characters event.
+     *
+     * @param ch An array of characters.
+     * @param start The starting position in the array.
+     * @param length The number of characters to use.
+     * @exception SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.DocumentHandler#characters
+     */
+    public void characters (char ch[], int start, int length)
+    throws SAXException
+    {
+    if (contentHandler != null) {
+        contentHandler.characters(ch, start, length);
+    }
+    }
+
+
+    /**
+     * Adapter implementation method; do not call.
+     * Adapt a SAX1 ignorable whitespace event.
+     *
+     * @param ch An array of characters.
+     * @param start The starting position in the array.
+     * @param length The number of characters to use.
+     * @exception SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.DocumentHandler#ignorableWhitespace
+     */
+    public void ignorableWhitespace (char ch[], int start, int length)
+    throws SAXException
+    {
+    if (contentHandler != null) {
+        contentHandler.ignorableWhitespace(ch, start, length);
+    }
+    }
+
+
+    /**
+     * Adapter implementation method; do not call.
+     * Adapt a SAX1 processing instruction event.
+     *
+     * @param target The processing instruction target.
+     * @param data The remainder of the processing instruction
+     * @exception SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.DocumentHandler#processingInstruction
+     */
+    public void processingInstruction (String target, String data)
+    throws SAXException
+    {
+    if (contentHandler != null) {
+        contentHandler.processingInstruction(target, data);
+    }
+    }
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Internal utility methods.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Initialize the parser before each run.
+     */
+    private void setupParser ()
+    {
+    // catch an illegal "nonsense" state.
+    if (!prefixes && !namespaces)
+        throw new IllegalStateException ();
+
+    nsSupport.reset();
+    if (uris)
+        nsSupport.setNamespaceDeclUris (true);
+
+    if (entityResolver != null) {
+        parser.setEntityResolver(entityResolver);
+    }
+    if (dtdHandler != null) {
+        parser.setDTDHandler(dtdHandler);
+    }
+    if (errorHandler != null) {
+        parser.setErrorHandler(errorHandler);
+    }
+    parser.setDocumentHandler(this);
+    locator = null;
+    }
+
+
+    /**
+     * Process a qualified (prefixed) name.
+     *
+     * <p>If the name has an undeclared prefix, use only the qname
+     * and make an ErrorHandler.error callback in case the app is
+     * interested.</p>
+     *
+     * @param qName The qualified (prefixed) name.
+     * @param isAttribute true if this is an attribute name.
+     * @return The name split into three parts.
+     * @exception SAXException The client may throw
+     *            an exception if there is an error callback.
+     */
+    private String [] processName (String qName, boolean isAttribute,
+                   boolean useException)
+    throws SAXException
+    {
+    String parts[] = nsSupport.processName(qName, nameParts,
+                           isAttribute);
+    if (parts == null) {
+        if (useException)
+        throw makeException("Undeclared prefix: " + qName);
+        reportError("Undeclared prefix: " + qName);
+        parts = new String[3];
+        parts[0] = parts[1] = "";
+        parts[2] = qName.intern();
+    }
+    return parts;
+    }
+
+
+    /**
+     * Report a non-fatal error.
+     *
+     * @param message The error message.
+     * @exception SAXException The client may throw
+     *            an exception.
+     */
+    void reportError (String message)
+    throws SAXException
+    {
+    if (errorHandler != null)
+        errorHandler.error(makeException(message));
+    }
+
+    
+    /**
+     * Construct an exception for the current context.
+     *
+     * @param message The error message.
+     */
+    private SAXParseException makeException (String message)
+    {
+    if (locator != null) {
+        return new SAXParseException(message, locator);
+    } else {
+        return new SAXParseException(message, null, null, -1, -1);
+    }
+    }
+
+
+    /**
+     * Throw an exception if we are parsing.
+     *
+     * <p>Use this method to detect illegal feature or
+     * property changes.</p>
+     *
+     * @param type The type of thing (feature or property).
+     * @param name The feature or property name.
+     * @exception SAXNotSupportedException If a
+     *            document is currently being parsed.
+     */
+    private void checkNotParsing (String type, String name)
+    throws SAXNotSupportedException
+    {
+    if (parsing) {
+        throw new SAXNotSupportedException("Cannot change " +
+                           type + ' ' +
+                           name + " while parsing");
+                           
+    }
+    }
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Internal state.
+    ////////////////////////////////////////////////////////////////////
+
+    private NamespaceSupport nsSupport;
+    private AttributeListAdapter attAdapter;
+
+    private boolean parsing = false;
+    private String nameParts[] = new String[3];
+
+    private Parser parser = null;
+
+    private AttributesImpl atts = null;
+
+                // Features
+    private boolean namespaces = true;
+    private boolean prefixes = false;
+    private boolean uris = false;
+
+                // Properties
+
+                // Handlers
+    Locator locator;
+
+    EntityResolver entityResolver = null;
+    DTDHandler dtdHandler = null;
+    ContentHandler contentHandler = null;
+    ErrorHandler errorHandler = null;
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Inner class to wrap an AttributeList when not doing NS proc.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Adapt a SAX1 AttributeList as a SAX2 Attributes object.
+     *
+     * <p>This class is in the Public Domain, and comes with NO
+     * WARRANTY of any kind.</p>
+     *
+     * <p>This wrapper class is used only when Namespace support
+     * is disabled -- it provides pretty much a direct mapping
+     * from SAX1 to SAX2, except that names and types are 
+     * interned whenever requested.</p>
+     */
+    final class AttributeListAdapter implements Attributes
+    {
+
+    /**
+     * Construct a new adapter.
+     */
+    AttributeListAdapter ()
+    {
+    }
+
+
+    /**
+     * Set the embedded AttributeList.
+     *
+     * <p>This method must be invoked before any of the others
+     * can be used.</p>
+     *
+     * @param The SAX1 attribute list (with qnames).
+     */
+    void setAttributeList (AttributeList qAtts)
+    {
+        this.qAtts = qAtts;
+    }
+
+
+    /**
+     * Return the length of the attribute list.
+     *
+     * @return The number of attributes in the list.
+     * @see org.xml.sax.Attributes#getLength
+     */
+    public int getLength ()
+    {
+        return qAtts.getLength();
+    }
+
+
+    /**
+     * Return the Namespace URI of the specified attribute.
+     *
+     * @param The attribute's index.
+     * @return Always the empty string.
+     * @see org.xml.sax.Attributes#getURI
+     */
+    public String getURI (int i)
+    {
+        return "";
+    }
+
+
+    /**
+     * Return the local name of the specified attribute.
+     *
+     * @param The attribute's index.
+     * @return Always the empty string.
+     * @see org.xml.sax.Attributes#getLocalName
+     */
+    public String getLocalName (int i)
+    {
+        return "";
+    }
+
+
+    /**
+     * Return the qualified (prefixed) name of the specified attribute.
+     *
+     * @param The attribute's index.
+     * @return The attribute's qualified name, internalized.
+     */
+    public String getQName (int i)
+    {
+        return qAtts.getName(i).intern();
+    }
+
+
+    /**
+     * Return the type of the specified attribute.
+     *
+     * @param The attribute's index.
+     * @return The attribute's type as an internalized string.
+     */
+    public String getType (int i)
+    {
+        return qAtts.getType(i).intern();
+    }
+
+
+    /**
+     * Return the value of the specified attribute.
+     *
+     * @param The attribute's index.
+     * @return The attribute's value.
+     */
+    public String getValue (int i)
+    {
+        return qAtts.getValue(i);
+    }
+
+
+    /**
+     * Look up an attribute index by Namespace name.
+     *
+     * @param uri The Namespace URI or the empty string.
+     * @param localName The local name.
+     * @return The attributes index, or -1 if none was found.
+     * @see org.xml.sax.Attributes#getIndex(java.lang.String,java.lang.String)
+     */
+    public int getIndex (String uri, String localName)
+    {
+        return -1;
+    }
+
+
+    /**
+     * Look up an attribute index by qualified (prefixed) name.
+     *
+     * @param qName The qualified name.
+     * @return The attributes index, or -1 if none was found.
+     * @see org.xml.sax.Attributes#getIndex(java.lang.String)
+     */
+    public int getIndex (String qName)
+    {
+        int max = atts.getLength();
+        for (int i = 0; i < max; i++) {
+        if (qAtts.getName(i).equals(qName)) {
+            return i;
+        }
+        }
+        return -1;
+    }
+
+
+    /**
+     * Look up the type of an attribute by Namespace name.
+     *
+     * @param uri The Namespace URI
+     * @param localName The local name.
+     * @return The attribute's type as an internalized string.
+     */
+    public String getType (String uri, String localName)
+    {
+        return null;
+    }
+
+
+    /**
+     * Look up the type of an attribute by qualified (prefixed) name.
+     *
+     * @param qName The qualified name.
+     * @return The attribute's type as an internalized string.
+     */
+    public String getType (String qName)
+    {
+        return qAtts.getType(qName).intern();
+    }
+
+
+    /**
+     * Look up the value of an attribute by Namespace name.
+     *
+     * @param uri The Namespace URI
+     * @param localName The local name.
+     * @return The attribute's value.
+     */
+    public String getValue (String uri, String localName)
+    {
+        return null;
+    }
+
+
+    /**
+     * Look up the value of an attribute by qualified (prefixed) name.
+     *
+     * @param qName The qualified name.
+     * @return The attribute's value.
+     */
+    public String getValue (String qName)
+    {
+        return qAtts.getValue(qName);
+    }
+
+    private AttributeList qAtts;
+    }
+}
+
+// end of ParserAdapter.java
diff --git a/xml/src/main/java/org/xml/sax/helpers/ParserFactory.java b/xml/src/main/java/org/xml/sax/helpers/ParserFactory.java
new file mode 100644
index 0000000..ffe2a60
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/helpers/ParserFactory.java
@@ -0,0 +1,133 @@
+// SAX parser factory.
+// http://www.saxproject.org
+// No warranty; no copyright -- use this as you will.
+// $Id: ParserFactory.java,v 1.7 2002/01/30 20:52:36 dbrownell Exp $
+
+package org.xml.sax.helpers;
+
+import java.lang.ClassNotFoundException;
+import java.lang.IllegalAccessException;
+import java.lang.InstantiationException;
+import java.lang.SecurityException;
+import java.lang.ClassCastException;
+
+import org.xml.sax.Parser;
+
+
+/**
+ * Java-specific class for dynamically loading SAX parsers.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p><strong>Note:</strong> This class is designed to work with the now-deprecated
+ * SAX1 {@link org.xml.sax.Parser Parser} class.  SAX2 applications should use
+ * {@link org.xml.sax.helpers.XMLReaderFactory XMLReaderFactory} instead.</p>
+ *
+ * <p>ParserFactory is not part of the platform-independent definition
+ * of SAX; it is an additional convenience class designed
+ * specifically for Java XML application writers.  SAX applications
+ * can use the static methods in this class to allocate a SAX parser
+ * dynamically at run-time based either on the value of the
+ * `org.xml.sax.parser' system property or on a string containing the class
+ * name.</p>
+ *
+ * <p>Note that the application still requires an XML parser that
+ * implements SAX1.</p>
+ *
+ * @deprecated This class works with the deprecated
+ *             {@link org.xml.sax.Parser Parser}
+ *             interface.
+ * @since SAX 1.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ */
+public class ParserFactory {
+    
+    
+    /**
+     * Private null constructor.
+     */
+    private ParserFactory ()
+    {
+    }
+    
+    
+    /**
+     * Create a new SAX parser using the `org.xml.sax.parser' system property.
+     *
+     * <p>The named class must exist and must implement the
+     * {@link org.xml.sax.Parser Parser} interface.</p>
+     * 
+     * @return the newly created parser.
+     *
+     * @exception java.lang.NullPointerException There is no value
+     *            for the `org.xml.sax.parser' system property.
+     * @exception java.lang.ClassNotFoundException The SAX parser
+     *            class was not found (check your CLASSPATH).
+     * @exception IllegalAccessException The SAX parser class was
+     *            found, but you do not have permission to load
+     *            it.
+     * @exception InstantiationException The SAX parser class was
+     *            found but could not be instantiated.
+     * @exception java.lang.ClassCastException The SAX parser class
+     *            was found and instantiated, but does not implement
+     *            org.xml.sax.Parser.
+     * @see #makeParser(java.lang.String)
+     * @see org.xml.sax.Parser
+     */
+    public static Parser makeParser ()
+    throws ClassNotFoundException,
+    IllegalAccessException, 
+    InstantiationException,
+    NullPointerException,
+    ClassCastException
+    {
+    String className = System.getProperty("org.xml.sax.parser");
+    if (className == null) {
+        throw new NullPointerException("No value for sax.parser property");
+    } else {
+        return makeParser(className);
+    }
+    }
+    
+    
+    /**
+     * Create a new SAX parser object using the class name provided.
+     *
+     * <p>The named class must exist and must implement the
+     * {@link org.xml.sax.Parser Parser} interface.</p>
+     *
+     * @return the newly created parser.
+     *
+     * @param className A string containing the name of the
+     *                  SAX parser class.
+     * @exception java.lang.ClassNotFoundException The SAX parser
+     *            class was not found (check your CLASSPATH).
+     * @exception IllegalAccessException The SAX parser class was
+     *            found, but you do not have permission to load
+     *            it.
+     * @exception InstantiationException The SAX parser class was
+     *            found but could not be instantiated.
+     * @exception java.lang.ClassCastException The SAX parser class
+     *            was found and instantiated, but does not implement
+     *            org.xml.sax.Parser.
+     * @see #makeParser()
+     * @see org.xml.sax.Parser
+     */
+    public static Parser makeParser (String className)
+    throws ClassNotFoundException,
+    IllegalAccessException, 
+    InstantiationException,
+    ClassCastException
+    {
+    return (Parser) NewInstance.newInstance (
+        NewInstance.getClassLoader (), className);
+    }
+    
+}
+
diff --git a/xml/src/main/java/org/xml/sax/helpers/XMLFilterImpl.java b/xml/src/main/java/org/xml/sax/helpers/XMLFilterImpl.java
new file mode 100644
index 0000000..68e2579
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/helpers/XMLFilterImpl.java
@@ -0,0 +1,715 @@
+// XMLFilterImpl.java - base SAX2 filter implementation.
+// http://www.saxproject.org
+// Written by David Megginson
+// NO WARRANTY!  This class is in the Public Domain.
+// $Id: XMLFilterImpl.java,v 1.9 2004/04/26 17:34:35 dmegginson Exp $
+
+package org.xml.sax.helpers;
+
+import java.io.IOException;
+
+import org.xml.sax.XMLReader;
+import org.xml.sax.XMLFilter;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.Attributes;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.SAXNotRecognizedException;
+
+
+/**
+ * Base class for deriving an XML filter.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This class is designed to sit between an {@link org.xml.sax.XMLReader
+ * XMLReader} and the client application's event handlers.  By default, it
+ * does nothing but pass requests up to the reader and events
+ * on to the handlers unmodified, but subclasses can override
+ * specific methods to modify the event stream or the configuration
+ * requests as they pass through.</p>
+ *
+ * @since SAX 2.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.XMLFilter
+ * @see org.xml.sax.XMLReader
+ * @see org.xml.sax.EntityResolver
+ * @see org.xml.sax.DTDHandler
+ * @see org.xml.sax.ContentHandler
+ * @see org.xml.sax.ErrorHandler
+ */
+public class XMLFilterImpl
+    implements XMLFilter, EntityResolver, DTDHandler, ContentHandler, ErrorHandler
+{
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Constructors.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Construct an empty XML filter, with no parent.
+     *
+     * <p>This filter will have no parent: you must assign a parent
+     * before you start a parse or do any configuration with
+     * setFeature or setProperty, unless you use this as a pure event
+     * consumer rather than as an {@link XMLReader}.</p>
+     *
+     * @see org.xml.sax.XMLReader#setFeature
+     * @see org.xml.sax.XMLReader#setProperty
+     * @see #setParent
+     */
+    public XMLFilterImpl ()
+    {
+    super();
+    }
+
+
+    /**
+     * Construct an XML filter with the specified parent.
+     * 
+     * @param parent the XML reader from which this filter receives its events. 
+     *
+     * @see #setParent
+     * @see #getParent
+     */
+    public XMLFilterImpl (XMLReader parent)
+    {
+        super();
+    setParent(parent);
+    }
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.XMLFilter.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Set the parent reader.
+     *
+     * <p>This is the {@link org.xml.sax.XMLReader XMLReader} from which 
+     * this filter will obtain its events and to which it will pass its 
+     * configuration requests.  The parent may itself be another filter.</p>
+     *
+     * <p>If there is no parent reader set, any attempt to parse
+     * or to set or get a feature or property will fail.</p>
+     *
+     * @param parent The parent XML reader.
+     * @see #getParent
+     */
+    public void setParent (XMLReader parent)
+    {
+    this.parent = parent;
+    }
+
+
+    /**
+     * Get the parent reader.
+     *
+     * @return The parent XML reader, or null if none is set.
+     * @see #setParent
+     */
+    public XMLReader getParent ()
+    {
+    return parent;
+    }
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.XMLReader.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Set the value of a feature.
+     *
+     * <p>This will always fail if the parent is null.</p>
+     *
+     * @param name The feature name.
+     * @param value The requested feature value.
+     * @exception org.xml.sax.SAXNotRecognizedException If the feature
+     *            value can't be assigned or retrieved from the parent.
+     * @exception org.xml.sax.SAXNotSupportedException When the
+     *            parent recognizes the feature name but 
+     *            cannot set the requested value.
+     */
+    public void setFeature (String name, boolean value)
+    throws SAXNotRecognizedException, SAXNotSupportedException
+    {
+    if (parent != null) {
+        parent.setFeature(name, value);
+    } else {
+        throw new SAXNotRecognizedException("Feature: " + name);
+    }
+    }
+
+
+    /**
+     * Look up the value of a feature.
+     *
+     * <p>This will always fail if the parent is null.</p>
+     *
+     * @param name The feature name.
+     * @return The current value of the feature.
+     * @exception org.xml.sax.SAXNotRecognizedException If the feature
+     *            value can't be assigned or retrieved from the parent.
+     * @exception org.xml.sax.SAXNotSupportedException When the
+     *            parent recognizes the feature name but 
+     *            cannot determine its value at this time.
+     */
+    public boolean getFeature (String name)
+    throws SAXNotRecognizedException, SAXNotSupportedException
+    {
+    if (parent != null) {
+        return parent.getFeature(name);
+    } else {
+        throw new SAXNotRecognizedException("Feature: " + name);
+    }
+    }
+
+
+    /**
+     * Set the value of a property.
+     *
+     * <p>This will always fail if the parent is null.</p>
+     *
+     * @param name The property name.
+     * @param value The requested property value.
+     * @exception org.xml.sax.SAXNotRecognizedException If the property
+     *            value can't be assigned or retrieved from the parent.
+     * @exception org.xml.sax.SAXNotSupportedException When the
+     *            parent recognizes the property name but 
+     *            cannot set the requested value.
+     */
+    public void setProperty (String name, Object value)
+    throws SAXNotRecognizedException, SAXNotSupportedException
+    {
+    if (parent != null) {
+        parent.setProperty(name, value);
+    } else {
+        throw new SAXNotRecognizedException("Property: " + name);
+    }
+    }
+
+
+    /**
+     * Look up the value of a property.
+     *
+     * @param name The property name.
+     * @return The current value of the property.
+     * @exception org.xml.sax.SAXNotRecognizedException If the property
+     *            value can't be assigned or retrieved from the parent.
+     * @exception org.xml.sax.SAXNotSupportedException When the
+     *            parent recognizes the property name but 
+     *            cannot determine its value at this time.
+     */
+    public Object getProperty (String name)
+    throws SAXNotRecognizedException, SAXNotSupportedException
+    {
+    if (parent != null) {
+        return parent.getProperty(name);
+    } else {
+        throw new SAXNotRecognizedException("Property: " + name);
+    }
+    }
+
+
+    /**
+     * Set the entity resolver.
+     *
+     * @param resolver The new entity resolver.
+     */
+    public void setEntityResolver (EntityResolver resolver)
+    {
+    entityResolver = resolver;
+    }
+
+
+    /**
+     * Get the current entity resolver.
+     *
+     * @return The current entity resolver, or null if none was set.
+     */
+    public EntityResolver getEntityResolver ()
+    {
+    return entityResolver;
+    }
+
+
+    /**
+     * Set the DTD event handler.
+     *
+     * @param handler the new DTD handler
+     */
+    public void setDTDHandler (DTDHandler handler)
+    {
+    dtdHandler = handler;
+    }
+
+
+    /**
+     * Get the current DTD event handler.
+     *
+     * @return The current DTD handler, or null if none was set.
+     */
+    public DTDHandler getDTDHandler ()
+    {
+    return dtdHandler;
+    }
+
+
+    /**
+     * Set the content event handler.
+     *
+     * @param handler the new content handler
+     */
+    public void setContentHandler (ContentHandler handler)
+    {
+    contentHandler = handler;
+    }
+
+
+    /**
+     * Get the content event handler.
+     *
+     * @return The current content handler, or null if none was set.
+     */
+    public ContentHandler getContentHandler ()
+    {
+    return contentHandler;
+    }
+
+
+    /**
+     * Set the error event handler.
+     *
+     * @param handler the new error handler
+     */
+    public void setErrorHandler (ErrorHandler handler)
+    {
+    errorHandler = handler;
+    }
+
+
+    /**
+     * Get the current error event handler.
+     *
+     * @return The current error handler, or null if none was set.
+     */
+    public ErrorHandler getErrorHandler ()
+    {
+    return errorHandler;
+    }
+
+
+    /**
+     * Parse a document.
+     *
+     * @param input The input source for the document entity.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @exception java.io.IOException An IO exception from the parser,
+     *            possibly from a byte stream or character stream
+     *            supplied by the application.
+     */
+    public void parse (InputSource input)
+    throws SAXException, IOException
+    {
+    setupParse();
+    parent.parse(input);
+    }
+
+
+    /**
+     * Parse a document.
+     *
+     * @param systemId The system identifier as a fully-qualified URI.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @exception java.io.IOException An IO exception from the parser,
+     *            possibly from a byte stream or character stream
+     *            supplied by the application.
+     */
+    public void parse (String systemId)
+    throws SAXException, IOException
+    {
+    parse(new InputSource(systemId));
+    }
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.EntityResolver.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Filter an external entity resolution.
+     *
+     * @param publicId The entity's public identifier, or null.
+     * @param systemId The entity's system identifier.
+     * @return A new InputSource or null for the default.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     * @exception java.io.IOException The client may throw an
+     *            I/O-related exception while obtaining the
+     *            new InputSource.
+     */
+    public InputSource resolveEntity (String publicId, String systemId)
+    throws SAXException, IOException
+    {
+    if (entityResolver != null) {
+        return entityResolver.resolveEntity(publicId, systemId);
+    } else {
+        return null;
+    }
+    }
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.DTDHandler.
+    ////////////////////////////////////////////////////////////////////
+
+    
+    /**
+     * Filter a notation declaration event.
+     *
+     * @param name The notation name.
+     * @param publicId The notation's public identifier, or null.
+     * @param systemId The notation's system identifier, or null.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    public void notationDecl (String name, String publicId, String systemId)
+    throws SAXException
+    {
+    if (dtdHandler != null) {
+        dtdHandler.notationDecl(name, publicId, systemId);
+    }
+    }
+
+    
+    /**
+     * Filter an unparsed entity declaration event.
+     *
+     * @param name The entity name.
+     * @param publicId The entity's public identifier, or null.
+     * @param systemId The entity's system identifier, or null.
+     * @param notationName The name of the associated notation.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    public void unparsedEntityDecl (String name, String publicId,
+                    String systemId, String notationName)
+    throws SAXException
+    {
+    if (dtdHandler != null) {
+        dtdHandler.unparsedEntityDecl(name, publicId, systemId,
+                      notationName);
+    }
+    }
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.ContentHandler.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Filter a new document locator event.
+     *
+     * @param locator The document locator.
+     */
+    public void setDocumentLocator (Locator locator)
+    {
+    this.locator = locator;
+    if (contentHandler != null) {
+        contentHandler.setDocumentLocator(locator);
+    }
+    }
+
+
+    /**
+     * Filter a start document event.
+     *
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    public void startDocument ()
+    throws SAXException
+    {
+    if (contentHandler != null) {
+        contentHandler.startDocument();
+    }
+    }
+
+
+    /**
+     * Filter an end document event.
+     *
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    public void endDocument ()
+    throws SAXException
+    {
+    if (contentHandler != null) {
+        contentHandler.endDocument();
+    }
+    }
+
+
+    /**
+     * Filter a start Namespace prefix mapping event.
+     *
+     * @param prefix The Namespace prefix.
+     * @param uri The Namespace URI.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    public void startPrefixMapping (String prefix, String uri)
+    throws SAXException
+    {
+    if (contentHandler != null) {
+        contentHandler.startPrefixMapping(prefix, uri);
+    }
+    }
+
+
+    /**
+     * Filter an end Namespace prefix mapping event.
+     *
+     * @param prefix The Namespace prefix.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    public void endPrefixMapping (String prefix)
+    throws SAXException
+    {
+    if (contentHandler != null) {
+        contentHandler.endPrefixMapping(prefix);
+    }
+    }
+
+
+    /**
+     * Filter a start element event.
+     *
+     * @param uri The element's Namespace URI, or the empty string.
+     * @param localName The element's local name, or the empty string.
+     * @param qName The element's qualified (prefixed) name, or the empty
+     *        string.
+     * @param atts The element's attributes.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    public void startElement (String uri, String localName, String qName,
+                  Attributes atts)
+    throws SAXException
+    {
+    if (contentHandler != null) {
+        contentHandler.startElement(uri, localName, qName, atts);
+    }
+    }
+
+
+    /**
+     * Filter an end element event.
+     *
+     * @param uri The element's Namespace URI, or the empty string.
+     * @param localName The element's local name, or the empty string.
+     * @param qName The element's qualified (prefixed) name, or the empty
+     *        string.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    public void endElement (String uri, String localName, String qName)
+    throws SAXException
+    {
+    if (contentHandler != null) {
+        contentHandler.endElement(uri, localName, qName);
+    }
+    }
+
+
+    /**
+     * Filter a character data event.
+     *
+     * @param ch An array of characters.
+     * @param start The starting position in the array.
+     * @param length The number of characters to use from the array.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    public void characters (char ch[], int start, int length)
+    throws SAXException
+    {
+    if (contentHandler != null) {
+        contentHandler.characters(ch, start, length);
+    }
+    }
+
+
+    /**
+     * Filter an ignorable whitespace event.
+     *
+     * @param ch An array of characters.
+     * @param start The starting position in the array.
+     * @param length The number of characters to use from the array.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    public void ignorableWhitespace (char ch[], int start, int length)
+    throws SAXException
+    {
+    if (contentHandler != null) {
+        contentHandler.ignorableWhitespace(ch, start, length);
+    }
+    }
+
+
+    /**
+     * Filter a processing instruction event.
+     *
+     * @param target The processing instruction target.
+     * @param data The text following the target.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    public void processingInstruction (String target, String data)
+    throws SAXException
+    {
+    if (contentHandler != null) {
+        contentHandler.processingInstruction(target, data);
+    }
+    }
+
+
+    /**
+     * Filter a skipped entity event.
+     *
+     * @param name The name of the skipped entity.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    public void skippedEntity (String name)
+    throws SAXException
+    {
+    if (contentHandler != null) {
+        contentHandler.skippedEntity(name);
+    }
+    }
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.ErrorHandler.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Filter a warning event.
+     *
+     * @param e The warning as an exception.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    public void warning (SAXParseException e)
+    throws SAXException
+    {
+    if (errorHandler != null) {
+        errorHandler.warning(e);
+    }
+    }
+
+
+    /**
+     * Filter an error event.
+     *
+     * @param e The error as an exception.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    public void error (SAXParseException e)
+    throws SAXException
+    {
+    if (errorHandler != null) {
+        errorHandler.error(e);
+    }
+    }
+
+
+    /**
+     * Filter a fatal error event.
+     *
+     * @param e The error as an exception.
+     * @exception org.xml.sax.SAXException The client may throw
+     *            an exception during processing.
+     */
+    public void fatalError (SAXParseException e)
+    throws SAXException
+    {
+    if (errorHandler != null) {
+        errorHandler.fatalError(e);
+    }
+    }
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Internal methods.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Set up before a parse.
+     *
+     * <p>Before every parse, check whether the parent is
+     * non-null, and re-register the filter for all of the 
+     * events.</p>
+     */
+    private void setupParse ()
+    {
+    if (parent == null) {
+        throw new NullPointerException("No parent for filter");
+    }
+    parent.setEntityResolver(this);
+    parent.setDTDHandler(this);
+    parent.setContentHandler(this);
+    parent.setErrorHandler(this);
+    }
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Internal state.
+    ////////////////////////////////////////////////////////////////////
+
+    private XMLReader parent = null;
+    private Locator locator = null;
+    private EntityResolver entityResolver = null;
+    private DTDHandler dtdHandler = null;
+    private ContentHandler contentHandler = null;
+    private ErrorHandler errorHandler = null;
+
+}
+
+// end of XMLFilterImpl.java
diff --git a/xml/src/main/java/org/xml/sax/helpers/XMLReaderAdapter.java b/xml/src/main/java/org/xml/sax/helpers/XMLReaderAdapter.java
new file mode 100644
index 0000000..cc8f431
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/helpers/XMLReaderAdapter.java
@@ -0,0 +1,538 @@
+// XMLReaderAdapter.java - adapt an SAX2 XMLReader to a SAX1 Parser
+// http://www.saxproject.org
+// Written by David Megginson
+// NO WARRANTY!  This class is in the public domain.
+// $Id: XMLReaderAdapter.java,v 1.9 2004/04/26 17:34:35 dmegginson Exp $
+
+package org.xml.sax.helpers;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import org.xml.sax.Parser;    // deprecated
+import org.xml.sax.Locator;
+import org.xml.sax.InputSource;
+import org.xml.sax.AttributeList; // deprecated
+import org.xml.sax.EntityResolver;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.DocumentHandler; // deprecated
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+
+import org.xml.sax.XMLReader;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXNotSupportedException;
+
+
+/**
+ * Adapt a SAX2 XMLReader as a SAX1 Parser.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This class wraps a SAX2 {@link org.xml.sax.XMLReader XMLReader}
+ * and makes it act as a SAX1 {@link org.xml.sax.Parser Parser}.  The XMLReader 
+ * must support a true value for the 
+ * http://xml.org/sax/features/namespace-prefixes property or parsing will fail
+ * with a {@link org.xml.sax.SAXException SAXException}; if the XMLReader 
+ * supports a false value for the http://xml.org/sax/features/namespaces 
+ * property, that will also be used to improve efficiency.</p>
+ *
+ * @since SAX 2.0
+ * @author David Megginson
+ * @version 2.0.1 (sax2r2)
+ * @see org.xml.sax.Parser
+ * @see org.xml.sax.XMLReader
+ */
+public class XMLReaderAdapter implements Parser, ContentHandler
+{
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Constructor.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Create a new adapter.
+     *
+     * <p>Use the "org.xml.sax.driver" property to locate the SAX2
+     * driver to embed.</p>
+     *
+     * @exception org.xml.sax.SAXException If the embedded driver
+     *            cannot be instantiated or if the
+     *            org.xml.sax.driver property is not specified.
+     */
+    public XMLReaderAdapter ()
+      throws SAXException
+    {
+    setup(XMLReaderFactory.createXMLReader());
+    }
+
+
+    /**
+     * Create a new adapter.
+     *
+     * <p>Create a new adapter, wrapped around a SAX2 XMLReader.
+     * The adapter will make the XMLReader act like a SAX1
+     * Parser.</p>
+     *
+     * @param xmlReader The SAX2 XMLReader to wrap.
+     * @exception java.lang.NullPointerException If the argument is null.
+     */
+    public XMLReaderAdapter (XMLReader xmlReader)
+    {
+    setup(xmlReader);
+    }
+
+
+
+    /**
+     * Internal setup.
+     *
+     * @param xmlReader The embedded XMLReader.
+     */
+    private void setup (XMLReader xmlReader)
+    {
+    if (xmlReader == null) {
+        throw new NullPointerException("XMLReader must not be null");
+    }
+    this.xmlReader = xmlReader;
+    qAtts = new AttributesAdapter();
+    }
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.Parser.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Set the locale for error reporting.
+     *
+     * <p>This is not supported in SAX2, and will always throw
+     * an exception.</p>
+     *
+     * @param locale the locale for error reporting.
+     * @see org.xml.sax.Parser#setLocale
+     * @exception org.xml.sax.SAXException Thrown unless overridden.
+     */
+    public void setLocale (Locale locale)
+    throws SAXException
+    {
+    throw new SAXNotSupportedException("setLocale not supported");
+    }
+
+
+    /**
+     * Register the entity resolver.
+     *
+     * @param resolver The new resolver.
+     * @see org.xml.sax.Parser#setEntityResolver
+     */
+    public void setEntityResolver (EntityResolver resolver)
+    {
+    xmlReader.setEntityResolver(resolver);
+    }
+
+
+    /**
+     * Register the DTD event handler.
+     *
+     * @param handler The new DTD event handler.
+     * @see org.xml.sax.Parser#setDTDHandler
+     */
+    public void setDTDHandler (DTDHandler handler)
+    {
+    xmlReader.setDTDHandler(handler);
+    }
+
+
+    /**
+     * Register the SAX1 document event handler.
+     *
+     * <p>Note that the SAX1 document handler has no Namespace
+     * support.</p>
+     *
+     * @param handler The new SAX1 document event handler.
+     * @see org.xml.sax.Parser#setDocumentHandler
+     */
+    public void setDocumentHandler (DocumentHandler handler)
+    {
+    documentHandler = handler;
+    }
+
+
+    /**
+     * Register the error event handler.
+     *
+     * @param handler The new error event handler.
+     * @see org.xml.sax.Parser#setErrorHandler
+     */
+    public void setErrorHandler (ErrorHandler handler)
+    {
+    xmlReader.setErrorHandler(handler);
+    }
+
+
+    /**
+     * Parse the document.
+     *
+     * <p>This method will throw an exception if the embedded
+     * XMLReader does not support the 
+     * http://xml.org/sax/features/namespace-prefixes property.</p>
+     *
+     * @param systemId The absolute URL of the document.
+     * @exception java.io.IOException If there is a problem reading
+     *            the raw content of the document.
+     * @exception org.xml.sax.SAXException If there is a problem
+     *            processing the document.
+     * @see #parse(org.xml.sax.InputSource)
+     * @see org.xml.sax.Parser#parse(java.lang.String)
+     */
+    public void parse (String systemId)
+    throws IOException, SAXException
+    {
+    parse(new InputSource(systemId));
+    }
+
+
+    /**
+     * Parse the document.
+     *
+     * <p>This method will throw an exception if the embedded
+     * XMLReader does not support the 
+     * http://xml.org/sax/features/namespace-prefixes property.</p>
+     *
+     * @param input An input source for the document.
+     * @exception java.io.IOException If there is a problem reading
+     *            the raw content of the document.
+     * @exception org.xml.sax.SAXException If there is a problem
+     *            processing the document.
+     * @see #parse(java.lang.String)
+     * @see org.xml.sax.Parser#parse(org.xml.sax.InputSource)
+     */
+    public void parse (InputSource input)
+    throws IOException, SAXException
+    {
+    setupXMLReader();
+    xmlReader.parse(input);
+    }
+
+
+    /**
+     * Set up the XML reader.
+     */
+    private void setupXMLReader ()
+    throws SAXException
+    {
+    xmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
+    try {
+        xmlReader.setFeature("http://xml.org/sax/features/namespaces",
+                             false);
+    } catch (SAXException e) {
+        // NO OP: it's just extra information, and we can ignore it
+    }
+    xmlReader.setContentHandler(this);
+    }
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Implementation of org.xml.sax.ContentHandler.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Set a document locator.
+     *
+     * @param locator The document locator.
+     * @see org.xml.sax.ContentHandler#setDocumentLocator
+     */
+    public void setDocumentLocator (Locator locator)
+    {
+    if (documentHandler != null)
+        documentHandler.setDocumentLocator(locator);
+    }
+
+
+    /**
+     * Start document event.
+     *
+     * @exception org.xml.sax.SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.ContentHandler#startDocument
+     */
+    public void startDocument ()
+    throws SAXException
+    {
+    if (documentHandler != null)
+        documentHandler.startDocument();
+    }
+
+
+    /**
+     * End document event.
+     *
+     * @exception org.xml.sax.SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.ContentHandler#endDocument
+     */
+    public void endDocument ()
+    throws SAXException
+    {
+    if (documentHandler != null)
+        documentHandler.endDocument();
+    }
+
+
+    /**
+     * Adapt a SAX2 start prefix mapping event.
+     *
+     * @param prefix The prefix being mapped.
+     * @param uri The Namespace URI being mapped to.
+     * @see org.xml.sax.ContentHandler#startPrefixMapping
+     */
+    public void startPrefixMapping (String prefix, String uri)
+    {
+    }
+
+
+    /**
+     * Adapt a SAX2 end prefix mapping event.
+     *
+     * @param prefix The prefix being mapped.
+     * @see org.xml.sax.ContentHandler#endPrefixMapping
+     */
+    public void endPrefixMapping (String prefix)
+    {
+    }
+
+
+    /**
+     * Adapt a SAX2 start element event.
+     *
+     * @param uri The Namespace URI.
+     * @param localName The Namespace local name.
+     * @param qName The qualified (prefixed) name.
+     * @param atts The SAX2 attributes.
+     * @exception org.xml.sax.SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.ContentHandler#endDocument
+     */
+    public void startElement (String uri, String localName,
+                  String qName, Attributes atts)
+    throws SAXException
+    {
+    if (documentHandler != null) {
+        qAtts.setAttributes(atts);
+        documentHandler.startElement(qName, qAtts);
+    }
+    }
+
+
+    /**
+     * Adapt a SAX2 end element event.
+     *
+     * @param uri The Namespace URI.
+     * @param localName The Namespace local name.
+     * @param qName The qualified (prefixed) name.
+     * @exception org.xml.sax.SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.ContentHandler#endElement
+     */
+    public void endElement (String uri, String localName,
+                String qName)
+    throws SAXException
+    {
+    if (documentHandler != null)
+        documentHandler.endElement(qName);
+    }
+
+
+    /**
+     * Adapt a SAX2 characters event.
+     *
+     * @param ch An array of characters.
+     * @param start The starting position in the array.
+     * @param length The number of characters to use.
+     * @exception org.xml.sax.SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.ContentHandler#characters
+     */
+    public void characters (char ch[], int start, int length)
+    throws SAXException
+    {
+    if (documentHandler != null)
+        documentHandler.characters(ch, start, length);
+    }
+
+
+    /**
+     * Adapt a SAX2 ignorable whitespace event.
+     *
+     * @param ch An array of characters.
+     * @param start The starting position in the array.
+     * @param length The number of characters to use.
+     * @exception org.xml.sax.SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.ContentHandler#ignorableWhitespace
+     */
+    public void ignorableWhitespace (char ch[], int start, int length)
+    throws SAXException
+    {
+    if (documentHandler != null)
+        documentHandler.ignorableWhitespace(ch, start, length);
+    }
+
+
+    /**
+     * Adapt a SAX2 processing instruction event.
+     *
+     * @param target The processing instruction target.
+     * @param data The remainder of the processing instruction
+     * @exception org.xml.sax.SAXException The client may raise a
+     *            processing exception.
+     * @see org.xml.sax.ContentHandler#processingInstruction
+     */
+    public void processingInstruction (String target, String data)
+    throws SAXException
+    {
+    if (documentHandler != null)
+        documentHandler.processingInstruction(target, data);
+    }
+
+
+    /**
+     * Adapt a SAX2 skipped entity event.
+     *
+     * @param name The name of the skipped entity.
+     * @see org.xml.sax.ContentHandler#skippedEntity
+     * @exception org.xml.sax.SAXException Throwable by subclasses.
+     */
+    public void skippedEntity (String name)
+    throws SAXException
+    {
+    }
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Internal state.
+    ////////////////////////////////////////////////////////////////////
+
+    XMLReader xmlReader;
+    DocumentHandler documentHandler;
+    AttributesAdapter qAtts;
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Internal class.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Internal class to wrap a SAX2 Attributes object for SAX1.
+     */
+    final class AttributesAdapter implements AttributeList
+    {
+    AttributesAdapter ()
+    {
+    }
+
+
+    /**
+     * Set the embedded Attributes object.
+     *
+     * @param The embedded SAX2 Attributes.
+     */ 
+    void setAttributes (Attributes attributes)
+    {
+        this.attributes = attributes;
+    }
+
+
+    /**
+     * Return the number of attributes.
+     *
+     * @return The length of the attribute list.
+     * @see org.xml.sax.AttributeList#getLength
+     */
+    public int getLength ()
+    {
+        return attributes.getLength();
+    }
+
+
+    /**
+     * Return the qualified (prefixed) name of an attribute by position.
+     *
+     * @return The qualified name.
+     * @see org.xml.sax.AttributeList#getName
+     */
+    public String getName (int i)
+    {
+        return attributes.getQName(i);
+    }
+
+
+    /**
+     * Return the type of an attribute by position.
+     *
+     * @return The type.
+     * @see org.xml.sax.AttributeList#getType(int)
+     */
+    public String getType (int i)
+    {
+        return attributes.getType(i);
+    }
+
+
+    /**
+     * Return the value of an attribute by position.
+     *
+     * @return The value.
+     * @see org.xml.sax.AttributeList#getValue(int)
+     */
+    public String getValue (int i)
+    {
+        return attributes.getValue(i);
+    }
+
+
+    /**
+     * Return the type of an attribute by qualified (prefixed) name.
+     *
+     * @return The type.
+     * @see org.xml.sax.AttributeList#getType(java.lang.String)
+     */
+    public String getType (String qName)
+    {
+        return attributes.getType(qName);
+    }
+
+
+    /**
+     * Return the value of an attribute by qualified (prefixed) name.
+     *
+     * @return The value.
+     * @see org.xml.sax.AttributeList#getValue(java.lang.String)
+     */
+    public String getValue (String qName)
+    {
+        return attributes.getValue(qName);
+    }
+
+    private Attributes attributes;
+    }
+
+}
+
+// end of XMLReaderAdapter.java
diff --git a/xml/src/main/java/org/xml/sax/helpers/XMLReaderFactory.java b/xml/src/main/java/org/xml/sax/helpers/XMLReaderFactory.java
new file mode 100644
index 0000000..96151a1
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/helpers/XMLReaderFactory.java
@@ -0,0 +1,206 @@
+// XMLReaderFactory.java - factory for creating a new reader.
+// http://www.saxproject.org
+// Written by David Megginson
+// and by David Brownell
+// NO WARRANTY!  This class is in the Public Domain.
+// $Id: XMLReaderFactory.java,v 1.10 2002/04/22 01:00:13 dbrownell Exp $
+
+package org.xml.sax.helpers;
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import org.xml.sax.XMLReader;
+import org.xml.sax.SAXException;
+
+
+/**
+ * Factory for creating an XML reader.
+ *
+ * <blockquote>
+ * <em>This module, both source code and documentation, is in the
+ * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
+ * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+ * for further information.
+ * </blockquote>
+ *
+ * <p>This class contains static methods for creating an XML reader
+ * from an explicit class name, or based on runtime defaults:</p>
+ *
+ * <pre>
+ * try {
+ *   XMLReader myReader = XMLReaderFactory.createXMLReader();
+ * } catch (SAXException e) {
+ *   System.err.println(e.getMessage());
+ * }
+ * </pre>
+ *
+ * <p><strong>Note to Distributions bundled with parsers:</strong>
+ * You should modify the implementation of the no-arguments
+ * <em>createXMLReader</em> to handle cases where the external
+ * configuration mechanisms aren't set up.  That method should do its
+ * best to return a parser when one is in the class path, even when
+ * nothing bound its class name to <code>org.xml.sax.driver</code> so
+ * those configuration mechanisms would see it.</p>
+ *
+ * @since SAX 2.0
+ * @author David Megginson, David Brownell
+ * @version 2.0.1 (sax2r2)
+ */
+final public class XMLReaderFactory
+{
+    /**
+     * Private constructor.
+     *
+     * <p>This constructor prevents the class from being instantiated.</p>
+     */
+    private XMLReaderFactory ()
+    {
+    }
+
+    private static final String property = "org.xml.sax.driver";
+
+    /**
+     * Attempt to create an XMLReader from system defaults.
+     * In environments which can support it, the name of the XMLReader
+     * class is determined by trying each these options in order, and
+     * using the first one which succeeds:</p> <ul>
+     *
+     * <li>If the system property <code>org.xml.sax.driver</code>
+     * has a value, that is used as an XMLReader class name. </li>
+     *
+     * <li>The JAR "Services API" is used to look for a class name
+     * in the <em>META-INF/services/org.xml.sax.driver</em> file in
+     * jarfiles available to the runtime.</li>
+     *
+     * <li> SAX parser distributions are strongly encouraged to provide
+     * a default XMLReader class name that will take effect only when
+     * previous options (on this list) are not successful.</li>
+     *
+     * <li>Finally, if {@link ParserFactory#makeParser()} can
+     * return a system default SAX1 parser, that parser is wrapped in
+     * a {@link ParserAdapter}.  (This is a migration aid for SAX1
+     * environments, where the <code>org.xml.sax.parser</code> system
+     * property will often be usable.) </li>
+     *
+     * </ul>
+     *
+     * <p> In environments such as small embedded systems, which can not
+     * support that flexibility, other mechanisms to determine the default
+     * may be used. </p>
+     *
+     * <p>Note that many Java environments allow system properties to be
+     * initialized on a command line.  This means that <em>in most cases</em>
+     * setting a good value for that property ensures that calls to this
+     * method will succeed, except when security policies intervene.
+     * This will also maximize application portability to older SAX
+     * environments, with less robust implementations of this method.
+     * </p>
+     *
+     * @return A new XMLReader.
+     * @exception org.xml.sax.SAXException If no default XMLReader class
+     *            can be identified and instantiated.
+     * @see #createXMLReader(java.lang.String)
+     */
+    public static XMLReader createXMLReader ()
+    throws SAXException
+    {
+    String        className = null;
+    ClassLoader    loader = NewInstance.getClassLoader ();
+    
+    // 1. try the JVM-instance-wide system property
+    try { className = System.getProperty (property); }
+    catch (RuntimeException e) { /* normally fails for applets */ }
+
+    // 2. if that fails, try META-INF/services/
+    if (className == null) {
+        try {
+        String        service = "META-INF/services/" + property;
+        InputStream    in;
+        BufferedReader    reader;
+
+        if (loader == null)
+            in = ClassLoader.getSystemResourceAsStream (service);
+        else
+            in = loader.getResourceAsStream (service);
+
+        if (in != null) {
+            // BEGIN android-modified
+            reader = new BufferedReader (
+                new InputStreamReader (in, "UTF8"), 8192);
+            // END android-modified
+            className = reader.readLine ();
+            in.close ();
+        }
+        } catch (Exception e) {
+        }
+    }
+
+    // 3. Distro-specific fallback
+    if (className == null) {
+// BEGIN DISTRIBUTION-SPECIFIC
+
+        // EXAMPLE:
+        // className = "com.example.sax.XmlReader";
+        // or a $JAVA_HOME/jre/lib/*properties setting...
+
+// END DISTRIBUTION-SPECIFIC
+    }
+    
+    // do we know the XMLReader implementation class yet?
+    if (className != null)
+        return loadClass (loader, className);
+
+    // 4. panic -- adapt any SAX1 parser
+    try {
+        return new ParserAdapter (ParserFactory.makeParser ());
+    } catch (Exception e) {
+        throw new SAXException ("Can't create default XMLReader; "
+            + "is system property org.xml.sax.driver set?");
+    }
+    }
+
+
+    /**
+     * Attempt to create an XML reader from a class name.
+     *
+     * <p>Given a class name, this method attempts to load
+     * and instantiate the class as an XML reader.</p>
+     * 
+     * @param className the name of the class that should be instantiated.
+     *
+     * <p>Note that this method will not be usable in environments where
+     * the caller (perhaps an applet) is not permitted to load classes
+     * dynamically.</p>
+     *
+     * @return A new XML reader.
+     * @exception org.xml.sax.SAXException If the class cannot be
+     *            loaded, instantiated, and cast to XMLReader.
+     * @see #createXMLReader()
+     */
+    public static XMLReader createXMLReader (String className)
+    throws SAXException
+    {
+    return loadClass (NewInstance.getClassLoader (), className);
+    }
+
+    private static XMLReader loadClass (ClassLoader loader, String className)
+    throws SAXException
+    {
+    try {
+        return (XMLReader) NewInstance.newInstance (loader, className);
+    } catch (ClassNotFoundException e1) {
+        throw new SAXException("SAX2 driver class " + className +
+                   " not found", e1);
+    } catch (IllegalAccessException e2) {
+        throw new SAXException("SAX2 driver class " + className +
+                   " found but cannot be loaded", e2);
+    } catch (InstantiationException e3) {
+        throw new SAXException("SAX2 driver class " + className +
+       " loaded but cannot be instantiated (no empty public constructor?)",
+                   e3);
+    } catch (ClassCastException e4) {
+        throw new SAXException("SAX2 driver class " + className +
+                   " does not implement XMLReader", e4);
+    }
+    }
+}
diff --git a/xml/src/main/java/org/xml/sax/helpers/package.html b/xml/src/main/java/org/xml/sax/helpers/package.html
new file mode 100644
index 0000000..3a265fd
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/helpers/package.html
@@ -0,0 +1,13 @@
+<HTML><HEAD>
+<!-- $Id: package.html,v 1.6 2002/01/30 20:52:39 dbrownell Exp $ -->
+</HEAD><BODY>
+
+<p>This package contains "helper" classes, including
+support for bootstrapping SAX-based applications.
+
+<p>See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+for more information about SAX.</p>
+
+@since Android 1.0
+
+</BODY></HTML>
diff --git a/xml/src/main/java/org/xml/sax/package.html b/xml/src/main/java/org/xml/sax/package.html
new file mode 100644
index 0000000..fbe7108
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/package.html
@@ -0,0 +1,299 @@
+<html><head>
+<!-- $Id: package.html,v 1.18 2004/04/21 13:06:01 dmegginson Exp $ -->
+</head><body>
+
+<p> This package provides the core SAX APIs.
+Some SAX1 APIs are deprecated to encourage integration of
+namespace-awareness into designs of new applications
+and into maintenance of existing infrastructure. </p>
+
+<p>See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
+for more information about SAX.</p>
+
+
+<h2> SAX2 Standard Feature Flags </h2>
+
+<p> One of the essential characteristics of SAX2 is that it added
+feature flags which can be used to examine and perhaps modify
+parser modes, in particular modes such as validation.
+Since features are identified by (absolute) URIs, anyone
+can define such features.   
+Currently defined standard feature URIs have the prefix
+<code>http://xml.org/sax/features/</code> before an identifier such as
+<code>validation</code>.  Turn features on or off using
+<em>setFeature</em>.  Those standard identifiers are: </p>
+
+
+<table border="1" cellpadding="3" cellspacing="0" width="100%">
+    <tr align="center" bgcolor="#ccccff">
+	<th>Feature ID</th>
+	<th>Access</th>
+	<th>Default</th>
+	<th>Description</th>
+	</tr>
+
+    <tr>
+	<td>external-general-entities</td>
+	<td><em>read/write</em></td>
+	<td><em>unspecified</em></td>
+	<td> Reports whether this parser processes external
+	    general entities; always true if validating.
+		</td>
+	</tr>
+
+    <tr>
+	<td>external-parameter-entities</td>
+	<td><em>read/write</em></td>
+	<td><em>unspecified</em></td>
+	<td> Reports whether this parser processes external
+	    parameter entities; always true if validating.
+		</td>
+	</tr>
+
+    <tr>
+	<td>is-standalone</td>
+	<td>(parsing) <em>read-only</em>, (not parsing) <em>none</em></td>
+	<td>not applicable</td>
+	<td> May be examined only during a parse, after the
+	    <em>startDocument()</em> callback has been completed; read-only.
+	    The value is true if the document specified standalone="yes" in 
+	    its XML declaration, and otherwise is false.
+		</td>
+	</tr>
+
+    <tr>
+	<td>lexical-handler/parameter-entities</td>
+	<td><em>read/write</em></td>
+	<td><em>unspecified</em></td>
+	<td> A value of "true" indicates that the LexicalHandler will report
+	    the beginning and end of parameter entities.
+		</td>
+	</tr>
+
+    <tr>
+	<td>namespaces</td>
+	<td><em>read/write</em></td>
+	<td>true</td>
+	<td> A value of "true" indicates namespace URIs and unprefixed local names
+	    for element and attribute names will be available.
+		</td>
+	</tr>
+
+    <tr>
+	<td>namespace-prefixes</td>
+	<td><em>read/write</em></td>
+	<td>false</td>
+	<td> A value of "true" indicates that XML qualified names (with prefixes) and
+	    attributes (including <em>xmlns*</em> attributes) will be available.
+		</td>
+	</tr>
+
+    <tr>
+	<td>resolve-dtd-uris</td>
+	<td><em>read/write</em></td>
+	<td><em>true</em></td>
+	<td> A value of "true" indicates that system IDs in declarations will
+	    be absolutized (relative to their base URIs) before reporting.
+	    (That is the default behavior for all SAX2 XML parsers.)
+	    A value of "false" indicates those IDs will not be absolutized;
+	    parsers will provide the base URI from
+	    <em>Locator.getSystemId()</em>.
+	    This applies to system IDs passed in <ul>
+		<li><em>DTDHandler.notationDecl()</em>,
+		<li><em>DTDHandler.unparsedEntityDecl()</em>, and
+		<li><em>DeclHandler.externalEntityDecl()</em>.
+	    </ul>
+	    It does not apply to <em>EntityResolver.resolveEntity()</em>,
+	    which is not used to report declarations, or to
+	    <em>LexicalHandler.startDTD()</em>, which already provides
+	    the non-absolutized URI.
+	    </td>
+	</tr>
+
+    <tr>
+	<td>string-interning</td>
+	<td><em>read/write</em></td>
+	<td><em>unspecified</em></td>
+	<td> Has a value of "true" if all XML names (for elements, prefixes,
+	    attributes, entities, notations, and local names),
+	    as well as Namespace URIs, will have been interned
+	    using <em>java.lang.String.intern</em>. This supports fast
+	    testing of equality/inequality against string constants,
+	    rather than forcing slower calls to <em>String.equals()</em>.
+	    </td>
+	</tr>
+
+    <tr>
+    <td>unicode-normalization-checking</td>
+    <td><em>read/write</em></td>
+    <td><em>false</em></td>
+    <td> Controls whether the parser reports Unicode normalization 
+        errors as described in section 2.13 and Appendix B of the 
+        XML 1.1 Recommendation. If true, Unicode normalization
+        errors are reported using the ErrorHandler.error() callback.
+        Such errors are not fatal in themselves (though, obviously,
+        other Unicode-related encoding errors may be).
+		</td>
+    </tr>
+    
+    <tr>
+	<td>use-attributes2</td>
+	<td><em>read-only</em></td>
+	<td>not applicable</td>
+	<td> Returns "true" if the <em>Attributes</em> objects passed by
+	    this parser in <em>ContentHandler.startElement()</em>
+	    implement the <a href="ext/Attributes2.html"
+	    ><em>org.xml.sax.ext.Attributes2</em></a> interface.
+	    That interface exposes additional DTD-related information,
+	    such as whether the attribute was specified in the
+	    source text rather than defaulted.
+		</td>
+	</tr>
+
+    <tr>
+	<td>use-locator2</td>
+	<td><em>read-only</em></td>
+	<td>not applicable</td>
+	<td> Returns "true" if the <em>Locator</em> objects passed by
+	    this parser in <em>ContentHandler.setDocumentLocator()</em>
+	    implement the <a href="ext/Locator2.html"
+	    ><em>org.xml.sax.ext.Locator2</em></a> interface.
+	    That interface exposes additional entity information,
+	    such as the character encoding and XML version used.
+		</td>
+	</tr>
+
+    <tr>
+	<td>use-entity-resolver2</td>
+	<td><em>read/write</em></td>
+	<td><em>true</em></td>
+	<td> Returns "true" if, when <em>setEntityResolver</em> is given
+	    an object implementing the <a href="ext/EntityResolver2.html"
+	    ><em>org.xml.sax.ext.EntityResolver2</em></a> interface,
+	    those new methods will be used.
+	    Returns "false" to indicate that those methods will not be used.
+		</td>
+	</tr>
+
+    <tr>
+	<td>validation</td>
+	<td><em>read/write</em></td>
+	<td><em>unspecified</em></td>
+	<td> Controls whether the parser is reporting all validity
+	    errors; if true, all external entities will be read.
+		</td>
+	</tr>
+
+    <tr>
+	<td>xmlns-uris</td>
+	<td><em>read/write</em></td>
+	<td><em>false</em></td>
+	<td> Controls whether, when the <em>namespace-prefixes</em> feature
+	    is set, the parser treats namespace declaration attributes as
+	    being in the <em>http://www.w3.org/2000/xmlns/</em> namespace.
+	    By default, SAX2 conforms to the original "Namespaces in XML"
+	    Recommendation, which explicitly states that such attributes are
+	    not in any namespace.
+	    Setting this optional flag to "true" makes the SAX2 events conform to
+	    a later backwards-incompatible revision of that recommendation,
+	    placing those attributes in a namespace.
+		</td>
+	</tr>
+
+    <tr>
+    <td>xml-1.1</td>
+    <td><em>read-only</em></td>
+    <td>not applicable</td>
+    <td> Returns "true" if the parser supports both XML 1.1 and XML 1.0.
+        Returns "false" if the parser supports only XML 1.0.
+		</td>
+    </tr>
+
+</table>
+
+<p> Support for the default values of the
+<em>namespaces</em> and <em>namespace-prefixes</em>
+properties is required.
+Support for any other feature flags is entirely optional.
+</p>
+
+<p> For default values not specified by SAX2,
+each XMLReader implementation specifies its default,
+or may choose not to expose the feature flag.
+Unless otherwise specified here,
+implementations may support changing current values
+of these standard feature flags, but not while parsing.
+</p>
+
+<h2> SAX2 Standard Handler and Property IDs </h2>
+
+<p> For parser interface characteristics that are described
+as objects, a separate namespace is defined.  The
+objects in this namespace are again identified by URI, and
+the standard property URIs have the prefix
+<code>http://xml.org/sax/properties/</code> before an identifier such as
+<code>lexical-handler</code> or
+<code>dom-node</code>.  Manage those properties using
+<em>setProperty()</em>.  Those identifiers are: </p>
+
+<table border="1" cellpadding="3" cellspacing="0" width="100%">
+    <tr align="center" bgcolor="#ccccff">
+	<th>Property ID</th>
+	<th>Description</th>
+	</tr>
+
+    <tr>
+	<td>declaration-handler</td>
+	<td> Used to see most DTD declarations except those treated
+	    as lexical ("document element name is ...") or which are
+	    mandatory for all SAX parsers (<em>DTDHandler</em>).
+	    The Object must implement <a href="ext/DeclHandler.html"
+	    ><em>org.xml.sax.ext.DeclHandler</em></a>.
+	    </td>
+	</tr>
+
+    <tr>
+        <td>document-xml-version</td>
+        <td> May be examined only during a parse, after the startDocument()
+            callback has been completed; read-only. This property is a 
+            literal string describing the actual XML version of the document, 
+            such as "1.0" or "1.1".
+            </td>
+        </tr>
+    
+    <tr>
+	<td>dom-node</td>
+	<td> For "DOM Walker" style parsers, which ignore their
+	    <em>parser.parse()</em> parameters, this is used to
+	    specify the DOM (sub)tree being walked by the parser.
+	    The Object must implement the
+	    <em>org.w3c.dom.Node</em> interface.
+	    </td>
+	</tr>
+
+    <tr>
+	<td>lexical-handler</td>
+	<td> Used to see some syntax events that are essential in some
+	    applications:  comments, CDATA delimiters, selected general
+	    entity inclusions, and the start and end of the DTD
+	    (and declaration of document element name).
+	    The Object must implement <a href="ext/LexicalHandler.html"
+	    ><em>org.xml.sax.ext.LexicalHandler</em></a>.
+	    </td>
+	</tr>
+
+    <tr>
+	<td>xml-string</td>
+	<td> Readable only during a parser callback, this exposes a <b>TBS</b>
+	    chunk of characters responsible for the current event. </td>
+	</tr>
+
+</table>
+
+<p> All of these standard properties are optional;
+XMLReader implementations need not support them.
+</p>
+
+@since Android 1.0
+
+</body></html>
\ No newline at end of file
diff --git a/xml/src/main/java/org/xmlpull/v1/XmlPullParser.java b/xml/src/main/java/org/xmlpull/v1/XmlPullParser.java
new file mode 100644
index 0000000..2c2946f
--- /dev/null
+++ b/xml/src/main/java/org/xmlpull/v1/XmlPullParser.java
@@ -0,0 +1,1116 @@
+/* -*-             c-basic-offset: 4; indent-tabs-mode: nil; -*-  //------100-columns-wide------>|*/
+// for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/)
+
+package org.xmlpull.v1;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.Reader;
+
+/**
+ * XML Pull Parser is an interface that defines parsing functionlity provided
+ * in <a href="http://www.xmlpull.org/">XMLPULL V1 API</a> (visit this website to
+ * learn more about API and its implementations).
+ *
+ * <p>There are following different
+ * kinds of parser depending on which features are set:<ul>
+ * <li><b>non-validating</b> parser as defined in XML 1.0 spec when
+ *   FEATURE_PROCESS_DOCDECL is set to true
+ * <li><b>validating parser</b> as defined in XML 1.0 spec when
+ *   FEATURE_VALIDATION is true (and that implies that FEATURE_PROCESS_DOCDECL is true)
+ * <li>when FEATURE_PROCESS_DOCDECL is false (this is default and
+ *   if different value is required necessary must be changed before parsing is started)
+ *   then parser behaves like XML 1.0 compliant non-validating parser under condition that
+ *  <em>no DOCDECL is present</em> in XML documents
+ *   (internal entites can still be defined with defineEntityReplacementText()).
+ *   This mode of operation is intened <b>for operation in constrained environments</b> such as J2ME.
+ * </ul>
+ *
+ *
+ * <p>There are two key methods: next() and nextToken(). While next() provides
+ * access to high level parsing events, nextToken() allows access to lower
+ * level tokens.
+ *
+ * <p>The current event state of the parser
+ * can be determined by calling the
+ * <a href="#getEventType()">getEventType()</a> method.
+ * Initially, the parser is in the <a href="#START_DOCUMENT">START_DOCUMENT</a>
+ * state.
+ *
+ * <p>The method <a href="#next()">next()</a> advances the parser to the
+ * next event. The int value returned from next determines the current parser
+ * state and is identical to the value returned from following calls to
+ * getEventType ().
+ *
+ * <p>Th following event types are seen by next()<dl>
+ * <dt><a href="#START_TAG">START_TAG</a><dd> An XML start tag was read.
+ * <dt><a href="#TEXT">TEXT</a><dd> Text content was read;
+ * the text content can be retreived using the getText() method.
+ *  (when in validating mode next() will not report ignorable whitespaces, use nextToken() instead)
+ * <dt><a href="#END_TAG">END_TAG</a><dd> An end tag was read
+ * <dt><a href="#END_DOCUMENT">END_DOCUMENT</a><dd> No more events are available
+ * </dl>
+ *
+ * <p>after first next() or nextToken() (or any other next*() method)
+ * is called user application can obtain
+ * XML version, standalone and encoding from XML declaration
+ * in following ways:<ul>
+ * <li><b>version</b>:
+ *  getProperty(&quot;<a href="http://xmlpull.org/v1/doc/properties.html#xmldecl-version">http://xmlpull.org/v1/doc/properties.html#xmldecl-version</a>&quot;)
+ *       returns String ("1.0") or null if XMLDecl was not read or if property is not supported
+ * <li><b>standalone</b>:
+ *  getProperty(&quot;<a href="http://xmlpull.org/v1/doc/features.html#xmldecl-standalone">http://xmlpull.org/v1/doc/features.html#xmldecl-standalone</a>&quot;)
+ *       returns Boolean: null if there was no standalone declaration
+ *  or if property is not supported
+ *         otherwise returns Boolean(true) if standalon="yes" and Boolean(false) when standalone="no"
+ * <li><b>encoding</b>: obtained from getInputEncoding()
+ *       null if stream had unknown encoding (not set in setInputStream)
+ *           and it was not declared in XMLDecl
+ * </ul>
+ *
+ * A minimal example for using this API may look as follows:
+ * <pre>
+ * import java.io.IOException;
+ * import java.io.StringReader;
+ *
+ * import org.xmlpull.v1.XmlPullParser;
+ * import org.xmlpull.v1.<a href="XmlPullParserException.html">XmlPullParserException.html</a>;
+ * import org.xmlpull.v1.<a href="XmlPullParserFactory.html">XmlPullParserFactory</a>;
+ *
+ * public class SimpleXmlPullApp
+ * {
+ *
+ *     public static void main (String args[])
+ *         throws XmlPullParserException, IOException
+ *     {
+ *         XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
+ *         factory.setNamespaceAware(true);
+ *         XmlPullParser xpp = factory.newPullParser();
+ *
+ *         xpp.<a href="#setInput">setInput</a>( new StringReader ( "&lt;foo>Hello World!&lt;/foo>" ) );
+ *         int eventType = xpp.getEventType();
+ *         while (eventType != XmlPullParser.END_DOCUMENT) {
+ *          if(eventType == XmlPullParser.START_DOCUMENT) {
+ *              System.out.println("Start document");
+ *          } else if(eventType == XmlPullParser.END_DOCUMENT) {
+ *              System.out.println("End document");
+ *          } else if(eventType == XmlPullParser.START_TAG) {
+ *              System.out.println("Start tag "+xpp.<a href="#getName()">getName()</a>);
+ *          } else if(eventType == XmlPullParser.END_TAG) {
+ *              System.out.println("End tag "+xpp.getName());
+ *          } else if(eventType == XmlPullParser.TEXT) {
+ *              System.out.println("Text "+xpp.<a href="#getText()">getText()</a>);
+ *          }
+ *          eventType = xpp.next();
+ *         }
+ *     }
+ * }
+ * </pre>
+ *
+ * <p>The above example will generate the following output:
+ * <pre>
+ * Start document
+ * Start tag foo
+ * Text Hello World!
+ * End tag foo
+ * </pre>
+ *
+ * <p>For more details on API usage, please refer to the
+ * quick Introduction available at <a href="http://www.xmlpull.org">http://www.xmlpull.org</a>
+ *
+ * @see XmlPullParserFactory
+ * @see #defineEntityReplacementText
+ * @see #getName
+ * @see #getNamespace
+ * @see #getText
+ * @see #next
+ * @see #nextToken
+ * @see #setInput
+ * @see #FEATURE_PROCESS_DOCDECL
+ * @see #FEATURE_VALIDATION
+ * @see #START_DOCUMENT
+ * @see #START_TAG
+ * @see #TEXT
+ * @see #END_TAG
+ * @see #END_DOCUMENT
+ *
+ * @author <a href="http://www-ai.cs.uni-dortmund.de/PERSONAL/haustein.html">Stefan Haustein</a>
+ * @author <a href="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a>
+ */
+
+public interface XmlPullParser {
+
+    /** This constant represents the default namespace (empty string "") */
+    String NO_NAMESPACE = "";
+
+    // ----------------------------------------------------------------------------
+    // EVENT TYPES as reported by next()
+
+    /**
+     * Signalize that parser is at the very beginning of the document
+     * and nothing was read yet.
+     * This event type can only be observed by calling getEvent()
+     * before the first call to next(), nextToken, or nextTag()</a>).
+     *
+     * @see #next
+     * @see #nextToken
+     */
+    int START_DOCUMENT = 0;
+
+    /**
+     * Logical end of the xml document. Returned from getEventType, next()
+     * and nextToken()
+     * when the end of the input document has been reached.
+     * <p><strong>NOTE:</strong> calling again
+     * <a href="#next()">next()</a> or <a href="#nextToken()">nextToken()</a>
+     * will result in exception being thrown.
+     *
+     * @see #next
+     * @see #nextToken
+     */
+    int END_DOCUMENT = 1;
+
+    /**
+     * Returned from getEventType(),
+     * <a href="#next()">next()</a>, <a href="#nextToken()">nextToken()</a> when
+     * a start tag was read.
+     * The name of start tag is available from getName(), its namespace and prefix are
+     * available from getNamespace() and getPrefix()
+     * if <a href='#FEATURE_PROCESS_NAMESPACES'>namespaces are enabled</a>.
+     * See getAttribute* methods to retrieve element attributes.
+     * See getNamespace* methods to retrieve newly declared namespaces.
+     *
+     * @see #next
+     * @see #nextToken
+     * @see #getName
+     * @see #getPrefix
+     * @see #getNamespace
+     * @see #getAttributeCount
+     * @see #getDepth
+     * @see #getNamespaceCount
+     * @see #getNamespace
+     * @see #FEATURE_PROCESS_NAMESPACES
+     */
+    int START_TAG = 2;
+
+    /**
+     * Returned from getEventType(), <a href="#next()">next()</a>, or
+     * <a href="#nextToken()">nextToken()</a> when an end tag was read.
+     * The name of start tag is available from getName(), its
+     * namespace and prefix are
+     * available from getNamespace() and getPrefix().
+     *
+     * @see #next
+     * @see #nextToken
+     * @see #getName
+     * @see #getPrefix
+     * @see #getNamespace
+     * @see #FEATURE_PROCESS_NAMESPACES
+     */
+    int END_TAG = 3;
+
+
+    /**
+     * Character data was read and will is available by calling getText().
+     * <p><strong>Please note:</strong> <a href="#next()">next()</a> will
+     * accumulate multiple
+     * events into one TEXT event, skipping IGNORABLE_WHITESPACE,
+     * PROCESSING_INSTRUCTION and COMMENT events,
+     * In contrast, <a href="#nextToken()">nextToken()</a> will stop reading
+     * text when any other event is observed.
+     * Also, when the state was reached by calling next(), the text value will
+     * be normalized, whereas getText() will
+     * return unnormalized content in the case of nextToken(). This allows
+     * an exact roundtrip without chnanging line ends when examining low
+     * level events, whereas for high level applications the text is
+     * normalized apropriately.
+     *
+     * @see #next
+     * @see #nextToken
+     * @see #getText
+     */
+    int TEXT = 4;
+
+    // ----------------------------------------------------------------------------
+    // additional events exposed by lower level nextToken()
+
+    /**
+     * A CDATA sections was just read;
+     * this token is available only from calls to <a href="#nextToken()">nextToken()</a>.
+     * A call to next() will accumulate various text events into a single event
+     * of type TEXT. The text contained in the CDATA section is available
+     * by callling getText().
+     *
+     * @see #nextToken
+     * @see #getText
+     */
+    int CDSECT = 5;
+
+    /**
+     * An entity reference was just read;
+     * this token is available from <a href="#nextToken()">nextToken()</a>
+     * only. The entity name is available by calling getName(). If available,
+     * the replacement text can be obtained by calling getTextt(); otherwise,
+     * the user is responsibile for resolving the entity reference.
+     * This event type is never returned from next(); next() will
+     * accumulate the replacement text and other text
+     * events to a single TEXT event.
+     *
+     * @see #nextToken
+     * @see #getText
+     */
+    int ENTITY_REF = 6;
+
+    /**
+     * Ignorable whitespace was just read.
+     * This token is available only from <a href="#nextToken()">nextToken()</a>).
+     * For non-validating
+     * parsers, this event is only reported by nextToken() when outside
+     * the root element.
+     * Validating parsers may be able to detect ignorable whitespace at
+     * other locations.
+     * The ignorable whitespace string is available by calling getText()
+     *
+     * <p><strong>NOTE:</strong> this is different from calling the
+     *  isWhitespace() method, since text content
+     *  may be whitespace but not ignorable.
+     *
+     * Ignorable whitespace is skipped by next() automatically; this event
+     * type is never returned from next().
+     *
+     * @see #nextToken
+     * @see #getText
+     */
+    int IGNORABLE_WHITESPACE = 7;
+
+    /**
+     * An XML processing instruction declaration was just read. This
+     * event type is available only via <a href="#nextToken()">nextToken()</a>.
+     * getText() will return text that is inside the processing instruction.
+     * Calls to next() will skip processing instructions automatically.
+     * @see #nextToken
+     * @see #getText
+     */
+    int PROCESSING_INSTRUCTION = 8;
+
+    /**
+     * An XML comment was just read. This event type is this token is
+     * available via <a href="#nextToken()">nextToken()</a> only;
+     * calls to next() will skip comments automatically.
+     * The content of the comment can be accessed using the getText()
+     * method.
+     *
+     * @see #nextToken
+     * @see #getText
+     */
+    int COMMENT = 9;
+
+    /**
+     * An XML document type declaration was just read. This token is
+     * available from <a href="#nextToken()">nextToken()</a> only.
+     * The unparsed text inside the doctype is available via
+     * the getText() method.
+     *
+     * @see #nextToken
+     * @see #getText
+     */
+    int DOCDECL = 10;
+
+    /**
+     * This array can be used to convert the event type integer constants
+     * such as START_TAG or TEXT to
+     * to a string. For example, the value of TYPES[START_TAG] is
+     * the string "START_TAG".
+     *
+     * This array is intended for diagnostic output only. Relying
+     * on the contents of the array may be dangerous since malicous
+     * applications may alter the array, although it is final, due
+     * to limitations of the Java language.
+     */
+    String [] TYPES = {
+        "START_DOCUMENT",
+            "END_DOCUMENT",
+            "START_TAG",
+            "END_TAG",
+            "TEXT",
+            "CDSECT",
+            "ENTITY_REF",
+            "IGNORABLE_WHITESPACE",
+            "PROCESSING_INSTRUCTION",
+            "COMMENT",
+            "DOCDECL"
+    };
+
+
+    // ----------------------------------------------------------------------------
+    // namespace related features
+
+    /**
+     * This feature determines whether the parser processes
+     * namespaces. As for all features, the default value is false.
+     * <p><strong>NOTE:</strong> The value can not be changed during
+     * parsing an must be set before parsing.
+     *
+     * @see #getFeature
+     * @see #setFeature
+     */
+    String FEATURE_PROCESS_NAMESPACES =
+        "http://xmlpull.org/v1/doc/features.html#process-namespaces";
+
+    /**
+     * This feature determines whether namespace attributes are
+     * exposed via the attribute access methods. Like all features,
+     * the default value is false. This feature cannot be changed
+     * during parsing.
+     *
+     * @see #getFeature
+     * @see #setFeature
+     */
+    String FEATURE_REPORT_NAMESPACE_ATTRIBUTES =
+        "http://xmlpull.org/v1/doc/features.html#report-namespace-prefixes";
+
+    /**
+     * This feature determines whether the document declaration
+     * is processed. If set to false,
+     * the DOCDECL event type is reported by nextToken()
+     * and ignored by next().
+     *
+     * If this featue is activated, then the document declaration
+     * must be processed by the parser.
+     *
+     * <p><strong>Please note:</strong> If the document type declaration
+     * was ignored, entity references may cause exceptions
+     * later in the parsing process.
+     * The default value of this feature is false. It cannot be changed
+     * during parsing.
+     *
+     * @see #getFeature
+     * @see #setFeature
+     */
+    String FEATURE_PROCESS_DOCDECL =
+        "http://xmlpull.org/v1/doc/features.html#process-docdecl";
+
+    /**
+     * If this feature is activated, all validation errors as
+     * defined in the XML 1.0 sepcification are reported.
+     * This implies that FEATURE_PROCESS_DOCDECL is true and both, the
+     * internal and external document type declaration will be processed.
+     * <p><strong>Please Note:</strong> This feature can not be changed
+     * during parsing. The default value is false.
+     *
+     * @see #getFeature
+     * @see #setFeature
+     */
+    String FEATURE_VALIDATION =
+        "http://xmlpull.org/v1/doc/features.html#validation";
+
+    /**
+     * Use this call to change the general behaviour of the parser,
+     * such as namespace processing or doctype declaration handling.
+     * This method must be called before the first call to next or
+     * nextToken. Otherwise, an exception is thrown.
+     * <p>Example: call setFeature(FEATURE_PROCESS_NAMESPACES, true) in order
+     * to switch on namespace processing. The initial settings correspond
+     * to the properties requested from the XML Pull Parser factory.
+     * If none were requested, all feautures are deactivated by default.
+     *
+     * @exception XmlPullParserException If the feature is not supported or can not be set
+     * @exception IllegalArgumentException If string with the feature name is null
+     */
+    void setFeature(String name,
+                           boolean state) throws XmlPullParserException;
+
+    /**
+     * Returns the current value of the given feature.
+     * <p><strong>Please note:</strong> unknown features are
+     * <strong>always</strong> returned as false.
+     *
+     * @param name The name of feature to be retrieved.
+     * @return The value of the feature.
+     * @exception IllegalArgumentException if string the feature name is null
+     */
+
+    boolean getFeature(String name);
+
+    /**
+     * Set the value of a property.
+     *
+     * The property name is any fully-qualified URI.
+     *
+     * @exception XmlPullParserException If the property is not supported or can not be set
+     * @exception IllegalArgumentException If string with the property name is null
+     */
+    void setProperty(String name,
+                            Object value) throws XmlPullParserException;
+
+    /**
+     * Look up the value of a property.
+     *
+     * The property name is any fully-qualified URI.
+     * <p><strong>NOTE:</strong> unknown properties are <strong>always</strong>
+     * returned as null.
+     *
+     * @param name The name of property to be retrieved.
+     * @return The value of named property.
+     */
+    Object getProperty(String name);
+
+
+    /**
+     * Set the input source for parser to the given reader and
+     * resets the parser. The event type is set to the initial value
+     * START_DOCUMENT.
+     * Setting the reader to null will just stop parsing and
+     * reset parser state,
+     * allowing the parser to free internal resources
+     * such as parsing buffers.
+     */
+    void setInput(Reader in) throws XmlPullParserException;
+
+
+    /**
+     * Sets the input stream the parser is going to process.
+     * This call resets the parser state and sets the event type
+     * to the initial value START_DOCUMENT.
+     *
+     * <p><strong>NOTE:</strong> If an input encoding string is passed,
+     *  it MUST be used. Otherwise,
+     *  if inputEncoding is null, the parser SHOULD try to determine
+     *  input encoding following XML 1.0 specification (see below).
+     *  If encoding detection is supported then following feature
+     *  <a href="http://xmlpull.org/v1/doc/features.html#detect-encoding">http://xmlpull.org/v1/doc/features.html#detect-encoding</a>
+     *  MUST be true amd otherwise it must be false
+     *
+     * @param inputStream contains a raw byte input stream of possibly
+     *     unknown encoding (when inputEncoding is null).
+     *
+     * @param inputEncoding if not null it MUST be used as encoding for inputStream
+     */
+    void setInput(InputStream inputStream, String inputEncoding)
+        throws XmlPullParserException;
+
+    /**
+     * Returns the input encoding if known, null otherwise.
+     * If setInput(InputStream, inputEncoding) was called with an inputEncoding
+     * value other than null, this value must be returned
+     * from this method. Otherwise, if inputEncoding is null and
+     * the parser suppports the encoding detection feature
+     * (http://xmlpull.org/v1/doc/features.html#detect-encoding),
+     * it must return the detected encoding.
+     * If setInput(Reader) was called, null is returned.
+     * After first call to next if XML declaration was present this method
+     * will return encoding declared.
+     */
+    String getInputEncoding();
+
+    /**
+     * Set new value for entity replacement text as defined in
+     * <a href="http://www.w3.org/TR/REC-xml#intern-replacement">XML 1.0 Section 4.5
+     * Construction of Internal Entity Replacement Text</a>.
+     * If FEATURE_PROCESS_DOCDECL or FEATURE_VALIDATION are set, calling this
+     * function will result in an exception -- when processing of DOCDECL is
+     * enabled, there is no need to the entity replacement text manually.
+     *
+     * <p>The motivation for this function is to allow very small
+     * implementations of XMLPULL that will work in J2ME environments.
+     * Though these implementations may not be able to process the document type
+     * declaration, they still can work with known DTDs by using this function.
+     *
+     * <p><b>Please notes:</b> The given value is used literally as replacement text
+     * and it corresponds to declaring entity in DTD that has all special characters
+     * escaped: left angle bracket is replaced with &amp;lt;, ampersnad with &amp;amp;
+     * and so on.
+     *
+     * <p><b>Note:</b> The given value is the literal replacement text and must not
+     * contain any other entity reference (if it contains any entity reference
+     * there will be no further replacement).
+     *
+     * <p><b>Note:</b> The list of pre-defined entity names will
+     * always contain standard XML entities such as
+     * amp (&amp;amp;), lt (&amp;lt;), gt (&amp;gt;), quot (&amp;quot;), and apos (&amp;apos;).
+     * Those cannot be redefined by this method!
+     *
+     * @see #setInput
+     * @see #FEATURE_PROCESS_DOCDECL
+     * @see #FEATURE_VALIDATION
+     */
+    void defineEntityReplacementText( String entityName,
+                                            String replacementText ) throws XmlPullParserException;
+
+    /**
+     * Returns the numbers of elements in the namespace stack for the given
+     * depth.
+     * If namespaces are not enabled, 0 is returned.
+     *
+     * <p><b>NOTE:</b> when parser is on END_TAG then it is allowed to call
+     *  this function with getDepth()+1 argument to retrieve position of namespace
+     *  prefixes and URIs that were declared on corresponding START_TAG.
+     * <p><b>NOTE:</b> to retrieve lsit of namespaces declared in current element:<pre>
+     *       XmlPullParser pp = ...
+     *       int nsStart = pp.getNamespaceCount(pp.getDepth()-1);
+     *       int nsEnd = pp.getNamespaceCount(pp.getDepth());
+     *       for (int i = nsStart; i < nsEnd; i++) {
+     *          String prefix = pp.getNamespacePrefix(i);
+     *          String ns = pp.getNamespaceUri(i);
+     *           // ...
+     *      }
+     * </pre>
+     *
+     * @see #getNamespacePrefix
+     * @see #getNamespaceUri
+     * @see #getNamespace()
+     * @see #getNamespace(String)
+     */
+    int getNamespaceCount(int depth) throws XmlPullParserException;
+
+    /**
+     * Returns the namespace prefixe for the given position
+     * in the namespace stack.
+     * Default namespace declaration (xmlns='...') will have null as prefix.
+     * If the given index is out of range, an exception is thrown.
+     * <p><b>Please note:</b> when the parser is on an END_TAG,
+     * namespace prefixes that were declared
+     * in the corresponding START_TAG are still accessible
+     * although they are no longer in scope.
+     */
+    String getNamespacePrefix(int pos) throws XmlPullParserException;
+
+    /**
+     * Returns the namespace URI for the given position in the
+     * namespace stack
+     * If the position is out of range, an exception is thrown.
+     * <p><b>NOTE:</b> when parser is on END_TAG then namespace prefixes that were declared
+     *  in corresponding START_TAG are still accessible even though they are not in scope
+     */
+    String getNamespaceUri(int pos) throws XmlPullParserException;
+
+    /**
+     * Returns the URI corresponding to the given prefix,
+     * depending on current state of the parser.
+     *
+     * <p>If the prefix was not declared in the current scope,
+     * null is returned. The default namespace is included
+     * in the namespace table and is available via
+     * getNamespace (null).
+     *
+     * <p>This method is a convenience method for
+     *
+     * <pre>
+     *  for (int i = getNamespaceCount(getDepth ())-1; i >= 0; i--) {
+     *   if (getNamespacePrefix(i).equals( prefix )) {
+     *     return getNamespaceUri(i);
+     *   }
+     *  }
+     *  return null;
+     * </pre>
+     *
+     * <p><strong>Please note:</strong> parser implementations
+     * may provide more efifcient lookup, e.g. using a Hashtable.
+     * The 'xml' prefix is bound to "http://www.w3.org/XML/1998/namespace", as
+     * defined in the
+     * <a href="http://www.w3.org/TR/REC-xml-names/#ns-using">Namespaces in XML</a>
+     * specification. Analogous, the 'xmlns' prefix is resolved to
+     * <a href="http://www.w3.org/2000/xmlns/">http://www.w3.org/2000/xmlns/</a>
+     *
+     * @see #getNamespaceCount
+     * @see #getNamespacePrefix
+     * @see #getNamespaceUri
+     */
+    String getNamespace (String prefix);
+
+
+    // --------------------------------------------------------------------------
+    // miscellaneous reporting methods
+
+    /**
+     * Returns the current depth of the element.
+     * Outside the root element, the depth is 0. The
+     * depth is incremented by 1 when a start tag is reached.
+     * The depth is decremented AFTER the end tag
+     * event was observed.
+     *
+     * <pre>
+     * &lt;!-- outside --&gt;     0
+     * &lt;root>                  1
+     *   sometext                 1
+     *     &lt;foobar&gt;         2
+     *     &lt;/foobar&gt;        2
+     * &lt;/root&gt;              1
+     * &lt;!-- outside --&gt;     0
+     * </pre>
+     */
+    int getDepth();
+
+    /**
+     * Returns a short text describing the current parser state, including
+     * the position, a
+     * description of the current event and the data source if known.
+     * This method is especially useful to provide meaningful
+     * error messages and for debugging purposes.
+     */
+    String getPositionDescription ();
+
+
+    /**
+     * Returns the current line number, starting from 1.
+     * When the parser does not know the current line number
+     * or can not determine it,  -1 is returned (e.g. for WBXML).
+     *
+     * @return current line number or -1 if unknown.
+     */
+    int getLineNumber();
+
+    /**
+     * Returns the current column number, starting from 0.
+     * When the parser does not know the current column number
+     * or can not determine it,  -1 is returned (e.g. for WBXML).
+     *
+     * @return current column number or -1 if unknown.
+     */
+    int getColumnNumber();
+
+
+    // --------------------------------------------------------------------------
+    // TEXT related methods
+
+    /**
+     * Checks whether the current TEXT event contains only whitespace
+     * characters.
+     * For IGNORABLE_WHITESPACE, this is always true.
+     * For TEXT and CDSECT, false is returned when the current event text
+     * contains at least one non-white space character. For any other
+     * event type an exception is thrown.
+     *
+     * <p><b>Please note:</b> non-validating parsers are not
+     * able to distinguish whitespace and ignorable whitespace,
+     * except from whitespace outside the root element. Ignorable
+     * whitespace is reported as separate event, which is exposed
+     * via nextToken only.
+     *
+     */
+    boolean isWhitespace() throws XmlPullParserException;
+
+    /**
+     * Returns the text content of the current event as String.
+     * The value returned depends on current event type,
+     * for example for TEXT event it is element content
+     * (this is typical case when next() is used).
+     *
+     * See description of nextToken() for detailed description of
+     * possible returned values for different types of events.
+     *
+     * <p><strong>NOTE:</strong> in case of ENTITY_REF, this method returns
+     * the entity replacement text (or null if not available). This is
+     * the only case where
+     * getText() and getTextCharacters() return different values.
+     *
+     * @see #getEventType
+     * @see #next
+     * @see #nextToken
+     */
+    String getText ();
+
+
+    /**
+     * Returns the buffer that contains the text of the current event,
+     * as well as the start offset and length relevant for the current
+     * event. See getText(), next() and nextToken() for description of possible returned values.
+     *
+     * <p><strong>Please note:</strong> this buffer must not
+     * be modified and its content MAY change after a call to
+     * next() or nextToken(). This method will always return the
+     * same value as getText(), except for ENTITY_REF. In the case
+     * of ENTITY ref, getText() returns the replacement text and
+     * this method returns the actual input buffer containing the
+     * entity name.
+     * If getText() returns null, this method returns null as well and
+     * the values returned in the holder array MUST be -1 (both start
+     * and length).
+     *
+     * @see #getText
+     * @see #next
+     * @see #nextToken
+     *
+     * @param holderForStartAndLength Must hold an 2-element int array
+     * into which the start offset and length values will be written.
+     * @return char buffer that contains the text of the current event
+     *  (null if the current event has no text associated).
+     */
+    char[] getTextCharacters(int [] holderForStartAndLength);
+
+    // --------------------------------------------------------------------------
+    // START_TAG / END_TAG shared methods
+
+    /**
+     * Returns the namespace URI of the current element.
+     * The default namespace is represented
+     * as empty string.
+     * If namespaces are not enabled, an empty String ("") is always returned.
+     * The current event must be START_TAG or END_TAG; otherwise,
+     * null is returned.
+     */
+    String getNamespace ();
+
+    /**
+     * For START_TAG or END_TAG events, the (local) name of the current
+     * element is returned when namespaces are enabled. When namespace
+     * processing is disabled, the raw name is returned.
+     * For ENTITY_REF events, the entity name is returned.
+     * If the current event is not START_TAG, END_TAG, or ENTITY_REF,
+     * null is returned.
+     * <p><b>Please note:</b> To reconstruct the raw element name
+     *  when namespaces are enabled and the prefix is not null,
+     * you will need to  add the prefix and a colon to localName..
+     *
+     */
+    String getName();
+
+    /**
+     * Returns the prefix of the current element.
+     * If the element is in the default namespace (has no prefix),
+     * null is returned.
+     * If namespaces are not enabled, or the current event
+     * is not  START_TAG or END_TAG, null is returned.
+     */
+    String getPrefix();
+
+    /**
+     * Returns true if the current event is START_TAG and the tag
+     * is degenerated
+     * (e.g. &lt;foobar/&gt;).
+     * <p><b>NOTE:</b> if the parser is not on START_TAG, an exception
+     * will be thrown.
+     */
+    boolean isEmptyElementTag() throws XmlPullParserException;
+
+    // --------------------------------------------------------------------------
+    // START_TAG Attributes retrieval methods
+
+    /**
+     * Returns the number of attributes of the current start tag, or
+     * -1 if the current event type is not START_TAG
+     *
+     * @see #getAttributeNamespace
+     * @see #getAttributeName
+     * @see #getAttributePrefix
+     * @see #getAttributeValue
+     */
+    int getAttributeCount();
+
+    /**
+     * Returns the namespace URI of the attribute
+     * with the given index (starts from 0).
+     * Returns an empty string ("") if namespaces are not enabled
+     * or the attribute has no namespace.
+     * Throws an IndexOutOfBoundsException if the index is out of range
+     * or the current event type is not START_TAG.
+     *
+     * <p><strong>NOTE:</strong> if FEATURE_REPORT_NAMESPACE_ATTRIBUTES is set
+     * then namespace attributes (xmlns:ns='...') must be reported
+     * with namespace
+     * <a href="http://www.w3.org/2000/xmlns/">http://www.w3.org/2000/xmlns/</a>
+     * (visit this URL for description!).
+     * The default namespace attribute (xmlns="...") will be reported with empty namespace.
+     * <p><strong>NOTE:</strong>The xml prefix is bound as defined in
+     * <a href="http://www.w3.org/TR/REC-xml-names/#ns-using">Namespaces in XML</a>
+     * specification to "http://www.w3.org/XML/1998/namespace".
+     *
+     * @param index zero-based index of attribute
+     * @return attribute namespace,
+     *   empty string ("") is returned  if namesapces processing is not enabled or
+     *   namespaces processing is enabled but attribute has no namespace (it has no prefix).
+     */
+    String getAttributeNamespace (int index);
+
+    /**
+     * Returns the local name of the specified attribute
+     * if namespaces are enabled or just attribute name if namespaces are disabled.
+     * Throws an IndexOutOfBoundsException if the index is out of range
+     * or current event type is not START_TAG.
+     *
+     * @param index zero-based index of attribute
+     * @return attribute name (null is never returned)
+     */
+    String getAttributeName (int index);
+
+    /**
+     * Returns the prefix of the specified attribute
+     * Returns null if the element has no prefix.
+     * If namespaces are disabled it will always return null.
+     * Throws an IndexOutOfBoundsException if the index is out of range
+     * or current event type is not START_TAG.
+     *
+     * @param index zero-based index of attribute
+     * @return attribute prefix or null if namespaces processing is not enabled.
+     */
+    String getAttributePrefix(int index);
+
+    /**
+     * Returns the type of the specified attribute
+     * If parser is non-validating it MUST return CDATA.
+     *
+     * @param index zero-based index of attribute
+     * @return attribute type (null is never returned)
+     */
+    String getAttributeType(int index);
+
+    /**
+     * Returns if the specified attribute was not in input was declared in XML.
+     * If parser is non-validating it MUST always return false.
+     * This information is part of XML infoset:
+     *
+     * @param index zero-based index of attribute
+     * @return false if attribute was in input
+     */
+    boolean isAttributeDefault(int index);
+
+    /**
+     * Returns the given attributes value.
+     * Throws an IndexOutOfBoundsException if the index is out of range
+     * or current event type is not START_TAG.
+     *
+     * <p><strong>NOTE:</strong> attribute value must be normalized
+     * (including entity replacement text if PROCESS_DOCDECL is false) as described in
+     * <a href="http://www.w3.org/TR/REC-xml#AVNormalize">XML 1.0 section
+     * 3.3.3 Attribute-Value Normalization</a>
+     *
+     * @see #defineEntityReplacementText
+     *
+     * @param index zero-based index of attribute
+     * @return value of attribute (null is never returned)
+     */
+    String getAttributeValue(int index);
+
+    /**
+     * Returns the attributes value identified by namespace URI and namespace localName.
+     * If namespaces are disabled namespace must be null.
+     * If current event type is not START_TAG then IndexOutOfBoundsException will be thrown.
+     *
+     * <p><strong>NOTE:</strong> attribute value must be normalized
+     * (including entity replacement text if PROCESS_DOCDECL is false) as described in
+     * <a href="http://www.w3.org/TR/REC-xml#AVNormalize">XML 1.0 section
+     * 3.3.3 Attribute-Value Normalization</a>
+     *
+     * @see #defineEntityReplacementText
+     *
+     * @param namespace Namespace of the attribute if namespaces are enabled otherwise must be null
+     * @param name If namespaces enabled local name of attribute otherwise just attribute name
+     * @return value of attribute or null if attribute with given name does not exist
+     */
+    String getAttributeValue(String namespace,
+                                    String name);
+
+    // --------------------------------------------------------------------------
+    // actual parsing methods
+
+    /**
+     * Returns the type of the current event (START_TAG, END_TAG, TEXT, etc.)
+     *
+     * @see #next()
+     * @see #nextToken()
+     */
+    int getEventType()
+        throws XmlPullParserException;
+
+    /**
+     * Get next parsing event - element content wil be coalesced and only one
+     * TEXT event must be returned for whole element content
+     * (comments and processing instructions will be ignored and emtity references
+     * must be expanded or exception mus be thrown if entity reerence can not be exapnded).
+     * If element content is empty (content is "") then no TEXT event will be reported.
+     *
+     * <p><b>NOTE:</b> empty element (such as &lt;tag/>) will be reported
+     *  with  two separate events: START_TAG, END_TAG - it must be so to preserve
+     *   parsing equivalency of empty element to &lt;tag>&lt;/tag>.
+     *  (see isEmptyElementTag ())
+     *
+     * @see #isEmptyElementTag
+     * @see #START_TAG
+     * @see #TEXT
+     * @see #END_TAG
+     * @see #END_DOCUMENT
+     */
+
+    int next()
+        throws XmlPullParserException, IOException;
+
+
+    /**
+     * This method works similarly to next() but will expose
+     * additional event types (COMMENT, CDSECT, DOCDECL, ENTITY_REF, PROCESSING_INSTRUCTION, or
+     * IGNORABLE_WHITESPACE) if they are available in input.
+     *
+     * <p>If special feature
+     * <a href="http://xmlpull.org/v1/doc/features.html#xml-roundtrip">FEATURE_XML_ROUNDTRIP</a>
+     * (identified by URI: http://xmlpull.org/v1/doc/features.html#xml-roundtrip)
+     * is enabled it is possible to do XML document round trip ie. reproduce
+     * exectly on output the XML input using getText():
+     * returned content is always unnormalized (exactly as in input).
+     * Otherwise returned content is end-of-line normalized as described
+     * <a href="http://www.w3.org/TR/REC-xml#sec-line-ends">XML 1.0 End-of-Line Handling</a>
+     * and. Also when this feature is enabled exact content of START_TAG, END_TAG,
+     * DOCDECL and PROCESSING_INSTRUCTION is available.
+     *
+     * <p>Here is the list of tokens that can be  returned from nextToken()
+     * and what getText() and getTextCharacters() returns:<dl>
+     * <dt>START_DOCUMENT<dd>null
+     * <dt>END_DOCUMENT<dd>null
+     * <dt>START_TAG<dd>null unless FEATURE_XML_ROUNDTRIP
+     *   enabled and then returns XML tag, ex: &lt;tag attr='val'>
+     * <dt>END_TAG<dd>null unless FEATURE_XML_ROUNDTRIP
+     *  id enabled and then returns XML tag, ex: &lt;/tag>
+     * <dt>TEXT<dd>return element content.
+     *  <br>Note: that element content may be delivered in multiple consecutive TEXT events.
+     * <dt>IGNORABLE_WHITESPACE<dd>return characters that are determined to be ignorable white
+     * space. If the FEATURE_XML_ROUNDTRIP is enabled all whitespace content outside root
+     * element will always reported as IGNORABLE_WHITESPACE otherise rteporting is optional.
+     *  <br>Note: that element content may be delevered in multiple consecutive IGNORABLE_WHITESPACE events.
+     * <dt>CDSECT<dd>
+     * return text <em>inside</em> CDATA
+     *  (ex. 'fo&lt;o' from &lt;!CDATA[fo&lt;o]]>)
+     * <dt>PROCESSING_INSTRUCTION<dd>
+     *  if FEATURE_XML_ROUNDTRIP is true
+     *  return exact PI content ex: 'pi foo' from &lt;?pi foo?>
+     *  otherwise it may be exact PI content or concatenation of PI target,
+     * space and data so for example for
+     *   &lt;?target    data?> string &quot;target data&quot; may
+     *       be returned if FEATURE_XML_ROUNDTRIP is false.
+     * <dt>COMMENT<dd>return comment content ex. 'foo bar' from &lt;!--foo bar-->
+     * <dt>ENTITY_REF<dd>getText() MUST return entity replacement text if PROCESS_DOCDECL is false
+     * otherwise getText() MAY return null,
+     * additionally getTextCharacters() MUST return entity name
+     * (for example 'entity_name' for &amp;entity_name;).
+     * <br><b>NOTE:</b> this is the only place where value returned from getText() and
+     *   getTextCharacters() <b>are different</b>
+     * <br><b>NOTE:</b> it is user responsibility to resolve entity reference
+     *    if PROCESS_DOCDECL is false and there is no entity replacement text set in
+     *    defineEntityReplacementText() method (getText() will be null)
+     * <br><b>NOTE:</b> character entities (ex. &amp;#32;) and standard entities such as
+     *  &amp;amp; &amp;lt; &amp;gt; &amp;quot; &amp;apos; are reported as well
+     *  and are <b>not</b> reported as TEXT tokens but as ENTITY_REF tokens!
+     *  This requirement is added to allow to do roundtrip of XML documents!
+     * <dt>DOCDECL<dd>
+     * if FEATURE_XML_ROUNDTRIP is true or PROCESS_DOCDECL is false
+     * then return what is inside of DOCDECL for example it returns:<pre>
+     * &quot; titlepage SYSTEM "http://www.foo.bar/dtds/typo.dtd"
+     * [&lt;!ENTITY % active.links "INCLUDE">]&quot;</pre>
+     * <p>for input document that contained:<pre>
+     * &lt;!DOCTYPE titlepage SYSTEM "http://www.foo.bar/dtds/typo.dtd"
+     * [&lt;!ENTITY % active.links "INCLUDE">]></pre>
+     * otherwise if FEATURE_XML_ROUNDTRIP is false and PROCESS_DOCDECL is true
+     *    then what is returned is undefined (it may be even null)
+     * </dd>
+     * </dl>
+     *
+     * <p><strong>NOTE:</strong> there is no gurantee that there will only one TEXT or
+     * IGNORABLE_WHITESPACE event from nextToken() as parser may chose to deliver element content in
+     * multiple tokens (dividing element content into chunks)
+     *
+     * <p><strong>NOTE:</strong> whether returned text of token is end-of-line normalized
+     *  is depending on FEATURE_XML_ROUNDTRIP.
+     *
+     * <p><strong>NOTE:</strong> XMLDecl (&lt;?xml ...?&gt;) is not reported but its content
+     * is available through optional properties (see class description above).
+     *
+     * @see #next
+     * @see #START_TAG
+     * @see #TEXT
+     * @see #END_TAG
+     * @see #END_DOCUMENT
+     * @see #COMMENT
+     * @see #DOCDECL
+     * @see #PROCESSING_INSTRUCTION
+     * @see #ENTITY_REF
+     * @see #IGNORABLE_WHITESPACE
+     */
+    int nextToken()
+        throws XmlPullParserException, IOException;
+
+    //-----------------------------------------------------------------------------
+    // utility methods to mak XML parsing easier ...
+
+    /**
+     * Test if the current event is of the given type and if the
+     * namespace and name do match. null will match any namespace
+     * and any name. If the test is not passed, an exception is
+     * thrown. The exception text indicates the parser position,
+     * the expected event and the current event that is not meeting the
+     * requirement.
+     *
+     * <p>Essentially it does this
+     * <pre>
+     *  if (type != getEventType()
+     *  || (namespace != null &amp;&amp;  !namespace.equals( getNamespace () ) )
+     *  || (name != null &amp;&amp;  !name.equals( getName() ) ) )
+     *     throw new XmlPullParserException( "expected "+ TYPES[ type ]+getPositionDescription());
+     * </pre>
+     */
+    void require(int type, String namespace, String name)
+        throws XmlPullParserException, IOException;
+
+    /**
+     * If current event is START_TAG then if next element is TEXT then element content is returned
+     * or if next event is END_TAG then empty string is returned, otherwise exception is thrown.
+     * After calling this function successfully parser will be positioned on END_TAG.
+     *
+     * <p>The motivation for this function is to allow to parse consistently both
+     * empty elements and elements that has non empty content, for example for input: <ol>
+     * <li>&lt;tag&gt;foo&lt;/tag&gt;
+     * <li>&lt;tag&gt;&lt;/tag&gt; (which is equivalent to &lt;tag/&gt;
+     * both input can be parsed with the same code:
+     * <pre>
+     *   p.nextTag()
+     *   p.requireEvent(p.START_TAG, "", "tag");
+     *   String content = p.nextText();
+     *   p.requireEvent(p.END_TAG, "", "tag");
+     * </pre>
+     * This function together with nextTag make it very easy to parse XML that has
+     * no mixed content.
+     *
+     *
+     * <p>Essentially it does this
+     * <pre>
+     *  if(getEventType() != START_TAG) {
+     *     throw new XmlPullParserException(
+     *       "parser must be on START_TAG to read next text", this, null);
+     *  }
+     *  int eventType = next();
+     *  if(eventType == TEXT) {
+     *     String result = getText();
+     *     eventType = next();
+     *     if(eventType != END_TAG) {
+     *       throw new XmlPullParserException(
+     *          "event TEXT it must be immediately followed by END_TAG", this, null);
+     *      }
+     *      return result;
+     *  } else if(eventType == END_TAG) {
+     *     return "";
+     *  } else {
+     *     throw new XmlPullParserException(
+     *       "parser must be on START_TAG or TEXT to read text", this, null);
+     *  }
+     * </pre>
+     */
+    String nextText() throws XmlPullParserException, IOException;
+
+    /**
+     * Call next() and return event if it is START_TAG or END_TAG
+     * otherwise throw an exception.
+     * It will skip whitespace TEXT before actual tag if any.
+     *
+     * <p>essentially it does this
+     * <pre>
+     *   int eventType = next();
+     *   if(eventType == TEXT &amp;&amp;  isWhitespace()) {   // skip whitespace
+     *      eventType = next();
+     *   }
+     *   if (eventType != START_TAG &amp;&amp;  eventType != END_TAG) {
+     *      throw new XmlPullParserException("expected start or end tag", this, null);
+     *   }
+     *   return eventType;
+     * </pre>
+     */
+    int nextTag() throws XmlPullParserException, IOException;
+
+}
+
diff --git a/xml/src/main/java/org/xmlpull/v1/XmlPullParserException.java b/xml/src/main/java/org/xmlpull/v1/XmlPullParserException.java
new file mode 100644
index 0000000..b4b4b71
--- /dev/null
+++ b/xml/src/main/java/org/xmlpull/v1/XmlPullParserException.java
@@ -0,0 +1,76 @@
+/* -*-             c-basic-offset: 4; indent-tabs-mode: nil; -*-  //------100-columns-wide------>|*/
+// for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/)
+
+package org.xmlpull.v1;
+
+/**
+ * This exception is thrown to signal XML Pull Parser related faults.
+ *
+ * @author <a href="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a>
+ */
+public class XmlPullParserException extends Exception {
+    protected Throwable detail;
+    protected int row = -1;
+    protected int column = -1;
+
+    /*    public XmlPullParserException() {
+          }*/
+
+    public XmlPullParserException(String s) {
+        super(s);
+    }
+
+    /*
+    public XmlPullParserException(String s, Throwable thrwble) {
+        super(s);
+        this.detail = thrwble;
+        }
+
+    public XmlPullParserException(String s, int row, int column) {
+        super(s);
+        this.row = row;
+        this.column = column;
+    }
+    */
+
+    public XmlPullParserException(String msg, XmlPullParser parser, Throwable chain) {
+        super ((msg == null ? "" : msg+" ")
+               + (parser == null ? "" : "(position:"+parser.getPositionDescription()+") ")
+               + (chain == null ? "" : "caused by: "+chain));
+
+        if (parser != null) {
+            this.row = parser.getLineNumber();
+            this.column = parser.getColumnNumber();
+        }
+        this.detail = chain;
+    }
+
+    public Throwable getDetail() { return detail; }
+    //    public void setDetail(Throwable cause) { this.detail = cause; }
+    public int getLineNumber() { return row; }
+    public int getColumnNumber() { return column; }
+
+    /*
+    public String getMessage() {
+        if(detail == null)
+            return super.getMessage();
+        else
+            return super.getMessage() + "; nested exception is: \n\t"
+                + detail.getMessage();
+    }
+    */
+
+    //NOTE: code that prints this and detail is difficult in J2ME
+    public void printStackTrace() {
+        if (detail == null) {
+            super.printStackTrace();
+        } else {
+            synchronized(System.err) {
+                System.err.println(super.getMessage() + "; nested exception is:");
+                detail.printStackTrace();
+            }
+        }
+    }
+
+}
+
diff --git a/xml/src/main/java/org/xmlpull/v1/XmlPullParserFactory.java b/xml/src/main/java/org/xmlpull/v1/XmlPullParserFactory.java
new file mode 100644
index 0000000..7b786f6
--- /dev/null
+++ b/xml/src/main/java/org/xmlpull/v1/XmlPullParserFactory.java
@@ -0,0 +1,349 @@
+/* -*-             c-basic-offset: 4; indent-tabs-mode: nil; -*-  //------100-columns-wide------>|*/
+// for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/)
+
+package org.xmlpull.v1;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * This class is used to create implementations of XML Pull Parser defined in XMPULL V1 API.
+ * The name of actual factory class will be determined based on several parameters.
+ * It works similar to JAXP but tailored to work in J2ME environments
+ * (no access to system properties or file system) so name of parser class factory to use
+ * and its class used for loading (no class loader - on J2ME no access to context class loaders)
+ * must be passed explicitly. If no name of parser factory was passed (or is null)
+ * it will try to find name by searching in CLASSPATH for
+ * META-INF/services/org.xmlpull.v1.XmlPullParserFactory resource that should contain
+ * a comma separated list of class names of factories or parsers to try (in order from
+ * left to the right). If none found, it will throw an exception.
+ *
+ * <br /><strong>NOTE:</strong>In J2SE or J2EE environments, you may want to use
+ * <code>newInstance(property, classLoaderCtx)</code>
+ * where first argument is
+ * <code>System.getProperty(XmlPullParserFactory.PROPERTY_NAME)</code>
+ * and second is <code>Thread.getContextClassLoader().getClass()</code> .
+ *
+ * @see XmlPullParser
+ *
+ * @author <a href="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a>
+ * @author Stefan Haustein
+ */
+
+public class XmlPullParserFactory {
+    /** used as default class to server as context class in newInstance() */
+    final static Class referenceContextClass;
+
+    static {
+        XmlPullParserFactory f = new XmlPullParserFactory();
+        referenceContextClass = f.getClass();
+    }
+
+    /** Name of the system or midlet property that should be used for
+     a system property containing a comma separated list of factory
+     or parser class names (value:
+     org.xmlpull.v1.XmlPullParserFactory). */
+
+
+    public static final String PROPERTY_NAME =
+        "org.xmlpull.v1.XmlPullParserFactory";
+
+    private static final String RESOURCE_NAME =
+        "/META-INF/services/" + PROPERTY_NAME;
+
+
+    // public static final String DEFAULT_PROPERTY =
+    //    "org.xmlpull.xpp3.XmlPullParser,org.kxml2.io.KXmlParser";
+
+
+    protected ArrayList parserClasses;
+    protected String classNamesLocation;
+
+    protected ArrayList serializerClasses;
+
+
+    // features are kept there
+    protected HashMap features = new HashMap();
+
+
+    /**
+     * Protected constructor to be called by factory implementations.
+     */
+
+    protected XmlPullParserFactory() {
+    }
+
+
+
+    /**
+     * Set the features to be set when XML Pull Parser is created by this factory.
+     * <p><b>NOTE:</b> factory features are not used for XML Serializer.
+     *
+     * @param name string with URI identifying feature
+     * @param state if true feature will be set; if false will be ignored
+     */
+
+    public void setFeature(String name,
+                           boolean state) throws XmlPullParserException {
+
+        features.put(name, new Boolean(state));
+    }
+
+
+    /**
+     * Return the current value of the feature with given name.
+     * <p><b>NOTE:</b> factory features are not used for XML Serializer.
+     *
+     * @param name The name of feature to be retrieved.
+     * @return The value of named feature.
+     *     Unknown features are <string>always</strong> returned as false
+     */
+
+    public boolean getFeature (String name) {
+        Boolean value = (Boolean) features.get(name);
+        return value != null ? value.booleanValue() : false;
+    }
+
+    /**
+     * Specifies that the parser produced by this factory will provide
+     * support for XML namespaces.
+     * By default the value of this is set to false.
+     *
+     * @param awareness true if the parser produced by this code
+     *    will provide support for XML namespaces;  false otherwise.
+     */
+
+    public void setNamespaceAware(boolean awareness) {
+        features.put (XmlPullParser.FEATURE_PROCESS_NAMESPACES, new Boolean (awareness));
+    }
+
+    /**
+     * Indicates whether or not the factory is configured to produce
+     * parsers which are namespace aware
+     * (it simply set feature XmlPullParser.FEATURE_PROCESS_NAMESPACES to true or false).
+     *
+     * @return  true if the factory is configured to produce parsers
+     *    which are namespace aware; false otherwise.
+     */
+
+    public boolean isNamespaceAware() {
+        return getFeature (XmlPullParser.FEATURE_PROCESS_NAMESPACES);
+    }
+
+
+    /**
+     * Specifies that the parser produced by this factory will be validating
+     * (it simply set feature XmlPullParser.FEATURE_VALIDATION to true or false).
+     *
+     * By default the value of this is set to false.
+     *
+     * @param validating - if true the parsers created by this factory  must be validating.
+     */
+
+    public void setValidating(boolean validating) {
+        features.put (XmlPullParser.FEATURE_VALIDATION, new Boolean (validating));
+    }
+
+    /**
+     * Indicates whether or not the factory is configured to produce parsers
+     * which validate the XML content during parse.
+     *
+     * @return   true if the factory is configured to produce parsers
+     * which validate the XML content during parse; false otherwise.
+     */
+
+    public boolean isValidating() {
+        return getFeature (XmlPullParser.FEATURE_VALIDATION);
+    }
+
+    /**
+     * Creates a new instance of a XML Pull Parser
+     * using the currently configured factory features.
+     *
+     * @return A new instance of a XML Pull Parser.
+     * @throws XmlPullParserException if a parser cannot be created which satisfies the
+     * requested configuration.
+     */
+
+    public XmlPullParser newPullParser() throws XmlPullParserException {
+
+        if (parserClasses == null) throw new XmlPullParserException
+                ("Factory initialization was incomplete - has not tried "+classNamesLocation);
+
+        if (parserClasses.size() == 0) throw new XmlPullParserException
+                ("No valid parser classes found in "+classNamesLocation);
+
+        final StringBuffer issues = new StringBuffer ();
+
+        for (int i = 0; i < parserClasses.size(); i++) {
+            final Class ppClass = (Class) parserClasses.get(i);
+            try {
+                final XmlPullParser pp = (XmlPullParser) ppClass.newInstance();
+
+                for (Iterator iter = features.keySet().iterator(); iter.hasNext(); ) {
+                    final String key = (String) iter.next();
+                    final Boolean value = (Boolean) features.get(key);
+                    if(value != null && value.booleanValue()) {
+                        pp.setFeature(key, true);
+                    }
+                }
+                return pp;
+
+            } catch(Exception ex) {
+                issues.append (ppClass.getName () + ": "+ ex.toString ()+"; ");
+            }
+        }
+
+        throw new XmlPullParserException ("could not create parser: "+issues);
+    }
+
+
+    /**
+     * Creates a new instance of a XML Serializer.
+     *
+     * <p><b>NOTE:</b> factory features are not used for XML Serializer.
+     *
+     * @return A new instance of a XML Serializer.
+     * @throws XmlPullParserException if a parser cannot be created which satisfies the
+     * requested configuration.
+     */
+
+    public XmlSerializer newSerializer() throws XmlPullParserException {
+
+        if (serializerClasses == null) {
+            throw new XmlPullParserException
+                ("Factory initialization incomplete - has not tried "+classNamesLocation);
+        }
+        if(serializerClasses.size() == 0) {
+            throw new XmlPullParserException
+                ("No valid serializer classes found in "+classNamesLocation);
+        }
+
+        final StringBuffer issues = new StringBuffer ();
+
+        for (int i = 0; i < serializerClasses.size (); i++) {
+            final Class ppClass = (Class) serializerClasses.get(i);
+            try {
+                final XmlSerializer ser = (XmlSerializer) ppClass.newInstance();
+
+                return ser;
+
+            } catch(Exception ex) {
+                issues.append (ppClass.getName () + ": "+ ex.toString ()+"; ");
+            }
+        }
+
+        throw new XmlPullParserException ("could not create serializer: "+issues);
+    }
+
+    /**
+     * Create a new instance of a PullParserFactory that can be used
+     * to create XML pull parsers (see class description for more
+     * details).
+     *
+     * @return a new instance of a PullParserFactory, as returned by newInstance (null, null); 
+     */
+    public static XmlPullParserFactory newInstance () throws XmlPullParserException {
+        return newInstance(null, null);
+    }
+
+    public static XmlPullParserFactory newInstance (String classNames, Class context)
+        throws XmlPullParserException {
+
+        if (context == null) {
+            //NOTE: make sure context uses the same class loader as API classes
+            //      this is the best we can do without having access to context classloader in J2ME
+            //      if API is in the same classloader as implementation then this will work
+            context = referenceContextClass;
+        }
+
+        /*
+        String  classNamesLocation = null;
+
+        if (classNames == null || classNames.length() == 0 || "DEFAULT".equals(classNames)) {
+            try {
+                InputStream is = context.getResourceAsStream (RESOURCE_NAME);
+
+                if (is == null) throw new XmlPullParserException
+                        ("resource not found: "+RESOURCE_NAME
+                             +" make sure that parser implementing XmlPull API is available");
+                final StringBuffer sb = new StringBuffer();
+
+                while (true) {
+                    final int ch = is.read();
+                    if (ch < 0) break;
+                    else if (ch > ' ')
+                        sb.append((char) ch);
+                }
+                is.close ();
+
+                classNames = sb.toString ();
+            }
+            catch (Exception e) {
+                throw new XmlPullParserException (null, null, e);
+            }
+            classNamesLocation = "resource "+RESOURCE_NAME+" that contained '"+classNames+"'";
+        } else {
+            classNamesLocation =
+                "parameter classNames to newInstance() that contained '"+classNames+"'";
+        }
+        */
+        classNames = "org.kxml2.io.KXmlParser,org.kxml2.io.KXmlSerializer";
+
+        XmlPullParserFactory factory = null;
+        final ArrayList parserClasses = new ArrayList();
+        final ArrayList serializerClasses = new ArrayList();
+        int pos = 0;
+
+        while (pos < classNames.length ()) {
+            int cut = classNames.indexOf (',', pos);
+
+            if (cut == -1) cut = classNames.length ();
+            final String name = classNames.substring (pos, cut);
+
+            Class candidate = null;
+            Object instance = null;
+
+            try {
+                candidate = Class.forName (name);
+                // necessary because of J2ME .class issue
+                instance = candidate.newInstance ();
+            }
+            catch (Exception e) {}
+
+            if (candidate != null) {
+                boolean recognized = false;
+                if (instance instanceof XmlPullParser) {
+                    parserClasses.add(candidate);
+                    recognized = true;
+                }
+                if (instance instanceof XmlSerializer) {
+                    serializerClasses.add(candidate);
+                    recognized = true;
+                }
+                if (instance instanceof XmlPullParserFactory) {
+                    if (factory == null) {
+                        factory = (XmlPullParserFactory) instance;
+                    }
+                    recognized = true;
+                }
+                if (!recognized) {
+                    throw new XmlPullParserException ("incompatible class: "+name);
+                }
+            }
+            pos = cut + 1;
+        }
+
+        if (factory == null) {
+            factory = new XmlPullParserFactory ();
+        }
+        factory.parserClasses = parserClasses;
+        factory.serializerClasses = serializerClasses;
+        factory.classNamesLocation = "org.kxml2.io.kXmlParser,org.kxml2.io.KXmlSerializer";
+        return factory;
+    }
+}
+
+
diff --git a/xml/src/main/java/org/xmlpull/v1/XmlSerializer.java b/xml/src/main/java/org/xmlpull/v1/XmlSerializer.java
new file mode 100644
index 0000000..8e85e2f
--- /dev/null
+++ b/xml/src/main/java/org/xmlpull/v1/XmlSerializer.java
@@ -0,0 +1,326 @@
+package org.xmlpull.v1;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+
+/**
+ * Define an interface to serialziation of XML Infoset.
+ * This interface abstracts away if serialized XML is XML 1.0 comaptible text or
+ * other formats of XML 1.0 serializations (such as binary XML for example with WBXML).
+ *
+ * <p><b>PLEASE NOTE:</b> This interface will be part of XmlPull 1.2 API.
+ * It is included as basis for discussion. It may change in any way.
+ *
+ * <p>Exceptions that may be thrown are: IOException or runtime exception
+ * (more runtime exceptions can be thrown but are not declared and as such
+ * have no semantics defined for this interface):
+ * <ul>
+ * <li><em>IllegalArgumentException</em> - for almost all methods to signal that
+ *     argument is illegal
+ * <li><em>IllegalStateException</em> - to signal that call has good arguments but
+ *     is not expected here (violation of contract) and for features/properties
+ *    when requesting setting unimplemented feature/property
+ *    (UnsupportedOperationException would be better but it is not in MIDP)
+ *  </ul>
+ *
+ * <p><b>NOTE:</b> writing  CDSECT, ENTITY_REF, IGNORABLE_WHITESPACE,
+ *  PROCESSING_INSTRUCTION, COMMENT, and DOCDECL in some implementations
+ * may not be supported (for example when serializing to WBXML).
+ * In such case IllegalStateException will be thrown and it is recommened
+ * to use an optional feature to signal that implementation is not
+ * supporting this kind of output.
+ */
+
+public interface XmlSerializer {
+    
+    /**
+     * Set feature identified by name (recommended to be URI for uniqueness).
+     * Some well known optional features are defined in
+     * <a href="http://www.xmlpull.org/v1/doc/features.html">
+     * http://www.xmlpull.org/v1/doc/features.html</a>.
+     *
+     * If feature is not recocgnized or can not be set
+     * then IllegalStateException MUST be thrown.
+     *
+     * @exception IllegalStateException If the feature is not supported or can not be set
+     */
+    void setFeature(String name,
+                           boolean state)
+        throws IllegalArgumentException, IllegalStateException;
+    
+    
+    /**
+     * Return the current value of the feature with given name.
+     * <p><strong>NOTE:</strong> unknown properties are <strong>always</strong> returned as null
+     *
+     * @param name The name of feature to be retrieved.
+     * @return The value of named feature.
+     * @exception IllegalArgumentException if feature string is null
+     */
+    boolean getFeature(String name);
+    
+    
+    /**
+     * Set the value of a property.
+     * (the property name is recommened to be URI for uniqueness).
+     * Some well known optional properties are defined in
+     * <a href="http://www.xmlpull.org/v1/doc/properties.html">
+     * http://www.xmlpull.org/v1/doc/properties.html</a>.
+     *
+     * If property is not recocgnized or can not be set
+     * then IllegalStateException MUST be thrown.
+     *
+     * @exception IllegalStateException if the property is not supported or can not be set
+     */
+    void setProperty(String name,
+                            Object value)
+        throws IllegalArgumentException, IllegalStateException;
+    
+    /**
+     * Look up the value of a property.
+     *
+     * The property name is any fully-qualified URI. I
+     * <p><strong>NOTE:</strong> unknown properties are <string>always</strong> returned as null
+     *
+     * @param name The name of property to be retrieved.
+     * @return The value of named property.
+     */
+    Object getProperty(String name);
+    
+    /**
+     * Set to use binary output stream with given encoding.
+     */
+    void setOutput (OutputStream os, String encoding)
+        throws IOException, IllegalArgumentException, IllegalStateException;
+    
+    /**
+     * Set the output to the given writer.
+     * <p><b>WARNING</b> no information about encoding is available!
+     */
+    void setOutput (Writer writer)
+        throws IOException, IllegalArgumentException, IllegalStateException;
+    
+    /**
+     * Write &lt;&#63;xml declaration with encoding (if encoding not null)
+     * and standalone flag (if standalone not null)
+     * This method can only be called just after setOutput.
+     */
+    void startDocument (String encoding, Boolean standalone)
+        throws IOException, IllegalArgumentException, IllegalStateException;
+    
+    /**
+     * Finish writing. All unclosed start tags will be closed and output
+     * will be flushed. After calling this method no more output can be
+     * serialized until next call to setOutput()
+     */
+    void endDocument ()
+        throws IOException, IllegalArgumentException, IllegalStateException;
+    
+    /**
+     * Binds the given prefix to the given namespace.
+     * This call is valid for the next element including child elements.
+     * The prefix and namespace MUST be always declared even if prefix
+     * is not used in element (startTag() or attribute()) - for XML 1.0
+     * it must result in declaring <code>xmlns:prefix='namespace'</code>
+     * (or <code>xmlns:prefix="namespace"</code> depending what character is used
+     * to quote attribute value).
+     *
+     * <p><b>NOTE:</b> this method MUST be called directly before startTag()
+     *   and if anything but startTag() or setPrefix() is called next there will be exception.
+     * <p><b>NOTE:</b> prefixes "xml" and "xmlns" are already bound
+     *   and can not be redefined see:
+     * <a href="http://www.w3.org/XML/xml-names-19990114-errata#NE05">Namespaces in XML Errata</a>.
+     * <p><b>NOTE:</b> to set default namespace use as prefix empty string.
+     *
+     * @param prefix must be not null (or IllegalArgumentException is thrown)
+     * @param namespace must be not null
+     */
+    void setPrefix (String prefix, String namespace)
+        throws IOException, IllegalArgumentException, IllegalStateException;
+    
+    /**
+     * Return namespace that corresponds to given prefix
+     * If there is no prefix bound to this namespace return null
+     * but if generatePrefix is false then return generated prefix.
+     *
+     * <p><b>NOTE:</b> if the prefix is empty string "" and defualt namespace is bound
+     * to this prefix then empty string ("") is returned.
+     *
+     * <p><b>NOTE:</b> prefixes "xml" and "xmlns" are already bound
+     *   will have values as defined
+     * <a href="http://www.w3.org/TR/REC-xml-names/">Namespaces in XML specification</a>
+     */
+    String getPrefix (String namespace, boolean generatePrefix)
+        throws IllegalArgumentException;
+    
+    /**
+     * Returns the current depth of the element.
+     * Outside the root element, the depth is 0. The
+     * depth is incremented by 1 when startTag() is called.
+     * The depth is decremented after the call to endTag()
+     * event was observed.
+     *
+     * <pre>
+     * &lt;!-- outside --&gt;     0
+     * &lt;root&gt;               1
+     *   sometext                 1
+     *     &lt;foobar&gt;         2
+     *     &lt;/foobar&gt;        2
+     * &lt;/root&gt;              1
+     * &lt;!-- outside --&gt;     0
+     * </pre>
+     */
+    int getDepth();
+    
+    /**
+     * Returns the namespace URI of the current element as set by startTag().
+     *
+     * <p><b>NOTE:</b> that measn in particaulr that: <ul>
+     * <li>if there was startTag("", ...) then getNamespace() returns ""
+     * <li>if there was startTag(null, ...) then getNamespace() returns null
+     * </ul>
+     *
+     * @return namespace set by startTag() that is currently in scope
+     */
+    String getNamespace ();
+    
+    /**
+     * Returns the name of the current element as set by startTag().
+     * It can only be null before first call to startTag()
+     * or when last endTag() is called to close first startTag().
+     *
+     * @return namespace set by startTag() that is currently in scope
+     */
+    String getName();
+    
+    /**
+     * Writes a start tag with the given namespace and name.
+     * If there is no prefix defined for the given namespace,
+     * a prefix will be defined automatically.
+     * The explicit prefixes for namespaces can be established by calling setPrefix()
+     * immediately before this method.
+     * If namespace is null no namespace prefix is printed but just name.
+     * If namespace is empty string then serialzier will make sure that
+     * default empty namespace is declared (in XML 1.0 xmlns='')
+     * or throw IllegalStateException if default namespace is already bound
+     * to non-empty string.
+     */
+    XmlSerializer startTag (String namespace, String name)
+        throws IOException, IllegalArgumentException, IllegalStateException;
+    
+    /**
+     * Write an attribute. Calls to attribute() MUST follow a call to
+     * startTag() immediately. If there is no prefix defined for the
+     * given namespace, a prefix will be defined automatically.
+     * If namespace is null or empty string
+     * no namespace prefix is printed but just name.
+     */
+    XmlSerializer attribute (String namespace, String name, String value)
+        throws IOException, IllegalArgumentException, IllegalStateException;
+    
+    /**
+     * Write end tag. Repetition of namespace and name is just for avoiding errors.
+     * <p><b>Background:</b> in kXML endTag had no arguments, and non matching tags were
+     *  very difficult to find...
+     * If namespace is null no namespace prefix is printed but just name.
+     * If namespace is empty string then serialzier will make sure that
+     * default empty namespace is declared (in XML 1.0 xmlns='').
+     */
+    XmlSerializer endTag (String namespace, String name)
+        throws IOException, IllegalArgumentException, IllegalStateException;
+    
+    
+    //    /**
+    //     * Writes a start tag with the given namespace and name.
+    //     * <br />If there is no prefix defined (prefix == null) for the given namespace,
+    //     * a prefix will be defined automatically.
+    //     * <br />If explicit prefixes is passed (prefix != null) then it will be used
+    //      *and namespace declared if not already declared or
+    //     * throw IllegalStateException the same prefix was already set on this
+    //     * element (setPrefix()) and was bound to different namespace.
+    //     * <br />If namespace is null then prefix must be null too or IllegalStateException is thrown.
+    //     * <br />If namespace is null then no namespace prefix is printed but just name.
+    //     * <br />If namespace is empty string then serializer will make sure that
+    //     * default empty namespace is declared (in XML 1.0 xmlns='')
+    //     * or throw IllegalStateException if default namespace is already bound
+    //     * to non-empty string.
+    //     */
+    //    XmlSerializer startTag (String prefix, String namespace, String name)
+    //        throws IOException, IllegalArgumentException, IllegalStateException;
+    //
+    //    /**
+    //     * Write an attribute. Calls to attribute() MUST follow a call to
+    //     * startTag() immediately.
+    //     * <br />If there is no prefix defined (prefix == null) for the given namespace,
+    //     * a prefix will be defined automatically.
+    //     * <br />If explicit prefixes is passed (prefix != null) then it will be used
+    //     * and namespace declared if not already declared or
+    //     * throw IllegalStateException the same prefix was already set on this
+    //     * element (setPrefix()) and was bound to different namespace.
+    //     * <br />If namespace is null then prefix must be null too or IllegalStateException is thrown.
+    //     * <br />If namespace is null then no namespace prefix is printed but just name.
+    //     * <br />If namespace is empty string then serializer will make sure that
+    //     * default empty namespace is declared (in XML 1.0 xmlns='')
+    //     * or throw IllegalStateException if default namespace is already bound
+    //     * to non-empty string.
+    //     */
+    //    XmlSerializer attribute (String prefix, String namespace, String name, String value)
+    //        throws IOException, IllegalArgumentException, IllegalStateException;
+    //
+    //    /**
+    //     * Write end tag. Repetition of namespace, prefix, and name is just for avoiding errors.
+    //     * <br />If namespace or name arguments are different from corresponding startTag call
+    //     * then IllegalArgumentException is thrown, if prefix argument is not null and is different
+    //     * from corresponding starTag then IllegalArgumentException is thrown.
+    //     * <br />If namespace is null then prefix must be null too or IllegalStateException is thrown.
+    //     * <br />If namespace is null then no namespace prefix is printed but just name.
+    //     * <br />If namespace is empty string then serializer will make sure that
+    //     * default empty namespace is declared (in XML 1.0 xmlns='').
+    //     * <p><b>Background:</b> in kXML endTag had no arguments, and non matching tags were
+    //     *  very difficult to find...</p>
+    //     */
+    // ALEK: This is really optional as prefix in end tag MUST correspond to start tag but good for error checking
+    //    XmlSerializer endTag (String prefix, String namespace, String name)
+    //        throws IOException, IllegalArgumentException, IllegalStateException;
+    
+    /**
+     * Writes text, where special XML chars are escaped automatically
+     */
+    XmlSerializer text (String text)
+        throws IOException, IllegalArgumentException, IllegalStateException;
+    
+    /**
+     * Writes text, where special XML chars are escaped automatically
+     */
+    XmlSerializer text (char [] buf, int start, int len)
+        throws IOException, IllegalArgumentException, IllegalStateException;
+    
+    void cdsect (String text)
+        throws IOException, IllegalArgumentException, IllegalStateException;
+    void entityRef (String text)  throws IOException,
+        IllegalArgumentException, IllegalStateException;
+    void processingInstruction (String text)
+        throws IOException, IllegalArgumentException, IllegalStateException;
+    void comment (String text)
+        throws IOException, IllegalArgumentException, IllegalStateException;
+    void docdecl (String text)
+        throws IOException, IllegalArgumentException, IllegalStateException;
+    void ignorableWhitespace (String text)
+        throws IOException, IllegalArgumentException, IllegalStateException;
+    
+    /**
+     * Write all pending output to the stream.
+     * If method startTag() or attribute() was called then start tag is closed (final &gt;)
+     * before flush() is called on underlying output stream.
+     *
+     * <p><b>NOTE:</b> if there is need to close start tag
+     * (so no more attribute() calls are allowed) but without flushinging output
+     * call method text() with empty string (text("")).
+     *
+     */
+    void flush ()
+        throws IOException;
+    
+}
+
diff --git a/xml/src/main/java/org/xmlpull/v1/sax2/Driver.java b/xml/src/main/java/org/xmlpull/v1/sax2/Driver.java
new file mode 100644
index 0000000..0bd2d4f
--- /dev/null
+++ b/xml/src/main/java/org/xmlpull/v1/sax2/Driver.java
@@ -0,0 +1,469 @@
+/* -*-             c-basic-offset: 4; indent-tabs-mode: nil; -*-  //------100-columns-wide------>|*/
+// for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/)
+
+package org.xmlpull.v1.sax2;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.Reader;
+
+// not J2ME classes -- remove if you want to run in MIDP devices
+import java.net.URL;
+import java.net.MalformedURLException;
+
+
+// not J2ME classes
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
+/**
+ * SAX2 Driver that pulls events from XmlPullParser
+ * and comverts them into SAX2 callbacks.
+ *
+ * @author <a href="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a>
+ */
+
+public class Driver implements Locator, XMLReader, Attributes
+{
+
+    protected static final String DECLARATION_HANDLER_PROPERTY =
+        "http://xml.org/sax/properties/declaration-handler";
+
+    protected static final String LEXICAL_HANDLER_PROPERTY =
+        "http://xml.org/sax/properties/lexical-handler";
+
+    protected static final String NAMESPACES_FEATURE =
+        "http://xml.org/sax/features/namespaces";
+
+    protected static final String NAMESPACE_PREFIXES_FEATURE =
+        "http://xml.org/sax/features/namespace-prefixes";
+
+    protected static final String VALIDATION_FEATURE =
+        "http://xml.org/sax/features/validation";
+
+    protected static final String APACHE_SCHEMA_VALIDATION_FEATURE =
+        "http://apache.org/xml/features/validation/schema";
+
+    protected static final String APACHE_DYNAMIC_VALIDATION_FEATURE =
+        "http://apache.org/xml/features/validation/dynamic";
+
+    protected ContentHandler contentHandler = new DefaultHandler();
+    protected ErrorHandler errorHandler = new DefaultHandler();;
+
+    protected String systemId;
+
+    protected XmlPullParser pp;
+
+    //private final static boolean DEBUG = false;
+
+    /**
+     */
+    public Driver() throws XmlPullParserException {
+        final XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
+        factory.setNamespaceAware(true);
+        pp = factory.newPullParser();
+    }
+
+    public Driver(XmlPullParser pp) throws XmlPullParserException {
+        this.pp = pp;
+    }
+
+    // -- Attributes interface
+
+    public int getLength() { return pp.getAttributeCount(); }
+    public String getURI(int index) { return pp.getAttributeNamespace(index); }
+    public String getLocalName(int index) { return pp.getAttributeName(index); }
+    public String getQName(int index) {
+        final String prefix = pp.getAttributePrefix(index);
+        if(prefix != null) {
+            return prefix+':'+pp.getAttributeName(index);
+        } else {
+            return pp.getAttributeName(index);
+        }
+    }
+    public String getType(int index) { return pp.getAttributeType(index); }
+    public String getValue(int index) { return pp.getAttributeValue(index); }
+
+    public int getIndex(String uri, String localName) {
+        for (int i = 0; i < pp.getAttributeCount(); i++)
+        {
+            if(pp.getAttributeNamespace(i).equals(uri)
+               && pp.getAttributeName(i).equals(localName))
+            {
+                return i;
+            }
+
+        }
+        return -1;
+    }
+
+    public int getIndex(String qName) {
+        for (int i = 0; i < pp.getAttributeCount(); i++)
+        {
+            if(pp.getAttributeName(i).equals(qName))
+            {
+                return i;
+            }
+
+        }
+        return -1;
+    }
+
+    public String getType(String uri, String localName) {
+        for (int i = 0; i < pp.getAttributeCount(); i++)
+        {
+            if(pp.getAttributeNamespace(i).equals(uri)
+               && pp.getAttributeName(i).equals(localName))
+            {
+                return pp.getAttributeType(i);
+            }
+
+        }
+        return null;
+    }
+    public String getType(String qName) {
+        for (int i = 0; i < pp.getAttributeCount(); i++)
+        {
+            if(pp.getAttributeName(i).equals(qName))
+            {
+                return pp.getAttributeType(i);
+            }
+
+        }
+        return null;
+    }
+    public String getValue(String uri, String localName) {
+        return pp.getAttributeValue(uri, localName);
+    }
+    public String getValue(String qName) {
+        return pp.getAttributeValue(null, qName);
+    }
+
+    // -- Locator interface
+
+    public String getPublicId() { return null; }
+    public String getSystemId() { return systemId; }
+    public int getLineNumber() { return pp.getLineNumber(); }
+    public int getColumnNumber() { return pp.getColumnNumber(); }
+
+    // --- XMLReader interface
+
+    public boolean getFeature(String name)
+        throws SAXNotRecognizedException, SAXNotSupportedException
+    {
+        if(NAMESPACES_FEATURE.equals(name)) {
+            return pp.getFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES);
+        } else if(NAMESPACE_PREFIXES_FEATURE.equals(name)) {
+            return pp.getFeature(XmlPullParser.FEATURE_REPORT_NAMESPACE_ATTRIBUTES);
+        } else if(VALIDATION_FEATURE.equals(name)) {
+            return pp.getFeature(XmlPullParser.FEATURE_VALIDATION);
+            //        } else if(APACHE_SCHEMA_VALIDATION_FEATURE.equals(name)) {
+            //            return false;  //TODO
+            //        } else if(APACHE_DYNAMIC_VALIDATION_FEATURE.equals(name)) {
+            //            return false; //TODO
+        } else {
+            return pp.getFeature(name);
+            //throw new SAXNotRecognizedException("unrecognized feature "+name);
+        }
+    }
+
+    public void setFeature (String name, boolean value)
+        throws SAXNotRecognizedException, SAXNotSupportedException
+    {
+        try {
+            if(NAMESPACES_FEATURE.equals(name)) {
+                pp.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, value);
+            } else if(NAMESPACE_PREFIXES_FEATURE.equals(name)) {
+                if(pp.getFeature(XmlPullParser.FEATURE_REPORT_NAMESPACE_ATTRIBUTES) != value) {
+                    pp.setFeature(XmlPullParser.FEATURE_REPORT_NAMESPACE_ATTRIBUTES, value);
+                }
+            } else if(VALIDATION_FEATURE.equals(name)) {
+                pp.setFeature(XmlPullParser.FEATURE_VALIDATION, value);
+                //          } else if(APACHE_SCHEMA_VALIDATION_FEATURE.equals(name)) {
+                //              // can ignore as validation must be false ...
+                //              //              if(true == value) {
+                //              //                  throw new SAXNotSupportedException("schema validation is not supported");
+                //              //              }
+                //          } else if(APACHE_DYNAMIC_VALIDATION_FEATURE.equals(name)) {
+                //              if(true == value) {
+                //                  throw new SAXNotSupportedException("dynamic validation is not supported");
+                //              }
+            } else {
+                pp.setFeature(name, value);
+                //throw new SAXNotRecognizedException("unrecognized feature "+name);
+            }
+        } catch(XmlPullParserException ex) {
+           // throw new SAXNotSupportedException("problem with setting feature "+name+": "+ex);
+        }
+    }
+
+    public Object getProperty (String name)
+        throws SAXNotRecognizedException, SAXNotSupportedException
+    {
+        if(DECLARATION_HANDLER_PROPERTY.equals(name)) {
+            return null;
+        } else if(LEXICAL_HANDLER_PROPERTY.equals(name)) {
+            return null;
+        } else {
+            return pp.getProperty(name);
+            //throw new SAXNotRecognizedException("not recognized get property "+name);
+        }
+    }
+
+    public void setProperty (String name, Object value)
+        throws SAXNotRecognizedException, SAXNotSupportedException
+    {
+        //
+        if(DECLARATION_HANDLER_PROPERTY.equals(name)) {
+            throw new SAXNotSupportedException("not supported setting property "+name);//+" to "+value);
+        } else if(LEXICAL_HANDLER_PROPERTY.equals(name)) {
+            throw new SAXNotSupportedException("not supported setting property "+name);//+" to "+value);
+        } else {
+            try {
+                pp.setProperty(name, value);
+            } catch(XmlPullParserException ex) {
+                throw new SAXNotSupportedException("not supported set property "+name+": "+ ex);
+            }
+            //throw new SAXNotRecognizedException("not recognized set property "+name);
+        }
+    }
+
+    public void setEntityResolver (EntityResolver resolver) {}
+
+    public EntityResolver getEntityResolver () { return null; }
+
+    public void setDTDHandler (DTDHandler handler) {}
+
+    public DTDHandler getDTDHandler () { return null; }
+
+    public void setContentHandler (ContentHandler handler)
+    {
+        this.contentHandler = handler;
+    }
+
+    public ContentHandler getContentHandler() { return contentHandler; }
+
+    public void setErrorHandler(ErrorHandler handler) {
+        this.errorHandler = handler;
+    }
+
+    public ErrorHandler getErrorHandler() { return errorHandler; }
+
+    public void parse(InputSource source) throws SAXException, IOException
+    {
+
+        systemId = source.getSystemId();
+        contentHandler.setDocumentLocator(this);
+
+        final Reader reader = source.getCharacterStream();
+        try {
+            if (reader == null) {
+                InputStream stream = source.getByteStream();
+                final String encoding = source.getEncoding();
+
+                if (stream == null) {
+                    systemId = source.getSystemId();
+                    if(systemId == null) {
+                        SAXParseException saxException = new SAXParseException(
+                            "null source systemId" , this);
+                        errorHandler.fatalError(saxException);
+                        return;
+                    }
+                    // NOTE: replace with Connection to run in J2ME environment
+                    try {
+                        final URL url = new URL(systemId);
+                        stream = url.openStream();
+                    } catch (MalformedURLException nue) {
+                        try {
+                            stream = new FileInputStream(systemId);
+                        } catch (FileNotFoundException fnfe) {
+                            final SAXParseException saxException = new SAXParseException(
+                                "could not open file with systemId "+systemId, this, fnfe);
+                            errorHandler.fatalError(saxException);
+                            return;
+                        }
+                    }
+                }
+                pp.setInput(stream, encoding);
+            } else {
+                pp.setInput(reader);
+            }
+        } catch (XmlPullParserException ex)  {
+            final SAXParseException saxException = new SAXParseException(
+                "parsing initialization error: "+ex, this, ex);
+            //if(DEBUG) ex.printStackTrace();
+            errorHandler.fatalError(saxException);
+            return;
+        }
+
+        // start parsing - move to first start tag
+        try {
+            contentHandler.startDocument();
+            // get first event
+            pp.next();
+            // it should be start tag...
+            if(pp.getEventType() != XmlPullParser.START_TAG) {
+                final SAXParseException saxException = new SAXParseException(
+                    "expected start tag not"+pp.getPositionDescription(), this);
+                //throw saxException;
+                errorHandler.fatalError(saxException);
+                return;
+            }
+        } catch (XmlPullParserException ex)  {
+            final SAXParseException saxException = new SAXParseException(
+                "parsing initialization error: "+ex, this, ex);
+            //ex.printStackTrace();
+            errorHandler.fatalError(saxException);
+            return;
+        }
+
+        // now real parsing can start!
+
+        parseSubTree(pp);
+
+        // and finished ...
+
+        contentHandler.endDocument();
+    }
+
+    public void parse(String systemId) throws SAXException, IOException {
+        parse(new InputSource(systemId));
+    }
+
+
+    public void parseSubTree(XmlPullParser pp) throws SAXException, IOException {
+        this.pp = pp;
+        final boolean namespaceAware = pp.getFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES);
+        try {
+            if(pp.getEventType() != XmlPullParser.START_TAG) {
+                throw new SAXException(
+                    "start tag must be read before skiping subtree"+pp.getPositionDescription());
+            }
+            final int[] holderForStartAndLength = new int[2];
+            final StringBuffer rawName = new StringBuffer(16);
+            String prefix = null;
+            String name = null;
+            int level = pp.getDepth() - 1;
+            int type = XmlPullParser.START_TAG;
+
+            LOOP:
+            do {
+                switch(type) {
+                    case XmlPullParser.START_TAG:
+                        if(namespaceAware) {
+                            final int depth = pp.getDepth() - 1;
+                            final int countPrev =
+                                (level > depth) ? pp.getNamespaceCount(depth) : 0;
+                            //int countPrev = pp.getNamespaceCount(pp.getDepth() - 1);
+                            final int count = pp.getNamespaceCount(depth + 1);
+                            for (int i = countPrev; i < count; i++)
+                            {
+                                contentHandler.startPrefixMapping(
+                                    pp.getNamespacePrefix(i),
+                                    pp.getNamespaceUri(i)
+                                );
+                            }
+                            name = pp.getName();
+                            prefix = pp.getPrefix();
+                            if(prefix != null) {
+                                rawName.setLength(0);
+                                rawName.append(prefix);
+                                rawName.append(':');
+                                rawName.append(name);
+                            }
+                            startElement(pp.getNamespace(),
+                                         name,
+                                         // TODO Fixed this. Was "not equals".
+                                         prefix == null ? name : rawName.toString());
+                        } else {
+                            startElement(pp.getNamespace(),
+                                         pp.getName(),
+                                         pp.getName());
+                        }
+                        //++level;
+
+                        break;
+                    case XmlPullParser.TEXT:
+                        final char[] chars = pp.getTextCharacters(holderForStartAndLength);
+                        contentHandler.characters(chars,
+                                                  holderForStartAndLength[0], //start
+                                                  holderForStartAndLength[1] //len
+                                                 );
+                        break;
+                    case XmlPullParser.END_TAG:
+                        //--level;
+                        if(namespaceAware) {
+                            name = pp.getName();
+                            prefix = pp.getPrefix();
+                            if(prefix != null) {
+                                rawName.setLength(0);
+                                rawName.append(prefix);
+                                rawName.append(':');
+                                rawName.append(name);
+                            }
+                            contentHandler.endElement(pp.getNamespace(),
+                                                      name,
+                                                      prefix != null ? name : rawName.toString()
+                                                     );
+                            // when entering show prefixes for all levels!!!!
+                            final int depth = pp.getDepth();
+                            final int countPrev =
+                                (level > depth) ? pp.getNamespaceCount(pp.getDepth()) : 0;
+                            int count = pp.getNamespaceCount(pp.getDepth() - 1);
+                            // undeclare them in reverse order
+                            for (int i = count - 1; i >= countPrev; i--)
+                            {
+                                contentHandler.endPrefixMapping(
+                                    pp.getNamespacePrefix(i)
+                                );
+                            }
+                        } else {
+                            contentHandler.endElement(pp.getNamespace(),
+                                                      pp.getName(),
+                                                      pp.getName()
+                                                     );
+
+                        }
+                        break;
+                    case XmlPullParser.END_DOCUMENT:
+                        break LOOP;
+                }
+                type = pp.next();
+            } while(pp.getDepth() > level);
+        } catch (XmlPullParserException ex)  {
+            final SAXParseException saxException = new SAXParseException("parsing error: "+ex, this, ex);
+            ex.printStackTrace();
+            errorHandler.fatalError(saxException);
+        }
+    }
+
+    /**
+     * Calls {@link ContentHandler#startElement(String, String, String, Attributes) startElement}
+     * on the <code>ContentHandler</code> with <code>this</code> driver object as the
+     * {@link Attributes} implementation. In default implementation
+     * {@link Attributes} object is valid only during this method call and may not
+     * be stored. Sub-classes can overwrite this method to cache attributes.
+     */
+    protected void startElement(String namespace, String localName, String qName) throws SAXException {
+        contentHandler.startElement(namespace, localName, qName, this);
+    }
+
+}
diff --git a/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp b/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
new file mode 100644
index 0000000..7149272
--- /dev/null
+++ b/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
@@ -0,0 +1,1530 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "ExpatParser"
+
+#include "jni.h"
+#include "utils/Log.h"
+#include "JNIHelp.h"
+
+#include <string.h>
+#include <utils/misc.h>
+#include <expat.h>
+#include <cutils/jstring.h>
+
+#define BUCKET_COUNT 128
+
+/**
+ * Wrapper around an interned string.
+ */
+typedef struct {
+
+    /** The interned string itself. */
+    jstring interned;
+
+    /** UTF-8 equivalent of the interned string. */
+    const char* bytes;
+
+    /** Hash code of the interned string. */
+    int hash;    
+} InternedString;
+
+/**
+ * Keeps track of strings between start and end events.
+ */
+typedef struct {
+
+    jstring* array;
+    int capacity;
+    int size;
+} StringStack;
+
+/**
+ * Data passed to parser handler method by the parser.
+ */
+typedef struct {
+
+    /**
+     * The JNI environment for the current thread. This should only be used
+     * to keep a reference to the env for use in Expat callbacks.
+     */
+    JNIEnv* env;
+
+    /** The Java parser object. */
+    jobject object;
+
+    /** Buffer for text events. */
+    jcharArray buffer;
+
+    /** The size of our buffer in jchars. */
+    int bufferSize;
+
+    /** Current attributes. */
+    const char** attributes;
+
+    /** Number of attributes. */
+    int attributeCount;
+
+    /** True if namespace support is enabled. */
+    bool processNamespaces;
+
+    /** Keep track of names. */
+    StringStack stringStack;
+
+    /** Cache of interned strings. */
+    InternedString** internedStrings[BUCKET_COUNT];
+} ParsingContext;
+
+static jmethodID startElementMethod;
+static jmethodID endElementMethod;
+static jmethodID textMethod;
+static jmethodID commentMethod;
+static jmethodID startCdataMethod;
+static jmethodID endCdataMethod;
+static jmethodID startDtdMethod;
+static jmethodID endDtdMethod;
+static jmethodID startNamespaceMethod;
+static jmethodID endNamespaceMethod;
+static jmethodID processingInstructionMethod;
+static jmethodID handleExternalEntityMethod;
+static jmethodID internMethod;
+static jclass stringClass;
+static jstring emptyString;
+
+/**
+ * Throws a NullPointerException.
+ *
+ * @param msg exception message
+ */
+static void throw_NullPointerException(JNIEnv* env, const char* msg) {
+    jniThrowException(env, "java/lang/NullPointerException", msg);
+}
+
+/**
+ * Throw a NullPointerException.
+ */
+static void throw_OutOfMemoryError(JNIEnv* env) {
+    jniThrowException(env, "java/lang/OutOfMemoryError", "Out of memory.");
+}
+
+/**
+ * Calculates a hash code for a null-terminated string. This is *not* equivalent
+ * to Java's String.hashCode(). This hashes the bytes while String.hashCode()
+ * hashes UTF-16 chars.
+ *
+ * @param s null-terminated string to hash
+ * @returns hash code
+ */
+static int hashString(const char* s) {
+    int hash = 0;
+    if (s) {
+        while (*s) {
+            hash = hash * 31 + *s++;
+        }
+    }
+    return hash;
+}
+
+/**
+ * Creates a new interned string wrapper. Looks up the interned string
+ * representing the given UTF-8 bytes.
+ *
+ * @param bytes null-terminated string to intern
+ * @param hash of bytes
+ * @returns wrapper of interned Java string
+ */
+static InternedString* newInternedString(JNIEnv* env,
+        ParsingContext* parsingContext, const char* bytes, int hash) {
+    // Allocate a new wrapper.
+    InternedString* wrapper
+        = (InternedString* ) malloc(sizeof(InternedString));
+    if (wrapper == NULL) {
+        throw_OutOfMemoryError(env);
+        return NULL;
+    }
+
+    // Create a copy of the UTF-8 bytes.
+    // TODO: sometimes we already know the length. Reuse it if so.
+    char* copy = strdup(bytes);
+    wrapper->bytes = copy;
+    if (wrapper->bytes == NULL) {
+        throw_OutOfMemoryError(env);
+        free(wrapper);
+        return NULL;
+    }
+
+    // Save the hash.
+    wrapper->hash = hash;
+
+    // To intern a string, we must first create a new string and then call
+    // intern() on it. We then keep a global reference to the interned string.
+    jstring newString = env->NewStringUTF(bytes);
+    if (env->ExceptionCheck()) {
+        free(copy);
+        free(wrapper);
+        return NULL;
+    }
+
+    // Call intern().
+    jstring interned =
+        (jstring) env->CallObjectMethod(newString, internMethod);
+    if (env->ExceptionCheck()) {
+        free(copy);
+        free(wrapper);
+        return NULL;
+    }
+
+    // Create a global reference to the interned string.
+    wrapper->interned = (jstring) env->NewGlobalRef(interned);
+    if (env->ExceptionCheck()) {
+        free(copy);
+        free(wrapper);
+        return NULL;
+    }
+
+    env->DeleteLocalRef(interned);
+    env->DeleteLocalRef(newString);
+
+    return wrapper;
+}
+
+/**
+ * Allocates a new bucket with one entry.
+ *
+ * @param entry to store in the bucket
+ * @returns a reference to the bucket
+ */
+static InternedString** newInternedStringBucket(InternedString* entry) {
+    InternedString** bucket
+        = (InternedString**) malloc(sizeof(InternedString*) * 2);
+    if (bucket == NULL) return NULL;
+
+    bucket[0] = entry;
+    bucket[1] = NULL;
+    return bucket;
+}
+
+/**
+ * Expands an interned string bucket and adds the given entry. Frees the
+ * provided bucket and returns a new one.
+ *
+ * @param existingBucket the bucket to replace
+ * @param entry to add to the bucket
+ * @returns a reference to the newly-allocated bucket containing the given entry
+ */
+static InternedString** expandInternedStringBucket(
+        InternedString** existingBucket, InternedString* entry) {
+    // Determine the size of the existing bucket.
+    int size = 0;
+    while (existingBucket[size]) size++;
+
+    // Allocate the new bucket with enough space for one more entry and
+    // a null terminator.
+    InternedString** newBucket = (InternedString**) realloc(existingBucket,
+            sizeof(InternedString*) * (size + 2));
+    if (newBucket == NULL) return NULL;
+
+    newBucket[size] = entry;
+    newBucket[size + 1] = NULL;
+
+    return newBucket;
+}
+
+/**
+ * Returns an interned string for the given UTF-8 string.
+ *
+ * @param bucket to search for s
+ * @param s null-terminated string to find
+ * @param hash of s
+ * @returns interned Java string equivalent of s or null if not found
+ */
+static jstring findInternedString(InternedString** bucket, const char* s,
+        int hash) {
+    InternedString* current;
+    while ((current = *(bucket++)) != NULL) {
+        if (current->hash != hash) continue;
+        if (!strcmp(s, current->bytes)) return current->interned;
+    }
+    return NULL;
+}
+
+/**
+ * Returns an interned string for the given UTF-8 string.
+ *
+ * @param s null-terminated string to intern
+ * @returns interned Java string equivelent of s or NULL if s is null
+ */
+static jstring internString(JNIEnv* env, ParsingContext* parsingContext,
+        const char* s) {
+    if (s == NULL) return NULL;
+
+    int hash = hashString(s);
+    int bucketIndex = hash & (BUCKET_COUNT - 1);
+
+    InternedString*** buckets = parsingContext->internedStrings;
+    InternedString** bucket = buckets[bucketIndex];
+    InternedString* internedString;
+
+    if (bucket) {
+        // We have a bucket already. Look for the given string.
+        jstring found = findInternedString(bucket, s, hash);
+        if (found) {
+            // We found it!
+            return found;
+        }
+
+        // We didn't find it. :(
+        // Create a new entry.
+        internedString = newInternedString(env, parsingContext, s, hash);
+        if (internedString == NULL) return NULL;
+
+        // Expand the bucket.
+        bucket = expandInternedStringBucket(bucket, internedString);
+        if (bucket == NULL) {
+            throw_OutOfMemoryError(env);
+            return NULL;
+        }
+
+        buckets[bucketIndex] = bucket;
+
+        return internedString->interned;
+    } else {
+        // We don't even have a bucket yet. Create an entry.
+        internedString = newInternedString(env, parsingContext, s, hash);
+        if (internedString == NULL) return NULL;
+
+        // Create a new bucket with one entry.
+        bucket = newInternedStringBucket(internedString);
+        if (bucket == NULL) {
+            throw_OutOfMemoryError(env);
+            return NULL;
+        }
+
+        buckets[bucketIndex] = bucket;
+
+        return internedString->interned;
+    }
+}
+
+/**
+ * Returns an interned string for the given UTF-8 string.
+ *
+ * @param s string to intern
+ * @param length of s
+ * @returns interned Java string equivelent of s
+ */
+static jstring internStringOfLength(JNIEnv* env, ParsingContext* parsingContext,
+        const char* s, int length) {
+    // Create a null-terminated version.
+    char nullTerminated[length + 1];
+    memcpy(nullTerminated, s, length);
+    nullTerminated[length] = 0;
+
+    return internString(env, parsingContext, nullTerminated);
+}
+
+/**
+ * Throw an assertion error.
+ *
+ * @param message to show
+ */
+static void fail(JNIEnv* env, const char* message) {
+    jclass clazz;
+    clazz = env->FindClass("java/lang/AssertionError");
+    env->ThrowNew(clazz, message);
+}
+
+/**
+ * Allocates a new parsing context.
+ *
+ * @param jobject the Java ExpatParser instance
+ * @returns a newly-allocated ParsingContext
+ */
+ParsingContext* newParsingContext(JNIEnv* env, jobject object) {
+    ParsingContext* result = (ParsingContext*) malloc(sizeof(ParsingContext));
+    if (result == NULL) {
+        throw_OutOfMemoryError(env);
+        return NULL;
+    }
+
+    result->env = NULL;
+    result->buffer = NULL;
+    result->bufferSize = -1;
+    result->object = object;
+
+    int stackSize = 10;
+    result->stringStack.capacity = stackSize;
+    result->stringStack.size = 0;
+    result->stringStack.array
+            = (jstring*) malloc(stackSize * sizeof(jstring));
+
+    for (int i = 0; i < BUCKET_COUNT; i++) {
+        result->internedStrings[i] = NULL;
+    }
+
+    return result;
+}
+
+/**
+ * Frees the char[] buffer if it exists.
+ */
+static void freeBuffer(JNIEnv* env, ParsingContext* parsingContext) {
+    if (parsingContext->buffer != NULL) {
+        env->DeleteGlobalRef(parsingContext->buffer);
+        parsingContext->buffer = NULL;
+        parsingContext->bufferSize = -1;
+    }
+}
+
+/**
+ * Ensures our buffer is big enough.
+ *
+ * @param length in jchars
+ * @returns a reference to the buffer
+ */
+static jcharArray ensureCapacity(ParsingContext* parsingContext, int length) {
+    if (parsingContext->bufferSize < length) {
+        JNIEnv* env = parsingContext->env;
+
+        // Free the existing char[].
+        freeBuffer(env, parsingContext);
+
+        // Allocate a new char[].
+        jcharArray javaBuffer = env->NewCharArray(length);
+        if (javaBuffer == NULL) return NULL;
+
+        // Create a global reference.
+        javaBuffer = (jcharArray) env->NewGlobalRef(javaBuffer);
+        if (javaBuffer == NULL) return NULL;
+
+        parsingContext->buffer = javaBuffer;
+        parsingContext->bufferSize = length;
+    }
+
+    return parsingContext->buffer;
+}
+
+/**
+ * Copies UTF-8 characters into the buffer. Returns the number of Java chars
+ * which were buffered.
+ *
+ * @param characters to copy into the buffer
+ * @param length of characters to copy (in bytes)
+ * @returns number of UTF-16 characters which were copied
+ */
+static size_t fillBuffer(ParsingContext* parsingContext, const char* characters,
+        int length) {
+    JNIEnv* env = parsingContext->env;
+
+    // Grow buffer if necessary.
+    jcharArray buffer = ensureCapacity(parsingContext, length);
+    if (buffer == NULL) return -1;
+
+    // Get a native reference to our buffer.
+    jchar* nativeBuffer = env->GetCharArrayElements(buffer, NULL);
+
+    // Decode UTF-8 characters into our buffer.
+    size_t utf16length;
+    strcpylen8to16((char16_t*) nativeBuffer, characters, length, &utf16length);
+
+    // Release our native reference.
+    env->ReleaseCharArrayElements(buffer, nativeBuffer, 0);
+
+    return utf16length;
+}
+
+/**
+ * Buffers the given text and passes it to the given method.
+ *
+ * @param method to pass the characters and length to with signature
+ *  (char[], int)
+ * @param data parsing context
+ * @param text to copy into the buffer
+ * @param length of text to copy (in bytes)
+ */
+static void bufferAndInvoke(jmethodID method, void* data, const char* text,
+        size_t length) {
+    ParsingContext* parsingContext = (ParsingContext*) data;
+    JNIEnv* env = parsingContext->env;
+
+    // Bail out if a previously called handler threw an exception.
+    if (env->ExceptionCheck()) return;
+
+    // Buffer the element name.
+    size_t utf16length = fillBuffer(parsingContext, text, length);
+
+    // Invoke given method.
+    jobject javaParser = parsingContext->object;
+    jcharArray buffer = parsingContext->buffer;
+    env->CallVoidMethod(javaParser, method, buffer, utf16length);
+}
+
+/**
+ * Finds the '|' in a null-terminated string. Returns -1 if none is found.
+ *
+ * @param s string to search
+ * @returns index of the separator
+ */
+static int findSeparator(const char* s) {
+    char* pointer = strchr(s, '|');
+    return pointer == NULL ? -1 : pointer - s;
+}
+
+/**
+ * Parses the URI out of an Expat element name and turns it into a Java string.
+ * Expat element names follow the format: "uri|localName".
+ *
+ * @param s string to parse from
+ * @param separatorIndex index of separator in s
+ * @returns interned Java string containing the URI
+ */
+static jstring parseUri(JNIEnv* env, ParsingContext* parsingContext, const char* s,
+        int separatorIndex) {
+    return separatorIndex == -1 ? emptyString
+        : internStringOfLength(env, parsingContext, s, separatorIndex);
+}
+
+/**
+ * Parses the local name out of an Expat element name and turns it into a Java
+ * string. Expat element names follow the format: "uri|localName".
+ *
+ * @param s string to parse from
+ * @param separatorIndex index of separator in s
+ * @returns interned Java string containing the local name
+ */
+static jstring parseLocalName(JNIEnv* env, ParsingContext* parsingContext,
+        const char* s, int separatorIndex) {
+    return internString(env, parsingContext, s + separatorIndex + 1);
+}
+
+/**
+ * Pushes a string onto the stack.
+ */
+static void stringStackPush(ParsingContext* parsingContext, jstring s) {
+    StringStack* stringStack = &parsingContext->stringStack;
+
+    // Expand if necessary.
+    if (stringStack->size == stringStack->capacity) {
+        int newCapacity = stringStack->capacity * 2;
+        stringStack->array = (jstring*) realloc(stringStack->array,
+            newCapacity * sizeof(jstring));
+
+        if (stringStack->array == NULL) {
+            throw_OutOfMemoryError(parsingContext->env);
+            return;
+        }
+
+        stringStack->capacity = newCapacity;
+    }
+
+    stringStack->array[stringStack->size++] = s;
+}
+
+/**
+ * Pops a string off the stack.
+ */
+static jstring stringStackPop(ParsingContext* parsingContext) {
+    StringStack* stringStack = &parsingContext->stringStack;
+
+    if (stringStack->size == 0) {
+        return NULL;
+    }
+
+    return stringStack->array[--stringStack->size];
+}
+
+/**
+ * Called by Expat at the start of an element. Delegates to the same method
+ * on the Java parser.
+ *
+ * @param data parsing context
+ * @param elementName "uri|localName" or "localName" for the current element
+ * @param attributes alternating attribute names and values. Like element
+ * names, attribute names follow the format "uri|localName" or "localName".
+ */
+static void startElement(void* data, const char* elementName,
+        const char** attributes) {
+    ParsingContext* parsingContext = (ParsingContext*) data;
+    JNIEnv* env = parsingContext->env;
+
+    // Bail out if a previously called handler threw an exception.
+    if (env->ExceptionCheck()) return;
+
+    // Count the number of attributes.
+    int count = 0;
+    while (attributes[count << 1]) count++;
+
+    // Make the attributes available for the duration of this call.
+    parsingContext->attributes = attributes;
+    parsingContext->attributeCount = count;
+
+    jobject javaParser = parsingContext->object;
+
+    if (parsingContext->processNamespaces) {
+        // Break down Expat's element name into two Java strings.
+        int separatorIndex = findSeparator(elementName);
+        jstring uri = parseUri(
+                env, parsingContext, elementName, separatorIndex);
+        jstring localName = parseLocalName(
+                env, parsingContext, elementName, separatorIndex);
+
+        stringStackPush(parsingContext, uri);
+        stringStackPush(parsingContext, localName);
+
+        env->CallVoidMethod(javaParser, startElementMethod, uri, localName,
+                emptyString, attributes, count);
+    } else {
+        jstring qName = internString(env, parsingContext, elementName);
+
+        stringStackPush(parsingContext, qName);
+
+        env->CallVoidMethod(javaParser, startElementMethod,
+                emptyString, emptyString, qName, attributes, count);
+    }
+
+    parsingContext->attributes = NULL;
+    parsingContext->attributeCount = -1;
+}
+
+/**
+ * Called by Expat at the end of an element. Delegates to the same method
+ * on the Java parser.
+ *
+ * @param data parsing context
+ * @param elementName "uri|localName" or "localName" for the current element
+ */
+static void endElement(void* data, const char* elementName) {
+    ParsingContext* parsingContext = (ParsingContext*) data;
+    JNIEnv* env = parsingContext->env;
+
+    // Bail out if a previously called handler threw an exception.
+    if (env->ExceptionCheck()) return;
+
+    jobject javaParser = parsingContext->object;
+
+    if (parsingContext->processNamespaces) {
+        jstring localName = stringStackPop(parsingContext);
+        jstring uri = stringStackPop(parsingContext);
+
+        env->CallVoidMethod(javaParser, endElementMethod, uri, localName,
+                emptyString);
+    } else {
+        jstring qName = stringStackPop(parsingContext);
+
+        env->CallVoidMethod(javaParser, endElementMethod,
+                emptyString, emptyString, qName);
+    }
+}
+
+/**
+ * Called by Expat when it encounters text. Delegates to the same method
+ * on the Java parser. This may be called mutiple times with incremental pieces
+ * of the same contiguous block of text.
+ *
+ * @param data parsing context
+ * @param characters buffer containing encountered text
+ * @param length number of characters in the buffer
+ */
+static void text(void* data, const char* characters, int length) {
+    bufferAndInvoke(textMethod, data, characters, length);
+}
+
+/**
+ * Called by Expat when it encounters a comment. Delegates to the same method
+ * on the Java parser.
+
+ * @param data parsing context
+ * @param comment 0-terminated
+ */
+static void comment(void* data, const char* comment) {
+    bufferAndInvoke(commentMethod, data, comment, strlen(comment));
+}
+
+/**
+ * Called by Expat at the beginning of a namespace mapping.
+ *
+ * @param data parsing context
+ * @param prefix null-terminated namespace prefix used in the XML
+ * @param uri of the namespace
+ */
+static void startNamespace(void* data, const char* prefix, const char* uri) {
+    ParsingContext* parsingContext = (ParsingContext*) data;
+    JNIEnv* env = parsingContext->env;
+
+    // Bail out if a previously called handler threw an exception.
+    if (env->ExceptionCheck()) return;
+
+    jstring internedPrefix = emptyString;
+    if (prefix != NULL) {
+        internedPrefix = internString(env, parsingContext, prefix);
+        if (env->ExceptionCheck()) return;
+    }
+
+    jstring internedUri = emptyString;
+    if (uri != NULL) {
+        internedUri = internString(env, parsingContext, uri);
+        if (env->ExceptionCheck()) return;
+    }
+
+    stringStackPush(parsingContext, internedPrefix);
+
+    jobject javaParser = parsingContext->object;
+    env->CallVoidMethod(javaParser, startNamespaceMethod, internedPrefix,
+        internedUri);
+}
+
+/**
+ * Called by Expat at the end of a namespace mapping.
+ *
+ * @param data parsing context
+ * @param prefix null-terminated namespace prefix used in the XML
+ */
+static void endNamespace(void* data, const char* prefix) {
+    ParsingContext* parsingContext = (ParsingContext*) data;
+    JNIEnv* env = parsingContext->env;
+
+    // Bail out if a previously called handler threw an exception.
+    if (env->ExceptionCheck()) return;
+
+    jstring internedPrefix = stringStackPop(parsingContext);
+
+    jobject javaParser = parsingContext->object;
+    env->CallVoidMethod(javaParser, endNamespaceMethod, internedPrefix);
+}
+
+/**
+ * Called by Expat at the beginning of a CDATA section.
+ *
+ * @param data parsing context
+ */
+static void startCdata(void* data) {
+    ParsingContext* parsingContext = (ParsingContext*) data;
+    JNIEnv* env = parsingContext->env;
+
+    // Bail out if a previously called handler threw an exception.
+    if (env->ExceptionCheck()) return;
+
+    jobject javaParser = parsingContext->object;
+    env->CallVoidMethod(javaParser, startCdataMethod);
+}
+
+/**
+ * Called by Expat at the end of a CDATA section.
+ *
+ * @param data parsing context
+ */
+static void endCdata(void* data) {
+    ParsingContext* parsingContext = (ParsingContext*) data;
+    JNIEnv* env = parsingContext->env;
+
+    // Bail out if a previously called handler threw an exception.
+    if (env->ExceptionCheck()) return;
+
+    jobject javaParser = parsingContext->object;
+    env->CallVoidMethod(javaParser, endCdataMethod);
+}
+
+/**
+ * Called by Expat at the beginning of a DOCTYPE section.
+ *
+ * @param data parsing context
+ */
+static void startDtd(void* data, const char* name,
+        const char* systemId, const char* publicId, int hasInternalSubset) {
+    ParsingContext* parsingContext = (ParsingContext*) data;
+    JNIEnv* env = parsingContext->env;
+
+    // Bail out if a previously called handler threw an exception.
+    if (env->ExceptionCheck()) return;
+
+    jstring javaName = internString(env, parsingContext, name);
+    if (env->ExceptionCheck()) return;
+
+    jstring javaPublicId = internString(env, parsingContext, publicId);
+    if (env->ExceptionCheck()) return;
+
+    jstring javaSystemId = internString(env, parsingContext, systemId);
+    if (env->ExceptionCheck()) return;
+
+    jobject javaParser = parsingContext->object;
+    env->CallVoidMethod(javaParser, startDtdMethod, javaName, javaPublicId,
+        javaSystemId);
+}
+
+/**
+ * Called by Expat at the end of a DOCTYPE section.
+ *
+ * @param data parsing context
+ */
+static void endDtd(void* data) {
+    ParsingContext* parsingContext = (ParsingContext*) data;
+    JNIEnv* env = parsingContext->env;
+
+    // Bail out if a previously called handler threw an exception.
+    if (env->ExceptionCheck()) return;
+
+    jobject javaParser = parsingContext->object;
+    env->CallVoidMethod(javaParser, endDtdMethod);
+}
+
+/**
+ * Called by Expat when it encounters processing instructions.
+ *
+ * @param data parsing context
+ * @param target of the instruction
+ * @param instructionData
+ */
+static void processingInstruction(void* data, const char* target,
+        const char* instructionData) {
+    ParsingContext* parsingContext = (ParsingContext*) data;
+    JNIEnv* env = parsingContext->env;
+
+    // Bail out if a previously called handler threw an exception.
+    if (env->ExceptionCheck()) return;
+
+    jstring javaTarget = internString(env, parsingContext, target);
+    if (env->ExceptionCheck()) return;
+
+    jstring javaInstructionData = env->NewStringUTF(instructionData);
+    if (env->ExceptionCheck()) return;
+
+    jobject javaParser = parsingContext->object;
+    env->CallVoidMethod(javaParser, processingInstructionMethod, javaTarget,
+        javaInstructionData);
+
+    // We have to temporarily clear an exception before we can release local
+    // references.
+    jthrowable exception = env->ExceptionOccurred();
+    if (exception != NULL) {
+        env->ExceptionClear();
+    }
+
+    env->DeleteLocalRef(javaInstructionData);
+
+    if (exception != NULL) {
+        env->Throw(exception);
+    }
+}
+
+/**
+ * Creates a new entity parser.
+ *
+ * @param object the Java ExpatParser instance
+ * @param parentParser pointer
+ * @param javaEncoding the character encoding name
+ * @param javaContext that was provided to handleExternalEntity
+ * @returns the pointer to the C Expat entity parser
+ */
+static jint createEntityParser(JNIEnv* env, jobject object, jint parentParser,
+        jstring javaEncoding, jstring javaContext) {
+    const char* encoding = env->GetStringUTFChars(javaEncoding, NULL);
+    if (encoding == NULL) {
+        return 0;
+    }
+
+    const char* context = env->GetStringUTFChars(javaContext, NULL);
+    if (context == NULL) {
+        env->ReleaseStringUTFChars(javaEncoding, encoding);
+        return 0;
+    }
+
+    XML_Parser parent = (XML_Parser) parentParser;
+    XML_Parser entityParser
+            = XML_ExternalEntityParserCreate(parent, context, NULL);
+    env->ReleaseStringUTFChars(javaEncoding, encoding);
+    env->ReleaseStringUTFChars(javaContext, context);
+
+    if (entityParser == NULL) {
+        throw_OutOfMemoryError(env);
+    }
+
+    return (jint) entityParser;
+}
+
+/**
+ * Handles external entities. We ignore the "base" URI and keep track of it
+ * ourselves.
+ */
+static int handleExternalEntity(XML_Parser parser, const char* context,
+        const char* ignored, const char* systemId, const char* publicId) {
+    ParsingContext* parsingContext = (ParsingContext*) XML_GetUserData(parser);
+    jobject javaParser = parsingContext->object;
+    JNIEnv* env = parsingContext->env;
+    jobject object = parsingContext->object;
+
+    // Bail out if a previously called handler threw an exception.
+    if (env->ExceptionCheck()) {
+        return XML_STATUS_ERROR;
+    }
+
+    jstring javaSystemId = env->NewStringUTF(systemId);
+    if (env->ExceptionCheck()) {
+        return XML_STATUS_ERROR;
+    }
+    jstring javaPublicId = env->NewStringUTF(publicId);
+    if (env->ExceptionCheck()) {
+        return XML_STATUS_ERROR;
+    }
+    jstring javaContext = env->NewStringUTF(context);
+    if (env->ExceptionCheck()) {
+        return XML_STATUS_ERROR;
+    }
+
+    // Pass the wrapped parser and both strings to java.
+    env->CallVoidMethod(javaParser, handleExternalEntityMethod, javaContext,
+        javaPublicId, javaSystemId);
+
+    /*
+     * Parsing the external entity leaves parsingContext->env and object set to
+     * NULL, so we need to restore both.
+     *
+     * TODO: consider restoring the original env and object instead of setting
+     * them to NULL in the append() functions.
+     */
+    parsingContext->env = env;
+    parsingContext->object = object;
+
+    env->DeleteLocalRef(javaSystemId);
+    env->DeleteLocalRef(javaPublicId);
+    env->DeleteLocalRef(javaContext);
+
+    return env->ExceptionCheck() ? XML_STATUS_ERROR : XML_STATUS_OK;
+}
+
+/**
+ * Releases the parsing context.
+ */
+static void releaseParsingContext(JNIEnv* env, ParsingContext* context) {
+    free(context->stringStack.array);
+
+    freeBuffer(env, context);
+
+    // Free interned string cache.
+    for (int i = 0; i < BUCKET_COUNT; i++) {
+        if (context->internedStrings[i]) {
+            InternedString** bucket = context->internedStrings[i];
+            InternedString* current;
+            while ((current = *(bucket++)) != NULL) {
+                // Free the UTF-8 bytes.
+                free((void*) (current->bytes));
+
+                // Free the interned string reference.
+                env->DeleteGlobalRef(current->interned);
+
+                // Free the bucket.
+                free(current);
+            }
+
+            // Free the buckets.
+            free(context->internedStrings[i]);
+        }
+    }
+
+    free(context);
+}
+
+/**
+ * Creates a new Expat parser. Called from the Java ExpatParser contructor.
+ *
+ * @param object the Java ExpatParser instance
+ * @param javaEncoding the character encoding name
+ * @param processNamespaces true if the parser should handle namespaces
+ * @returns the pointer to the C Expat parser
+ */
+static jint initialize(JNIEnv* env, jobject object, jstring javaEncoding,
+        jboolean processNamespaces) {
+    // Allocate parsing context.
+    ParsingContext* context = newParsingContext(env, object);
+    if (context == NULL) {
+        return 0;
+    }
+
+    context->processNamespaces = (bool) processNamespaces;
+
+    // Create a parser.
+    XML_Parser parser;
+    const char* encoding = env->GetStringUTFChars(javaEncoding, NULL);
+    if (processNamespaces) {
+        // Use '|' to separate URIs from local names.
+        parser = XML_ParserCreateNS(encoding, '|');
+    } else {
+        parser = XML_ParserCreate(encoding);
+    }
+    env->ReleaseStringUTFChars(javaEncoding, encoding);
+
+    if (parser != NULL) {
+        if (processNamespaces) {
+            XML_SetNamespaceDeclHandler(parser, startNamespace, endNamespace);
+        }
+
+        XML_SetCommentHandler(parser, comment);
+        XML_SetCdataSectionHandler(parser, startCdata, endCdata);
+
+        XML_SetElementHandler(parser, startElement, endElement);
+        XML_SetCharacterDataHandler(parser, text);
+        XML_SetDoctypeDeclHandler(parser, startDtd, endDtd);
+        XML_SetProcessingInstructionHandler(parser, processingInstruction);
+        XML_SetExternalEntityRefHandler(parser, handleExternalEntity);
+
+        XML_SetUserData(parser, context);
+    } else {
+        releaseParsingContext(env, context);
+        throw_OutOfMemoryError(env);
+        return 0;
+    }
+
+    return (jint) parser;
+}
+
+/**
+ * Passes some XML to the parser.
+ *
+ * @param object the Java ExpatParser instance
+ * @param pointer to the C expat parser
+ * @param xml Java string containing an XML snippet
+ * @param isFinal whether or not this is the last snippet; enables more error
+ *  checking, i.e. is the document complete?
+ */
+static void appendString(JNIEnv* env, jobject object, jint pointer, jstring xml,
+        jboolean isFinal) {
+    XML_Parser parser = (XML_Parser) pointer;
+    ParsingContext* context = (ParsingContext*) XML_GetUserData(parser);
+    context->env = env;
+    context->object = object;
+
+    int length = env->GetStringLength(xml) << 1; // in bytes
+    const jchar* characters = env->GetStringChars(xml, NULL);
+
+    if (!XML_Parse(parser, (char*) characters, length, isFinal)
+            && !env->ExceptionCheck()) {
+        jclass clazz = env->FindClass("org/apache/harmony/xml/ExpatException");
+        const char* errorMessage = XML_ErrorString(XML_GetErrorCode(parser));
+        env->ThrowNew(clazz, errorMessage);
+    }
+
+    // We have to temporarily clear an exception before we can release local
+    // references.
+    jthrowable exception = env->ExceptionOccurred();
+    if (exception) {
+        env->ExceptionClear();
+        env->ReleaseStringChars(xml, characters);
+        env->Throw(exception);
+    } else {
+        env->ReleaseStringChars(xml, characters);
+    }
+
+    context->object = NULL;
+    context->env = NULL;
+}
+
+/**
+ * Passes some XML to the parser.
+ *
+ * @param object the Java ExpatParser instance
+ * @param pointer to the C expat parser
+ * @param xml Java char[] containing XML
+ * @param offset into the xml buffer
+ * @param length of text in the xml buffer
+ */
+static void appendCharacters(JNIEnv* env, jobject object, jint pointer,
+        jcharArray xml, jint offset, jint length) {
+    XML_Parser parser = (XML_Parser) pointer;
+    ParsingContext* context = (ParsingContext*) XML_GetUserData(parser);
+    context->env = env;
+    context->object = object;
+
+    jchar* characters = env->GetCharArrayElements(xml, NULL);
+
+    if (!XML_Parse(parser, ((char*) characters) + (offset << 1),
+            length << 1, XML_FALSE) && !env->ExceptionCheck()) {
+        jclass clazz = env->FindClass("org/apache/harmony/xml/ExpatException");
+        const char* errorMessage = XML_ErrorString(XML_GetErrorCode(parser));
+        env->ThrowNew(clazz, errorMessage);
+    }
+
+    // We have to temporarily clear an exception before we can release local
+    // references.
+    jthrowable exception = env->ExceptionOccurred();
+    if (exception) {
+        env->ExceptionClear();
+        env->ReleaseCharArrayElements(xml, characters, JNI_ABORT);
+        env->Throw(exception);
+    } else {
+        env->ReleaseCharArrayElements(xml, characters, JNI_ABORT);
+    }
+
+    context->object = NULL;
+    context->env = NULL;
+}
+
+/**
+ * Passes some XML to the parser.
+ *
+ * @param object the Java ExpatParser instance
+ * @param pointer to the C expat parser
+ * @param xml Java byte[] containing XML
+ * @param offset into the xml buffer
+ * @param length of text in the xml buffer
+ */
+static void appendBytes(JNIEnv* env, jobject object, jint pointer,
+        jbyteArray xml, jint offset, jint length) {
+    XML_Parser parser = (XML_Parser) pointer;
+    ParsingContext* context = (ParsingContext*) XML_GetUserData(parser);
+    context->env = env;
+    context->object = object;
+
+    jbyte* bytes = env->GetByteArrayElements(xml, NULL);
+
+    if (!XML_Parse(parser, ((char*) bytes) + offset, length, XML_FALSE)
+            && !env->ExceptionCheck()) {
+        jclass clazz = env->FindClass("org/apache/harmony/xml/ExpatException");
+        const char* errorMessage = XML_ErrorString(XML_GetErrorCode(parser));
+        env->ThrowNew(clazz, errorMessage);
+    }
+
+    // We have to temporarily clear an exception before we can release local
+    // references.
+    jthrowable exception = env->ExceptionOccurred();
+    if (exception) {
+        env->ExceptionClear();
+        env->ReleaseByteArrayElements(xml, bytes, JNI_ABORT);
+        env->Throw(exception);
+    } else {
+        env->ReleaseByteArrayElements(xml, bytes, JNI_ABORT);
+    }
+
+    context->object = NULL;
+    context->env = NULL;
+}
+
+/**
+ * Releases parser only.
+ *
+ * @param object the Java ExpatParser instance
+ * @param i pointer to the C expat parser
+ */
+static void releaseParser(JNIEnv* env, jobject object, jint i) {
+    XML_Parser parser = (XML_Parser) i;
+    XML_ParserFree(parser);
+}
+
+/**
+ * Cleans up after the parser. Called at garbage collection time.
+ *
+ * @param object the Java ExpatParser instance
+ * @param i pointer to the C expat parser
+ */
+static void release(JNIEnv* env, jobject object, jint i) {
+    XML_Parser parser = (XML_Parser) i;
+
+    ParsingContext* context = (ParsingContext*) XML_GetUserData(parser);
+    releaseParsingContext(env, context);
+
+    XML_ParserFree(parser);
+}
+
+/**
+ * Gets the current line.
+ *
+ * @param object the Java ExpatParser instance
+ * @param pointer to the C expat parser
+ * @returns current line number
+ */
+static int line(JNIEnv* env, jobject clazz, jint pointer) {
+    XML_Parser parser = (XML_Parser) pointer;
+    return XML_GetCurrentLineNumber(parser);
+}
+
+/**
+ * Gets the current column.
+ *
+ * @param object the Java ExpatParser instance
+ * @param pointer to the C expat parser
+ * @returns current column number
+ */
+static int column(JNIEnv* env, jobject clazz, jint pointer) {
+    XML_Parser parser = (XML_Parser) pointer;
+    return XML_GetCurrentColumnNumber(parser);
+}
+
+/**
+ * Gets the URI of the attribute at the given index.
+ *
+ * @param object Java ExpatParser instance
+ * @param pointer to the C expat parser
+ * @param attributePointer to the attribute array
+ * @param index of the attribute
+ * @returns interned Java string containing attribute's URI
+ */
+static jstring getAttributeURI(JNIEnv* env, jobject clazz, jint pointer,
+        jint attributePointer, jint index) {
+    XML_Parser parser = (XML_Parser) pointer;
+    ParsingContext* context = (ParsingContext*) XML_GetUserData(parser);
+
+    if (!context->processNamespaces) {
+        return emptyString;
+    }
+
+    const char** attributes = (const char**) attributePointer;
+
+    const char* name = attributes[index << 1];
+    int separatorIndex = findSeparator(name);
+    return parseUri(env, context, name, separatorIndex);
+}
+
+/**
+ * Gets the local name of the attribute at the given index.
+ *
+ * @param object Java ExpatParser instance
+ * @param pointer to the C expat parser
+ * @param attributePointer to the attribute array
+ * @param index of the attribute
+ * @returns interned Java string containing attribute's local name
+ */
+static jstring getAttributeLocalName(JNIEnv* env, jobject clazz, jint pointer,
+        jint attributePointer, jint index) {
+    XML_Parser parser = (XML_Parser) pointer;
+    ParsingContext* context = (ParsingContext*) XML_GetUserData(parser);
+
+    if (!context->processNamespaces) {
+        return emptyString;
+    }
+
+    const char** attributes = (const char**) attributePointer;
+    const char* name = attributes[index << 1];
+
+    int separatorIndex = findSeparator(name);
+    return parseLocalName(env, context, name, separatorIndex);
+}
+
+/**
+ * Gets the qualified name of the attribute at the given index.
+ *
+ * @param object Java ExpatParser instance
+ * @param pointer to the C expat parser
+ * @param attributePointer to the attribute array
+ * @param index of the attribute
+ * @returns interned Java string containing attribute's local name
+ */
+static jstring getAttributeQName(JNIEnv* env, jobject clazz, jint pointer,
+        jint attributePointer, jint index) {
+    XML_Parser parser = (XML_Parser) pointer;
+    ParsingContext* context = (ParsingContext*) XML_GetUserData(parser);
+
+    if (context->processNamespaces) {
+        return emptyString;
+    }
+
+    const char** attributes = (const char**) attributePointer;
+
+    const char* name = attributes[index << 1];
+    return internString(env, context, name);
+}
+
+/**
+ * Gets the value of the attribute at the given index.
+ *
+ * @param object Java ExpatParser instance
+ * @param attributePointer to the attribute array
+ * @param index of the attribute
+ * @returns Java string containing attribute's value
+ */
+static jstring getAttributeValueByIndex(JNIEnv* env, jobject clazz,
+        jint attributePointer, jint index) {
+    const char** attributes = (const char**) attributePointer;
+    const char* value = attributes[(index << 1) + 1];
+    return env->NewStringUTF(value);
+}
+
+/**
+ * Searches the attributes for the given name and returns the attribute's
+ * index or -1 if not found.
+ *
+ * @param attributes alternating name/value pairs
+ * @param name of attribute to look for
+ * @returns index of found attribute or -1 if not found
+ */
+static jint findAttributeByName(const char** attributes,
+        const char* name) {
+    int index;
+    for (index = 0; attributes[index]; index += 2) {
+        if (strcmp(attributes[index], name) == 0)
+            return index >> 1;
+    }
+
+    // Not found.
+    return -1;
+}
+
+/**
+ * Gets the index of the attribute with the given qualified name.
+ *
+ * @param attributePointer to the attribute array
+ * @param qName to look for
+ * @returns index of attribute with the given uri and local name or -1 if not
+ *  found
+ */
+static jint getAttributeIndexForQName(JNIEnv* env, jobject clazz,
+        jint attributePointer, jstring qName) {
+    const char** attributes = (const char**) attributePointer;
+    int length = env->GetStringUTFLength(qName);
+
+    const char* qNameBytes = env->GetStringUTFChars(qName, NULL);
+    if (qNameBytes == NULL) return -1;
+    int found = findAttributeByName(attributes, qNameBytes);
+    env->ReleaseStringUTFChars(qName, qNameBytes);
+    return found;
+}
+
+/**
+ * Gets the index of the attribute with the given URI and name.
+ *
+ * @param attributePointer to the attribute array
+ * @param uri to look for
+ * @param localName to look for
+ * @returns index of attribute with the given uri and local name or -1 if not
+ *  found
+ */
+static jint getAttributeIndex(JNIEnv* env, jobject clazz,
+        jint attributePointer, jstring uri, jstring localName) {
+    const char** attributes = (const char**) attributePointer;
+    int uriLength = env->GetStringUTFLength(uri);
+
+    if (uriLength == 0) {
+        // If there's no URI, then a local name works just like a qName.
+        return getAttributeIndexForQName(
+                env, clazz, attributePointer, localName);
+    }
+
+    int localNameLength = env->GetStringUTFLength(localName);
+
+    // Create string in the same format used by Expat: "uri|localName"
+    char concatenated[uriLength + localNameLength + 2];
+
+    // Append uri.
+    const char* uriBytes = env->GetStringUTFChars(uri, NULL);
+    if (uriBytes == NULL) return -1;
+    strcpy(concatenated, uriBytes);
+    env->ReleaseStringUTFChars(uri, uriBytes);
+
+    // Separarator.
+    concatenated[uriLength] = '|';
+
+    // Append local name.
+    const char* localNameBytes = env->GetStringUTFChars(localName, NULL);
+    if (localNameBytes == NULL) return -1;
+    strcpy(concatenated + uriLength + 1, localNameBytes);
+    env->ReleaseStringUTFChars(localName, localNameBytes);
+
+    return findAttributeByName(attributes, concatenated);
+}
+
+/**
+ * Gets the value of the attribute with the given qualified name.
+ *
+ * @param attributePointer to the attribute array
+ * @param uri to look for
+ * @param localName to look for
+ * @returns value of attribute with the given uri and local name or NULL if not
+ *  found
+ */
+static jstring getAttributeValueForQName(JNIEnv* env, jobject clazz,
+        jint attributePointer, jstring qName) {
+    jint index = getAttributeIndexForQName(
+            env, clazz, attributePointer, qName);
+    return index == -1 ? NULL
+        : getAttributeValueByIndex(env, clazz, attributePointer, index);
+}
+
+/**
+ * Gets the value of the attribute with the given URI and name.
+ *
+ * @param attributePointer to the attribute array
+ * @param uri to look for
+ * @param localName to look for
+ * @returns value of attribute with the given uri and local name or NULL if not
+ *  found
+ */
+static jstring getAttributeValue(JNIEnv* env, jobject clazz,
+        jint attributePointer, jstring uri, jstring localName) {
+    jint index = getAttributeIndex(
+            env, clazz, attributePointer, uri, localName);
+    return index == -1 ? NULL
+        : getAttributeValueByIndex(env, clazz, attributePointer, index);
+}
+
+/**
+ * Clones an array of strings. Uses one contiguous block of memory so as to
+ * maximize performance.
+ */
+static char** cloneStrings(const char** source, int count) {
+    // Figure out how big the buffer needs to be.
+    int arraySize = (count + 1) * sizeof(char*);
+    int totalSize = arraySize;
+    int stringLengths[count];
+    for (int i = 0; i < count; i++) {
+        int length = strlen(source[i]);
+        stringLengths[i] = length;
+        totalSize += length + 1;
+    }
+
+    char* buffer = (char*) malloc(totalSize);
+    if (buffer == NULL) {
+        return NULL;
+    }
+
+    // Array is at the beginning of the buffer.
+    char** clonedArray = (char**) buffer;
+    clonedArray[count] = NULL; // null terminate
+
+    // First string is immediately after.
+    char* destinationString = buffer + arraySize;
+
+    for (int i = 0; i < count; i++) {
+        const char* sourceString = source[i];
+        int stringLength = stringLengths[i];
+        memcpy(destinationString, sourceString, stringLength + 1);
+        clonedArray[i] = destinationString;
+        destinationString += stringLength + 1;
+    }
+
+    return clonedArray;
+}
+
+/**
+ * Clones attributes.
+ *
+ * @param pointer to char** to clone
+ * @param count number of attributes
+ */
+static jint cloneAttributes(JNIEnv* env, jobject clazz,
+        jint pointer, jint count) {
+    return (int) cloneStrings((const char**) pointer, count << 1);
+}
+
+/**
+ * Frees cloned attributes.
+ */
+static void freeAttributes(JNIEnv* env, jobject clazz, jint pointer) {
+    free((void*) pointer);
+}
+
+/**
+ * Called when we initialize our Java parser class.
+ *
+ * @param clazz Java ExpatParser class
+ */
+static void staticInitialize(JNIEnv* env, jobject clazz, jstring empty) {
+    startElementMethod = env->GetMethodID((jclass) clazz, "startElement",
+        "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;II)V");
+    if (startElementMethod == NULL) return;
+    
+    endElementMethod = env->GetMethodID((jclass) clazz, "endElement",
+        "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
+    if (endElementMethod == NULL) return;
+
+    textMethod = env->GetMethodID((jclass) clazz, "text", "([CI)V");
+    if (textMethod == NULL) return;
+
+    commentMethod = env->GetMethodID((jclass) clazz, "comment", "([CI)V");
+    if (commentMethod == NULL) return;
+
+    startCdataMethod = env->GetMethodID((jclass) clazz, "startCdata", "()V");
+    if (startCdataMethod == NULL) return;
+
+    endCdataMethod = env->GetMethodID((jclass) clazz, "endCdata", "()V");
+    if (endCdataMethod == NULL) return;
+
+    startDtdMethod = env->GetMethodID((jclass) clazz, "startDtd",
+        "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
+    if (startDtdMethod == NULL) return;
+
+    endDtdMethod = env->GetMethodID((jclass) clazz, "endDtd", "()V");
+    if (endDtdMethod == NULL) return;
+
+    startNamespaceMethod = env->GetMethodID((jclass) clazz, "startNamespace",
+        "(Ljava/lang/String;Ljava/lang/String;)V");
+    if (startNamespaceMethod == NULL) return;
+
+    endNamespaceMethod = env->GetMethodID((jclass) clazz, "endNamespace",
+        "(Ljava/lang/String;)V");
+    if (endNamespaceMethod == NULL) return;
+
+    processingInstructionMethod = env->GetMethodID((jclass) clazz,
+        "processingInstruction", "(Ljava/lang/String;Ljava/lang/String;)V");
+    if (processingInstructionMethod == NULL) return;
+
+    handleExternalEntityMethod = env->GetMethodID((jclass) clazz,
+        "handleExternalEntity",
+        "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
+    if (handleExternalEntityMethod == NULL) return;
+
+    // Look up String class.
+    stringClass = env->FindClass("java/lang/String");
+
+    internMethod = env->GetMethodID(stringClass, "intern",
+        "()Ljava/lang/String;");
+    if (internMethod == NULL) return;
+
+    // Reference to "".
+    emptyString = (jstring) env->NewGlobalRef(empty);
+}
+
+static JNINativeMethod parserMethods[] = {
+    { "line", "(I)I", (void*) line },
+    { "column", "(I)I", (void*) column },
+    { "release", "(I)V", (void*) release },
+    { "releaseParser", "(I)V", (void*) releaseParser },
+    { "append", "(ILjava/lang/String;Z)V", (void*) appendString },
+    { "append", "(I[CII)V", (void*) appendCharacters },
+    { "append", "(I[BII)V", (void*) appendBytes },
+    { "initialize", "(Ljava/lang/String;Z)I",
+        (void*) initialize},
+    { "createEntityParser", "(ILjava/lang/String;Ljava/lang/String;)I",
+        (void*) createEntityParser},
+    { "staticInitialize", "(Ljava/lang/String;)V", (void*) staticInitialize},
+    { "cloneAttributes", "(II)I", (void*) cloneAttributes },
+};
+
+static JNINativeMethod attributeMethods[] = {
+    { "getURI", "(III)Ljava/lang/String;", (void*) getAttributeURI },
+    { "getLocalName", "(III)Ljava/lang/String;", (void*) getAttributeLocalName },
+    { "getQName", "(III)Ljava/lang/String;", (void*) getAttributeQName },
+    { "getValue", "(II)Ljava/lang/String;", (void*) getAttributeValueByIndex },
+    { "getIndex", "(ILjava/lang/String;Ljava/lang/String;)I",
+        (void*) getAttributeIndex },
+    { "getIndex", "(ILjava/lang/String;)I",
+        (void*) getAttributeIndexForQName },
+    { "getValue", "(ILjava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
+        (void*) getAttributeValue },
+    { "getValue", "(ILjava/lang/String;)Ljava/lang/String;",
+        (void*) getAttributeValueForQName },
+    { "freeAttributes", "(I)V", (void*) freeAttributes },
+};
+
+/**
+ * Called from Register.c.
+ */
+extern "C" int register_org_apache_harmony_xml_ExpatParser(JNIEnv* env) {
+    int result = jniRegisterNativeMethods(env, "org/apache/harmony/xml/ExpatParser",
+        parserMethods, NELEM(parserMethods));
+    if (result != 0) {
+        return result;
+    }
+
+    return jniRegisterNativeMethods(env, "org/apache/harmony/xml/ExpatAttributes",
+        attributeMethods, NELEM(attributeMethods));
+}
diff --git a/xml/src/main/native/sub.mk b/xml/src/main/native/sub.mk
new file mode 100644
index 0000000..e48d12e
--- /dev/null
+++ b/xml/src/main/native/sub.mk
@@ -0,0 +1,20 @@
+# This file is included by the top-level libcore Android.mk.
+# It's not a normal makefile, so we don't include CLEAR_VARS
+# or BUILD_*_LIBRARY.
+
+LOCAL_SRC_FILES := org_apache_harmony_xml_ExpatParser.cpp 
+
+LOCAL_C_INCLUDES += \
+	external/expat/lib
+
+# Any shared/static libs that are listed here must also
+# be listed in libs/nativehelper/Android.mk.
+# TODO: fix this requirement
+
+LOCAL_SHARED_LIBRARIES += \
+	libcutils \
+	libexpat \
+	libutils
+
+#LOCAL_STATIC_LIBRARIES +=
+
diff --git a/xml/src/test/java/org/apache/harmony/xml/ExpatParserTest.java b/xml/src/test/java/org/apache/harmony/xml/ExpatParserTest.java
new file mode 100644
index 0000000..480bca3
--- /dev/null
+++ b/xml/src/test/java/org/apache/harmony/xml/ExpatParserTest.java
@@ -0,0 +1,839 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.harmony.xml;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+import org.kxml2.io.KXmlParser;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ext.DefaultHandler2;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+public class ExpatParserTest extends TestCase {
+
+    private static final String SNIPPET = "<dagny dad=\"bob\">hello</dagny>";
+
+    public void testExceptions() {
+        // From startElement().
+        ContentHandler contentHandler = new DefaultHandler() {
+            @Override
+            public void startElement(String uri, String localName,
+                    String qName, Attributes attributes)
+                    throws SAXException {
+                throw new SAXException();
+            }
+        };
+        try {
+            parse(SNIPPET, contentHandler);
+            fail();
+        } catch (SAXException checked) { /* expected */ }
+
+        // From endElement().
+        contentHandler = new DefaultHandler() {
+            @Override
+            public void endElement(String uri, String localName,
+                    String qName)
+                    throws SAXException {
+                throw new SAXException();
+            }
+        };
+        try {
+            parse(SNIPPET, contentHandler);
+            fail();
+        } catch (SAXException checked) { /* expected */ }
+
+        // From characters().
+        contentHandler = new DefaultHandler() {
+            @Override
+            public void characters(char ch[], int start, int length)
+                    throws SAXException {
+                throw new SAXException();
+            }
+        };
+        try {
+            parse(SNIPPET, contentHandler);
+            fail();
+        } catch (SAXException checked) { /* expected */ }
+    }
+
+    public void testSax() {
+        try {
+            // Parse String.
+            TestHandler handler = new TestHandler();
+            parse(SNIPPET, handler);
+            validate(handler);
+
+            // Parse Reader.
+            handler = new TestHandler();
+            parse(new StringReader(SNIPPET), handler);
+            validate(handler);
+
+            // Parse InputStream.
+            handler = new TestHandler();
+            parse(new ByteArrayInputStream(SNIPPET.getBytes()),
+                    Encoding.UTF_8, handler);
+            validate(handler);
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    static void validate(TestHandler handler) {
+        assertEquals("dagny", handler.startElementName);
+        assertEquals("dagny", handler.endElementName);
+        assertEquals("hello", handler.text.toString());
+    }
+
+    static class TestHandler extends DefaultHandler {
+
+        String startElementName;
+        String endElementName;
+        StringBuilder text = new StringBuilder();
+
+        @Override
+        public void startElement(String uri, String localName, String qName,
+                Attributes attributes) throws SAXException {
+
+            assertNull(this.startElementName);
+            this.startElementName = localName;
+
+            // Validate attributes.
+            assertEquals(1, attributes.getLength());
+            assertEquals("", attributes.getURI(0));
+            assertEquals("dad", attributes.getLocalName(0));
+            assertEquals("bob", attributes.getValue(0));
+            assertEquals(0, attributes.getIndex("", "dad"));
+            assertEquals("bob", attributes.getValue("", "dad"));
+        }
+
+        @Override
+        public void endElement(String uri, String localName, String qName)
+                throws SAXException {
+            assertNull(this.endElementName);
+            this.endElementName = localName;
+        }
+
+        @Override
+        public void characters(char ch[], int start, int length)
+                throws SAXException {
+            this.text.append(ch, start, length);
+        }
+    }
+
+    public void testPullParser() {
+        try {
+            XmlPullParser parser = newPullParser();
+
+            // Test reader.
+            parser.setInput(new StringReader(SNIPPET));
+            validate(parser);
+
+            // Test input stream.
+            parser.setInput(new ByteArrayInputStream(SNIPPET.getBytes()),
+                    "UTF-8");
+            validate(parser);
+        } catch (XmlPullParserException e) {
+            throw new RuntimeException(e);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    static void validate(XmlPullParser parser)
+            throws XmlPullParserException, IOException {
+        assertEquals(XmlPullParser.START_DOCUMENT, parser.getEventType());
+
+        assertEquals(0, parser.getDepth());
+
+        assertEquals(XmlPullParser.START_TAG, parser.next());
+
+        assertEquals(1, parser.getDepth());
+
+        assertEquals("dagny", parser.getName());
+        assertEquals(1, parser.getAttributeCount());
+        assertEquals("dad", parser.getAttributeName(0));
+        assertEquals("bob", parser.getAttributeValue(0));
+        assertEquals("bob", parser.getAttributeValue(null, "dad"));
+
+        assertEquals(XmlPullParser.TEXT, parser.next());
+
+        assertEquals(1, parser.getDepth());
+
+        assertEquals("hello", parser.getText());
+
+        assertEquals(XmlPullParser.END_TAG, parser.next());
+
+        assertEquals(1, parser.getDepth());
+
+        assertEquals("dagny", parser.getName());
+
+        assertEquals(XmlPullParser.END_DOCUMENT, parser.next());
+
+        assertEquals(0, parser.getDepth());
+    }
+
+    static final String XML =
+        "<one xmlns='ns:default' xmlns:n1='ns:1' a='b'>\n"
+              + "  <n1:two c='d' n1:e='f' xmlns:n2='ns:2'>text</n1:two>\n"
+              + "</one>";
+
+    public void testExpatPullParserNamespaces() throws Exception {
+        XmlPullParser pullParser = newPullParser();
+        pullParser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
+        pullParser.setInput(new StringReader(XML));
+        testPullParserNamespaces(pullParser);
+    }
+
+    public void testKxmlPullParserNamespaces() throws Exception {
+        XmlPullParser pullParser = new KXmlParser();
+        pullParser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
+        pullParser.setInput(new StringReader(XML));
+        testPullParserNamespaces(pullParser);
+    }
+
+    private void testPullParserNamespaces(XmlPullParser parser) throws Exception {
+        assertEquals(0, parser.getDepth());
+        assertEquals(0, parser.getNamespaceCount(0));
+
+        try {
+            parser.getNamespaceCount(1);
+            fail();
+        } catch (IndexOutOfBoundsException e) { /* expected */ }
+
+        // one
+        assertEquals(XmlPullParser.START_TAG, parser.next());
+        assertEquals(1, parser.getDepth());
+
+        checkNamespacesInOne(parser);
+
+        // n1:two
+        assertEquals(XmlPullParser.START_TAG, parser.nextTag());
+
+        assertEquals(2, parser.getDepth());
+        checkNamespacesInTwo(parser);
+
+        // Body of two.
+        assertEquals(XmlPullParser.TEXT, parser.next());
+
+        // End of two.
+        assertEquals(XmlPullParser.END_TAG, parser.nextTag());
+
+        // Depth should still be 2.
+        assertEquals(2, parser.getDepth());
+
+        // We should still be able to see the namespaces from two.
+        checkNamespacesInTwo(parser);
+
+        // End of one.
+        assertEquals(XmlPullParser.END_TAG, parser.nextTag());
+
+        // Depth should be back to 1.
+        assertEquals(1, parser.getDepth());
+
+        // We can still see the namespaces in one.
+        checkNamespacesInOne(parser);
+
+        // We shouldn't be able to see the namespaces in two anymore.
+        try {
+            parser.getNamespaceCount(2);
+            fail();
+        } catch (IndexOutOfBoundsException e) { /* expected */ }
+
+        assertEquals(XmlPullParser.END_DOCUMENT, parser.next());
+
+        // We shouldn't be able to see the namespaces in one anymore.
+        try {
+            parser.getNamespaceCount(1);
+            fail();
+        } catch (IndexOutOfBoundsException e) { /* expected */ }
+
+        assertEquals(0, parser.getNamespaceCount(0));
+    }
+
+    private void checkNamespacesInOne(XmlPullParser parser) throws XmlPullParserException {
+        assertEquals(2, parser.getNamespaceCount(1));
+
+        // Prefix for default namespace is null.
+        assertNull(parser.getNamespacePrefix(0));
+        assertEquals("ns:default", parser.getNamespaceUri(0));
+
+        assertEquals("n1", parser.getNamespacePrefix(1));
+        assertEquals("ns:1", parser.getNamespaceUri(1));
+
+        assertEquals("ns:default", parser.getNamespace(null));
+
+        // KXML returns null.
+        // assertEquals("ns:default", parser.getNamespace(""));
+    }
+
+    private void checkNamespacesInTwo(XmlPullParser parser) throws XmlPullParserException {
+        // These should still be valid.
+        checkNamespacesInOne(parser);
+
+        assertEquals(3, parser.getNamespaceCount(2));
+
+        // Default ns should still be in the stack
+        assertNull(parser.getNamespacePrefix(0));
+        assertEquals("ns:default", parser.getNamespaceUri(0));
+    }
+
+    public void testNamespaces() {
+        try {
+            NamespaceHandler handler = new NamespaceHandler();
+            parse(XML, handler);
+            handler.validate();
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    static class NamespaceHandler implements ContentHandler {
+
+        Locator locator;
+        boolean documentStarted;
+        boolean documentEnded;
+        Map<String, String> prefixMappings = new HashMap<String, String>();
+
+        boolean oneStarted;
+        boolean twoStarted;
+        boolean oneEnded;
+        boolean twoEnded;
+
+        public void validate() {
+            assertTrue(documentEnded);
+        }
+
+        public void setDocumentLocator(Locator locator) {
+            this.locator = locator;
+        }
+
+        public void startDocument() throws SAXException {
+            documentStarted = true;
+            assertNotNull(locator);
+            assertEquals(0, prefixMappings.size());
+            assertFalse(documentEnded);
+        }
+
+        public void endDocument() throws SAXException {
+            assertTrue(documentStarted);
+            assertTrue(oneEnded);
+            assertTrue(twoEnded);
+            assertEquals(0, prefixMappings.size());
+            documentEnded = true;
+        }
+
+        public void startPrefixMapping(String prefix, String uri)
+                throws SAXException {
+            prefixMappings.put(prefix, uri);
+        }
+
+        public void endPrefixMapping(String prefix) throws SAXException {
+            assertNotNull(prefixMappings.remove(prefix));
+        }
+
+        public void startElement(String uri, String localName, String qName,
+                Attributes atts) throws SAXException {
+
+            if (localName == "one") {
+                assertEquals(2, prefixMappings.size());
+
+                assertEquals(1, locator.getLineNumber());
+
+                assertFalse(oneStarted);
+                assertFalse(twoStarted);
+                assertFalse(oneEnded);
+                assertFalse(twoEnded);
+
+                oneStarted = true;
+
+                assertSame("ns:default", uri);
+                // TODO The result of the RI is "one"
+                assertEquals("", qName);
+
+                // Check atts.
+                assertEquals(1, atts.getLength());
+
+                assertSame("", atts.getURI(0));
+                assertSame("a", atts.getLocalName(0));
+                assertEquals("b", atts.getValue(0));
+                assertEquals(0, atts.getIndex("", "a"));
+                assertEquals("b", atts.getValue("", "a"));
+
+                return;
+            }
+
+            if (localName == "two") {
+                assertEquals(3, prefixMappings.size());
+
+                assertTrue(oneStarted);
+                assertFalse(twoStarted);
+                assertFalse(oneEnded);
+                assertFalse(twoEnded);
+
+                twoStarted = true;
+
+                assertSame("ns:1", uri);
+                // TODO The result of the RI is "n1:two"
+                Assert.assertEquals("", qName);
+
+                // Check atts.
+                assertEquals(2, atts.getLength());
+
+                assertSame("", atts.getURI(0));
+                assertSame("c", atts.getLocalName(0));
+                assertEquals("d", atts.getValue(0));
+                assertEquals(0, atts.getIndex("", "c"));
+                assertEquals("d", atts.getValue("", "c"));
+
+                assertSame("ns:1", atts.getURI(1));
+                assertSame("e", atts.getLocalName(1));
+                assertEquals("f", atts.getValue(1));
+                assertEquals(1, atts.getIndex("ns:1", "e"));
+                assertEquals("f", atts.getValue("ns:1", "e"));
+
+                // We shouldn't find these.
+                assertEquals(-1, atts.getIndex("ns:default", "e"));
+                assertEquals(null, atts.getValue("ns:default", "e"));
+
+                return;
+            }
+
+            fail();
+         }
+
+        public void endElement(String uri, String localName, String qName)
+                throws SAXException {
+            if (localName == "one") {
+                assertEquals(3, locator.getLineNumber());
+
+                assertTrue(oneStarted);
+                assertTrue(twoStarted);
+                assertTrue(twoEnded);
+                assertFalse(oneEnded);
+
+                oneEnded = true;
+
+                assertSame("ns:default", uri);
+                assertEquals("", qName);
+
+                return;
+            }
+
+            if (localName == "two") {
+                assertTrue(oneStarted);
+                assertTrue(twoStarted);
+                assertFalse(twoEnded);
+                assertFalse(oneEnded);
+
+                twoEnded = true;
+
+                assertSame("ns:1", uri);
+                assertEquals("", qName);
+
+                return;
+            }
+
+            fail();
+        }
+
+        public void characters(char ch[], int start, int length)
+                throws SAXException {
+            String s = new String(ch, start, length).trim();
+
+            if (!s.equals("")) {
+                assertTrue(oneStarted);
+                assertTrue(twoStarted);
+                assertFalse(oneEnded);
+                assertFalse(twoEnded);
+                assertEquals("text", s);
+            }
+        }
+
+        public void ignorableWhitespace(char ch[], int start, int length)
+                throws SAXException {
+            fail();
+        }
+
+        public void processingInstruction(String target, String data)
+                throws SAXException {
+            fail();
+        }
+
+        public void skippedEntity(String name) throws SAXException {
+            fail();
+        }
+    }
+
+    public void testDtd() throws Exception {
+        Reader in = new StringReader(
+            "<?xml version=\"1.0\"?><!DOCTYPE foo PUBLIC 'bar' 'tee'><a></a>");
+        ExpatReader reader = new ExpatReader();
+        TestDtdHandler handler = new TestDtdHandler();
+        reader.setContentHandler(handler);
+        reader.setLexicalHandler(handler);
+        reader.parse(new InputSource(in));
+
+        assertEquals("foo", handler.name);
+        assertEquals("bar", handler.publicId);
+        assertEquals("tee", handler.systemId);
+
+        assertTrue(handler.ended);
+    }
+
+    static class TestDtdHandler extends DefaultHandler2 {
+
+        String name;
+        String publicId;
+        String systemId;
+
+        boolean ended;
+
+        Locator locator;
+
+        @Override
+        public void startDTD(String name, String publicId, String systemId) {
+            this.name = name;
+            this.publicId = publicId;
+            this.systemId = systemId;
+        }
+
+        @Override
+        public void endDTD() {
+            ended = true;
+        }
+
+        @Override
+        public void setDocumentLocator(Locator locator) {
+            this.locator = locator;
+        }
+    }
+
+    public void testCdata() throws Exception {
+        Reader in = new StringReader(
+            "<a><![CDATA[<b></b>]]> <![CDATA[<c></c>]]></a>");
+
+        ExpatReader reader = new ExpatReader();
+        TestCdataHandler handler = new TestCdataHandler();
+        reader.setContentHandler(handler);
+        reader.setLexicalHandler(handler);
+
+        reader.parse(new InputSource(in));
+
+        assertEquals(2, handler.startCdata);
+        assertEquals(2, handler.endCdata);
+        assertEquals("<b></b> <c></c>", handler.buffer.toString());
+    }
+
+    static class TestCdataHandler extends DefaultHandler2 {
+
+        int startCdata, endCdata;
+        StringBuffer buffer = new StringBuffer();
+
+        @Override
+        public void characters(char ch[], int start, int length) {
+            buffer.append(ch, start, length);
+        }
+
+        @Override
+        public void startCDATA() throws SAXException {
+            startCdata++;
+        }
+
+        @Override
+        public void endCDATA() throws SAXException {
+            endCdata++;
+        }
+    }
+
+    public void testProcessingInstructions() throws IOException, SAXException {
+        Reader in = new StringReader(
+            "<?bob lee?><a></a>");
+
+        ExpatReader reader = new ExpatReader();
+        TestProcessingInstrutionHandler handler
+                = new TestProcessingInstrutionHandler();
+        reader.setContentHandler(handler);
+
+        reader.parse(new InputSource(in));
+
+        assertEquals("bob", handler.target);
+        assertEquals("lee", handler.data);
+    }
+
+    static class TestProcessingInstrutionHandler extends DefaultHandler2 {
+
+        String target;
+        String data;
+
+        @Override
+        public void processingInstruction(String target, String data) {
+            this.target = target;
+            this.data = data;
+        }
+    }
+
+    public void testExternalEntity() throws IOException, SAXException {
+        class Handler extends DefaultHandler {
+
+            List<String> elementNames = new ArrayList<String>();
+            StringBuilder text = new StringBuilder();
+
+            public InputSource resolveEntity(String publicId, String systemId)
+                    throws IOException, SAXException {
+                if (publicId.equals("publicA") && systemId.equals("systemA")) {
+                    return new InputSource(new StringReader("<a/>"));
+                } else if (publicId.equals("publicB")
+                        && systemId.equals("systemB")) {
+                    /*
+                     * Explicitly set the encoding here or else the parser will
+                     * try to use the parent parser's encoding which is utf-16.
+                     */
+                    InputSource inputSource = new InputSource(
+                            new ByteArrayInputStream("bob".getBytes("utf-8")));
+                    inputSource.setEncoding("utf-8");
+                    return inputSource;
+                }
+
+                throw new AssertionError();
+            }
+
+            @Override
+            public void startElement(String uri, String localName, String qName,
+                    Attributes attributes) throws SAXException {
+                elementNames.add(localName);
+            }
+
+            @Override
+            public void endElement(String uri, String localName, String qName)
+                    throws SAXException {
+                elementNames.add("/" + localName);
+            }
+
+            @Override
+            public void characters(char ch[], int start, int length)
+                    throws SAXException {
+                text.append(ch, start, length);
+            }
+        }
+
+        Reader in = new StringReader("<?xml version=\"1.0\"?>\n"
+            + "<!DOCTYPE foo [\n"
+            + "  <!ENTITY a PUBLIC 'publicA' 'systemA'>\n"
+            + "  <!ENTITY b PUBLIC 'publicB' 'systemB'>\n"
+            + "]>\n"
+            + "<foo>\n"
+            + "  &a;<b>&b;</b></foo>");
+
+        ExpatReader reader = new ExpatReader();
+        Handler handler = new Handler();
+        reader.setContentHandler(handler);
+        reader.setEntityResolver(handler);
+
+        reader.parse(new InputSource(in));
+
+        assertEquals(Arrays.asList("foo", "a", "/a", "b", "/b", "/foo"),
+                handler.elementNames);
+        assertEquals("bob", handler.text.toString().trim());
+    }
+
+    public void testExternalEntityDownload() throws IOException, SAXException {
+        class Server implements Runnable {
+
+            private final ServerSocket serverSocket;
+
+            Server() throws IOException {
+                serverSocket = new ServerSocket(8080);
+            }
+
+            public void run() {
+                try {
+                    Socket socket = serverSocket.accept();
+
+                    final InputStream in = socket.getInputStream();
+                    Thread inputThread = new Thread() {
+                        public void run() {
+                            try {
+                                byte[] buffer = new byte[1024];
+                                while (in.read(buffer) > -1) { /* ignore */ }
+                            } catch (IOException e) {
+                                e.printStackTrace();
+                            }
+                        }
+                    };
+                    inputThread.setDaemon(true);
+                    inputThread.start();
+
+                    OutputStream out = socket.getOutputStream();
+
+                    String body = "<bar></bar>";
+                    String response = "HTTP/1.0 200 OK\n"
+                        + "Content-Length: " + body.length() + "\n"
+                        + "\n"
+                        + body;
+
+                    out.write(response.getBytes("UTF-8"));
+                    out.close();
+                    serverSocket.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+
+        class Handler extends DefaultHandler {
+
+            List<String> elementNames = new ArrayList<String>();
+
+            public InputSource resolveEntity(String publicId, String systemId)
+                    throws IOException, SAXException {
+                // The parser should have resolved the systemId.
+                assertEquals("http://localhost:8080/systemBar", systemId);
+                return new InputSource(systemId);
+            }
+
+            @Override
+            public void startElement(String uri, String localName, String qName,
+                    Attributes attributes) throws SAXException {
+                elementNames.add(localName);
+            }
+
+            @Override
+            public void endElement(String uri, String localName, String qName)
+                    throws SAXException {
+                elementNames.add("/" + localName);
+            }
+        }
+
+        // Start server to serve up the XML for 'systemBar'.
+        Thread serverThread = new Thread(new Server());
+        serverThread.setDaemon(true);
+        serverThread.start();
+
+        // 'systemBar', the external entity, is relative to 'systemFoo':
+        Reader in = new StringReader("<?xml version=\"1.0\"?>\n"
+            + "<!DOCTYPE foo [\n"
+            + "  <!ENTITY bar SYSTEM 'systemBar'>\n"
+            + "]>\n"
+            + "<foo>&bar;</foo>");
+
+        ExpatReader reader = new ExpatReader();
+
+        Handler handler = new Handler();
+
+        reader.setContentHandler(handler);
+        reader.setEntityResolver(handler);
+
+        InputSource source = new InputSource(in);
+        source.setSystemId("http://localhost:8080/systemFoo");
+        reader.parse(source);
+
+        assertEquals(Arrays.asList("foo", "bar", "/bar", "/foo"),
+                handler.elementNames);
+    }
+
+    /**
+     * Parses the given xml string and fires events on the given SAX handler.
+     */
+    private static void parse(String xml, ContentHandler contentHandler)
+            throws SAXException {
+        try {
+            XMLReader reader = new ExpatReader();
+            reader.setContentHandler(contentHandler);
+            reader.parse(new InputSource(new StringReader(xml)));
+        }
+        catch (IOException e) {
+            throw new AssertionError(e);
+        }
+    }
+
+    /**
+     * Parses xml from the given reader and fires events on the given SAX
+     * handler.
+     */
+    private static void parse(Reader in, ContentHandler contentHandler)
+            throws IOException, SAXException {
+        XMLReader reader = new ExpatReader();
+        reader.setContentHandler(contentHandler);
+        reader.parse(new InputSource(in));
+    }
+
+    /**
+     * Parses xml from the given input stream and fires events on the given SAX
+     * handler.
+     */
+    private static void parse(InputStream in, Encoding encoding,
+            ContentHandler contentHandler) throws IOException, SAXException {
+        try {
+            XMLReader reader = new ExpatReader();
+            reader.setContentHandler(contentHandler);
+            InputSource source = new InputSource(in);
+            source.setEncoding(encoding.expatName);
+            reader.parse(source);
+        } catch (IOException e) {
+            throw new AssertionError(e);
+        }
+    }
+
+    /**
+     * Supported character encodings.
+     */
+    private enum Encoding {
+
+        US_ASCII("US-ASCII"),
+        UTF_8("UTF-8"),
+        UTF_16("UTF-16"),
+        ISO_8859_1("ISO-8859-1");
+
+        final String expatName;
+
+        Encoding(String expatName) {
+            this.expatName = expatName;
+        }
+    }
+
+    /**
+     * Creates a new pull parser with namespace support.
+     */
+    private static XmlPullParser newPullParser() {
+        ExpatPullParser parser = new ExpatPullParser();
+        parser.setNamespaceProcessingEnabled(true);
+        return parser;
+    }
+}
diff --git a/xml/src/test/java/tests/api/javax/xml/parsers/AllTests.java b/xml/src/test/java/tests/api/javax/xml/parsers/AllTests.java
new file mode 100644
index 0000000..f0e8ebd
--- /dev/null
+++ b/xml/src/test/java/tests/api/javax/xml/parsers/AllTests.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.javax.xml.parsers;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.apache.harmony.xml.ExpatParserTest;
+
+/**
+ * This is autogenerated source file. Includes tests for package tests.api.javax.xml.parsers;
+ */
+
+public class AllTests {
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(AllTests.suite());
+    }
+
+    public static Test suite() {
+        TestSuite suite = tests.TestSuiteFactory.createTestSuite("All tests for package tests.api.javax.xml.parsers;");
+        // $JUnit-BEGIN$
+
+        suite.addTestSuite(DocumentBuilderFactoryTest.class);
+        suite.addTestSuite(DocumentBuilderTest.class);
+        suite.addTestSuite(FactoryConfigurationErrorTest.class);
+        suite.addTestSuite(ParserConfigurationExceptionTest.class);
+        suite.addTestSuite(SAXParserFactoryTest.class);       
+        suite.addTestSuite(SAXParserTest.class);
+        suite.addTestSuite(ExpatParserTest.class);
+
+        // $JUnit-END$
+        return suite;
+    }
+}
diff --git a/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderFactoryTest.java b/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderFactoryTest.java
new file mode 100644
index 0000000..1e1ffdd
--- /dev/null
+++ b/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderFactoryTest.java
@@ -0,0 +1,1121 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.javax.xml.parsers;
+
+import dalvik.annotation.KnownFailure;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import junit.framework.TestCase;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import tests.api.javax.xml.parsers.SAXParserFactoryTest.MyHandler;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.FactoryConfigurationError;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+
+@TestTargetClass(DocumentBuilderFactory.class) 
+public class DocumentBuilderFactoryTest extends TestCase {
+
+    DocumentBuilderFactory dbf;
+
+    List<String> cdataElements;
+
+    List<String> textElements;
+
+    List<String> commentElements;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        dbf = DocumentBuilderFactory.newInstance();
+
+        cdataElements = new ArrayList<String>();
+        textElements = new ArrayList<String>();
+        commentElements = new ArrayList<String>();
+    }
+
+    protected void tearDown() throws Exception {
+        dbf = null;
+        cdataElements = null;
+        textElements = null;
+        commentElements = null;
+        super.tearDown();
+    }
+
+    /**
+     * @tests javax.xml.parsers.DocumentBuilderFactory#DocumentBuilderFactory().
+     */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "DocumentBuilderFactory",
+        args = {}
+    )
+    public void test_Constructor() {
+        try {
+            new DocumentBuilderFactoryChild();
+        } catch (Exception e) {
+            fail("Unexpected exception " + e.toString());
+        }
+    }
+
+    /**
+     * @tests javax.xml.parsers.DocumentBuilderFactory#getAttribute(String).
+     */
+//    public void test_getAttributeLjava_lang_String() {
+//        String[] attributes = {
+//                "http://java.sun.com/xml/jaxp/properties/schemaLanguage",
+//                "http://java.sun.com/xml/jaxp/properties/schemaSource" };
+//        Object[] values = { "http://www.w3.org/2001/XMLSchema", "source" };
+//
+//        try {
+//            for (int i = 0; i < attributes.length; i++) {
+//                dbf.setAttribute(attributes[i], values[i]);
+//                assertEquals(values[i], dbf.getAttribute(attributes[i]));
+//            }
+//        } catch (IllegalArgumentException e) {
+//            fail("Unexpected IllegalArgumentException" + e.getMessage());
+//        } catch (Exception e) {
+//            fail("Unexpected exception" + e.getMessage());
+//        }
+//
+//        try {
+//            for (int i = 0; i < attributes.length; i++) {
+//                dbf.setAttribute(null, null);
+//                fail("NullPointerException expected");
+//            }
+//        } catch (NullPointerException e) {
+//            // expected
+//        }
+//
+//        String[] badAttributes = {"bad1", "bad2", ""};
+//        try {
+//            for (int i = 0; i < badAttributes.length; i++) {
+//                dbf.getAttribute(badAttributes[i]);
+//                fail("IllegalArgumentException expected");
+//            }
+//        } catch (IllegalArgumentException e) {
+//            // expected
+//        }
+//    }
+
+    /**
+     * @tests javax.xml.parsers.DocumentBuilderFactory#getFeature(String).
+     */
+// TODO Fails on JDK. Why?    
+//    public void test_getFeatureLjava_lang_String() {
+//        String[] features = { "http://xml.org/sax/features/namespaces",
+//                "http://xml.org/sax/features/validation",
+//                "http://xml.org/sax/features/external-general-entities" };
+//        try {
+//            for (int i = 0; i < features.length; i++) {
+//                dbf.setFeature(features[i], true);
+//                assertTrue(dbf.getFeature(features[i]));
+//            }
+//        } catch (ParserConfigurationException e) {
+//            fail("Unexpected ParserConfigurationException " + e.getMessage());
+//        }
+//
+//        try {
+//            for (int i = 0; i < features.length; i++) {
+//                dbf.setFeature(features[i], false);
+//                assertFalse(dbf.getFeature(features[i]));
+//            }
+//        } catch (ParserConfigurationException e) {
+//            fail("Unexpected ParserConfigurationException " + e.getMessage());
+//        }
+//
+//        try {
+//            for (int i = 0; i < features.length; i++) {
+//                dbf.setFeature(null, false);
+//                fail("NullPointerException expected");
+//            }
+//        } catch (NullPointerException e) {
+//            // expected
+//        } catch (ParserConfigurationException e) {
+//            fail("Unexpected ParserConfigurationException" + e.getMessage());
+//        }
+//
+//        String[] badFeatures = {"bad1", "bad2", ""};
+//        try {
+//            for (int i = 0; i < badFeatures.length; i++) {
+//                dbf.getFeature(badFeatures[i]);
+//                fail("ParserConfigurationException expected");
+//            }
+//        } catch (ParserConfigurationException e) {
+//            // expected
+//        }
+//
+//    }
+
+    /**
+     * @tests javax.xml.parsers.DocumentBuilderFactory#getSchema().
+     *  TBD getSchemas() IS NOT SUPPORTED
+     */
+/*    public void test_getSchema() {
+        assertNull(dbf.getSchema());
+        SchemaFactory sf =
+            SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+        try {
+            Schema schema = sf.newSchema();
+            dbf.setSchema(schema);
+            assertNotNull(dbf.getSchema());
+        } catch (SAXException sax) {
+            fail("Unexpected exception " + sax.toString());
+        }
+    }
+    */
+
+    /**
+     * @tests javax.xml.parsers.DocumentBuilderFactory#isCoalescing().
+     */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "isCoalescing",
+        args = {}
+    )
+    public void test_isCoalescing() {
+        dbf.setCoalescing(true);
+        assertTrue(dbf.isCoalescing());
+
+        dbf.setCoalescing(false);
+        assertFalse(dbf.isCoalescing());
+    }
+
+    /**
+     * @tests javax.xml.parsers.DocumentBuilderFactory#isExpandEntityReferences().
+     */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "isExpandEntityReferences",
+        args = {}
+    )
+    public void test_isExpandEntityReferences() {
+        dbf.setExpandEntityReferences(true);
+        assertTrue(dbf.isExpandEntityReferences());
+
+        dbf.setExpandEntityReferences(false);
+        assertFalse(dbf.isExpandEntityReferences());
+    }
+
+    /**
+     * @tests javax.xml.parsers.DocumentBuilderFactory#isIgnoringComments().
+     */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "isIgnoringComments",
+        args = {}
+    )
+    public void test_isIgnoringComments() {
+        dbf.setIgnoringComments(true);
+        assertTrue(dbf.isIgnoringComments());
+
+        dbf.setIgnoringComments(false);
+        assertFalse(dbf.isIgnoringComments());
+    }
+
+    /**
+     * @tests javax.xml.parsers.DocumentBuilderFactory#isIgnoringElementContentWhitespace().
+     */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "isIgnoringElementContentWhitespace",
+        args = {}
+    )
+    public void test_isIgnoringElementContentWhitespace() {
+        dbf.setIgnoringElementContentWhitespace(true);
+        assertTrue(dbf.isIgnoringElementContentWhitespace());
+
+        dbf.setIgnoringElementContentWhitespace(false);
+        assertFalse(dbf.isIgnoringElementContentWhitespace());
+    }
+
+    /**
+     * @tests javax.xml.parsers.DocumentBuilderFactory#isNamespaceAware().
+     */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "isNamespaceAware",
+        args = {}
+    )
+    public void test_isNamespaceAware() {
+        dbf.setNamespaceAware(true);
+        assertTrue(dbf.isNamespaceAware());
+
+        dbf.setNamespaceAware(false);
+        assertFalse(dbf.isNamespaceAware());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            notes = "",
+            method = "isValidating",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.SUFFICIENT,
+            notes = "",
+            method = "setValidating",
+            args = {boolean.class}
+        )
+    })
+    public void test_setIsValidating() {
+        dbf.setValidating(true);
+        assertTrue(dbf.isValidating());
+
+        dbf.setValidating(false);
+        assertFalse(dbf.isValidating());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            notes = "",
+            method = "isXIncludeAware",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.SUFFICIENT,
+            notes = "",
+            method = "setXIncludeAware",
+            args = {boolean.class}
+        )
+    })
+    @KnownFailure("Should handle XIncludeAware flag more gracefully")
+    public void test_isSetXIncludeAware() {
+        dbf.setXIncludeAware(true);
+        assertTrue(dbf.isXIncludeAware());
+
+        dbf.setXIncludeAware(false);
+        assertFalse(dbf.isXIncludeAware());
+    }
+
+    /**
+     * @tests javax.xml.parsers.DocumentBuilderFactory#newInstance().
+     */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "newInstance",
+        args = {}
+    )
+    public void test_newInstance() {
+        String className = null;
+        try {
+            // case 1: Try to obtain a new instance of factory by default.
+            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+            assertNotNull(dbf);
+
+            // case 2: Try to create a new instance of factory using
+            // property DATATYPEFACTORY_PROPERTY
+            className = System.getProperty("javax.xml.parsers.DocumentBuilderFactory");
+            System.setProperty("javax.xml.parsers.DocumentBuilderFactory",
+                    "org.apache.harmony.xml.parsers.DocumentBuilderFactoryImpl");
+
+            dbf = DocumentBuilderFactory.newInstance();
+            assertNotNull(dbf);
+            assertTrue(dbf instanceof org.apache.harmony.xml.parsers.DocumentBuilderFactoryImpl);
+
+            // case 3: Try to create a new instance of factory using Property
+            String keyValuePair = "javax.xml.parsers.DocumentBuilderFactory"
+                    + "=" + "org.apache.harmony.xml.parsers.DocumentBuilderFactoryImpl";
+            ByteArrayInputStream bis = new ByteArrayInputStream(keyValuePair
+                    .getBytes());
+            Properties prop = System.getProperties();
+            prop.load(bis);
+            dbf = DocumentBuilderFactory.newInstance();
+            assertNotNull(dbf);
+            assertTrue(dbf instanceof org.apache.harmony.xml.parsers.DocumentBuilderFactoryImpl);
+
+            // case 4: Check FactoryConfiguration error
+            System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "");
+            try {
+                DocumentBuilderFactory.newInstance();
+            } catch (FactoryConfigurationError fce) {
+                // expected
+            }
+
+        } catch (Exception e) {
+            fail("Unexpected exception " + e.toString());
+        } finally {
+            // Set default value of Datatype factory,
+            // because of this test modifies it.
+            if (className == null) {
+                System.clearProperty("javax.xml.parsers.DocumentBuilderFactory");
+            } else {
+                System.setProperty("javax.xml.parsers.DocumentBuilderFactory",
+                    className);
+            }
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.SUFFICIENT,
+        notes = "SAXException untested; unused on Android",
+        method = "newDocumentBuilder",
+        args = {}
+    )
+    public void test_newDocumentBuilder() {
+        // Ordinary case
+        try {
+            DocumentBuilder db = dbf.newDocumentBuilder();
+            assertTrue(db instanceof DocumentBuilder);
+            db.parse(getClass().getResourceAsStream("/simple.xml"));
+        } catch(Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        // Exception case
+        dbf.setValidating(true);
+        try {
+            DocumentBuilder db = dbf.newDocumentBuilder();
+        } catch(ParserConfigurationException e) {
+            // Expected, since Android doesn't have a validating parser.
+        }
+    }
+    
+    /**
+     * @tests javax.xml.parsers.DocumentBuilderFactory#setAttribute(java.lang.String,
+     *     java.lang.Object).
+     */
+//    public void test_setAttributeLjava_lang_StringLjava_lang_Object() {
+//        String[] attributes = {
+//                "http://java.sun.com/xml/jaxp/properties/schemaLanguage",
+//                "http://java.sun.com/xml/jaxp/properties/schemaSource" };
+//        Object[] values = { "http://www.w3.org/2001/XMLSchema", "source" };
+//
+//        try {
+//            for (int i = 0; i < attributes.length; i++) {
+//                dbf.setAttribute(attributes[i], values[i]);
+//                assertEquals(values[i], dbf.getAttribute(attributes[i]));
+//            }
+//        } catch (IllegalArgumentException e) {
+//            fail("Unexpected IllegalArgumentException" + e.getMessage());
+//        } catch (Exception e) {
+//            fail("Unexpected exception" + e.getMessage());
+//        }
+//
+//        String[] badAttributes = {"bad1", "bad2", ""};
+//        try {
+//            for (int i = 0; i < badAttributes.length; i++) {
+//                dbf.setAttribute(badAttributes[i], "");
+//                fail("IllegalArgumentException expected");
+//            }
+//        } catch (IllegalArgumentException iae) {
+//            // expected
+//        }
+//
+//        try {
+//            for (int i = 0; i < attributes.length; i++) {
+//                dbf.setAttribute(null, null);
+//                fail("NullPointerException expected");
+//            }
+//        } catch (NullPointerException e) {
+//            // expected
+//        }
+//    }
+
+    /**
+     * @tests javax.xml.parsers.DocumentBuilderFactory#setCoalescing(boolean).
+     */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "setCoalescing",
+        args = {boolean.class}
+    )
+    @KnownFailure("Should support coalescing")
+    public void test_setCoalescingZ() {
+        dbf.setCoalescing(true);
+        assertTrue(dbf.isCoalescing());
+
+        textElements.clear();
+        cdataElements.clear();
+        Exception parseException = null;
+        DocumentBuilder parser = null;
+
+        try {
+            parser = dbf.newDocumentBuilder();
+            ValidationErrorHandler errorHandler = new ValidationErrorHandler();
+            parser.setErrorHandler(errorHandler);
+
+            Document document = parser.parse(getClass().getResourceAsStream(
+                    "/recipt.xml"));
+
+            parseException = errorHandler.getFirstException();
+
+            goThroughDocument((Node) document, "");
+            assertTrue(textElements
+                    .contains("BeefParmesan<title>withGarlicAngelHairPasta</title>"));
+        } catch (Exception ex) {
+            parseException = ex;
+        }
+        parser.setErrorHandler(null);
+
+        if (parseException != null) {
+            fail("Unexpected exception " + parseException.getMessage());
+        }
+
+        dbf.setCoalescing(false);
+        assertFalse(dbf.isCoalescing());
+
+        textElements.clear();
+        cdataElements.clear();
+
+        try {
+            parser = dbf.newDocumentBuilder();
+            ValidationErrorHandler errorHandler = new ValidationErrorHandler();
+            parser.setErrorHandler(errorHandler);
+
+            Document document = parser.parse(getClass().getResourceAsStream(
+                    "/recipt.xml"));
+
+            parseException = errorHandler.getFirstException();
+
+            goThroughDocument((Node) document, "");
+
+            assertFalse(textElements
+                    .contains("BeefParmesan<title>withGarlicAngelHairPasta</title>"));
+
+        } catch (Exception ex) {
+            parseException = ex;
+        }
+        parser.setErrorHandler(null);
+
+        if (parseException != null) {
+            fail("Unexpected exception " + parseException.getMessage());
+        }
+    }
+
+    /**
+     * @tests javax.xml.parsers.DocumentBuilderFactory#setExpandEntityReferences(boolean).
+     */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "setExpandEntityReferences",
+        args = {boolean.class}
+    )
+    public void test_setExpandEntityReferencesZ() {
+        dbf.setExpandEntityReferences(true);
+        assertTrue(dbf.isExpandEntityReferences());
+
+        Exception parseException = null;
+        DocumentBuilder parser = null;
+
+        try {
+            parser = dbf.newDocumentBuilder();
+            ValidationErrorHandler errorHandler = new ValidationErrorHandler();
+            parser.setErrorHandler(errorHandler);
+
+            Document document = parser.parse(getClass().getResourceAsStream(
+                    "/recipt.xml"));
+
+            parseException = errorHandler.getFirstException();
+
+            assertNotNull(document);
+
+        } catch (Exception ex) {
+            parseException = ex;
+        }
+        parser.setErrorHandler(null);
+
+        if (parseException != null) {
+            fail("Unexpected exception " + parseException.getMessage());
+        }
+
+        dbf.setExpandEntityReferences(false);
+        assertFalse(dbf.isExpandEntityReferences());
+        try {
+            parser = dbf.newDocumentBuilder();
+            ValidationErrorHandler errorHandler = new ValidationErrorHandler();
+            parser.setErrorHandler(errorHandler);
+
+            Document document = parser.parse(getClass().getResourceAsStream(
+                    "/recipt.xml"));
+
+            parseException = errorHandler.getFirstException();
+
+            assertNotNull(document);
+
+        } catch (Exception ex) {
+            parseException = ex;
+        }
+        parser.setErrorHandler(null);
+
+        if (parseException != null) {
+            fail("Unexpected exception " + parseException.getMessage());
+        }
+    }
+
+    /**
+     * @tests javax.xml.parsers.DocumentBuilderFactory#setFeature(java.lang.String).
+     */
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            notes = "",
+            method = "getFeature",
+            args = {java.lang.String.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            notes = "",
+            method = "setFeature",
+            args = {java.lang.String.class, boolean.class}
+        )
+    })
+    public void test_getSetFeatureLjava_lang_String() {
+        String[] features = { "http://xml.org/sax/features/namespaces",
+                "http://xml.org/sax/features/validation" };
+        try {
+            for (int i = 0; i < features.length; i++) {
+                dbf.setFeature(features[i], true);
+                assertTrue(dbf.getFeature(features[i]));
+            }
+        } catch (ParserConfigurationException e) {
+            fail("Unexpected ParserConfigurationException" + e.getMessage());
+        }
+
+        try {
+            for (int i = 0; i < features.length; i++) {
+                dbf.setFeature(features[i], false);
+                assertFalse(dbf.getFeature(features[i]));
+            }
+        } catch (ParserConfigurationException e) {
+            fail("Unexpected ParserConfigurationException" + e.getMessage());
+        }
+
+        try {
+            for (int i = 0; i < features.length; i++) {
+                dbf.setFeature(null, false);
+                fail("NullPointerException expected");
+            }
+        } catch (NullPointerException e) {
+            // expected
+        } catch (ParserConfigurationException e) {
+            fail("Unexpected ParserConfigurationException" + e.getMessage());
+        }
+
+        String[] badFeatures = { "bad1", "bad2", "" };
+        try {
+            for (int i = 0; i < badFeatures.length; i++) {
+                dbf.setFeature(badFeatures[i], false);
+                fail("ParserConfigurationException expected");
+            }
+        } catch (ParserConfigurationException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests javax.xml.parsers.DocumentBuilderFactory#setIgnoringComments(boolean).
+     */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "setIgnoringComments",
+        args = {boolean.class}
+    )
+    public void test_setIgnoringCommentsZ() {
+        commentElements.clear();
+
+        dbf.setIgnoringComments(true);
+        assertTrue(dbf.isIgnoringComments());
+
+        try {
+            DocumentBuilder parser = dbf.newDocumentBuilder();
+
+            Document document = parser.parse(getClass().getResourceAsStream(
+                    "/recipt.xml"));
+
+            goThroughDocument((Node) document, "");
+            assertFalse(commentElements.contains("comment1"));
+            assertFalse(commentElements.contains("comment2"));
+
+        } catch (IOException e) {
+            fail("Unexpected IOException " + e.getMessage());
+        } catch (ParserConfigurationException e) {
+            fail("Unexpected ParserConfigurationException " + e.getMessage());
+        } catch (SAXException e) {
+            fail("Unexpected SAXException " + e.getMessage());
+        }
+
+        commentElements.clear();
+
+        dbf.setIgnoringComments(false);
+        assertFalse(dbf.isIgnoringComments());
+
+        try {
+            DocumentBuilder parser = dbf.newDocumentBuilder();
+
+            Document document = parser.parse(getClass().getResourceAsStream(
+                    "/recipt.xml"));
+
+            goThroughDocument((Node) document, "");
+            assertTrue(commentElements.contains("comment1"));
+            assertTrue(commentElements.contains("comment2"));
+
+        } catch (IOException e) {
+            fail("Unexpected IOException " + e.getMessage());
+        } catch (ParserConfigurationException e) {
+            fail("Unexpected ParserConfigurationException " + e.getMessage());
+        } catch (SAXException e) {
+            fail("Unexpected SAXException " + e.getMessage());
+        }
+    }
+
+    /**
+     * @tests javax.xml.parsers.DocumentBuilderFactory#setIgnoringElementContentWhitespace(boolean).
+     */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "setIgnoringElementContentWhitespace",
+        args = {boolean.class}
+    )
+    public void test_setIgnoringElementContentWhitespaceZ() {
+        dbf.setIgnoringElementContentWhitespace(true);
+        assertTrue(dbf.isIgnoringElementContentWhitespace());
+
+        try {
+            DocumentBuilder parser = dbf.newDocumentBuilder();
+
+            Document document = parser.parse(getClass().getResourceAsStream(
+                    "/recipt.xml"));
+
+            assertNotNull(document);
+
+        } catch (IOException e) {
+            fail("Unexpected IOException " + e.getMessage());
+        } catch (ParserConfigurationException e) {
+            fail("Unexpected ParserConfigurationException " + e.getMessage());
+        } catch (SAXException e) {
+            fail("Unexpected SAXException " + e.getMessage());
+        }
+
+        dbf.setIgnoringElementContentWhitespace(false);
+        assertFalse(dbf.isIgnoringElementContentWhitespace());
+
+        try {
+            DocumentBuilder parser = dbf.newDocumentBuilder();
+
+            Document document = parser.parse(getClass().getResourceAsStream(
+                    "/recipt.xml"));
+
+            assertNotNull(document);
+
+        } catch (IOException e) {
+            fail("Unexpected IOException " + e.getMessage());
+        } catch (ParserConfigurationException e) {
+            fail("Unexpected ParserConfigurationException " + e.getMessage());
+        } catch (SAXException e) {
+            fail("Unexpected SAXException " + e.getMessage());
+        }
+    }
+
+    /**
+     * @tests javax.xml.parsers.DocumentBuilderFactory#setNamespaceAware(boolean).
+     */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "setNamespaceAware",
+        args = {boolean.class}
+    )
+    public void test_setNamespaceAwareZ() {
+        dbf.setNamespaceAware(true);
+        assertTrue(dbf.isNamespaceAware());
+
+        try {
+            DocumentBuilder parser = dbf.newDocumentBuilder();
+
+            Document document = parser.parse(getClass().getResourceAsStream(
+                    "/recipt.xml"));
+
+            assertNotNull(document);
+
+        } catch (IOException e) {
+            fail("Unexpected IOException " + e.getMessage());
+        } catch (ParserConfigurationException e) {
+            fail("Unexpected ParserConfigurationException " + e.getMessage());
+        } catch (SAXException e) {
+            fail("Unexpected SAXException " + e.getMessage());
+        }
+
+        dbf.setNamespaceAware(false);
+        assertFalse(dbf.isNamespaceAware());
+
+        try {
+            DocumentBuilder parser = dbf.newDocumentBuilder();
+
+            Document document = parser.parse(getClass().getResourceAsStream(
+                    "/recipt.xml"));
+
+            assertNotNull(document);
+
+        } catch (IOException e) {
+            fail("Unexpected IOException " + e.getMessage());
+        } catch (ParserConfigurationException e) {
+            fail("Unexpected ParserConfigurationException " + e.getMessage());
+        } catch (SAXException e) {
+            fail("Unexpected SAXException " + e.getMessage());
+        }
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            notes = "",
+            method = "getAttribute",
+            args = {java.lang.String.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            notes = "",
+            method = "setAttribute",
+            args = {java.lang.String.class, Object.class}
+        )
+    })
+    public void test_getSetAttribute() {
+        // Android SAX implementation doesn't support attributes, so
+        // we can only make sure the expected exception is thrown.
+        try {
+            dbf.setAttribute("foo", new Object());
+            fail("IllegalArgumentException expected");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+        
+        try {
+            dbf.getAttribute("foo");
+            fail("IllegalArgumentException expected");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+    }
+    
+    /**
+     * @tests javax.xml.parsers.DocumentBuilderFactory#setSchema(javax.xml.validation.Schema).
+     */
+ /*   public void test_setSchemaLjavax_xml_validation_Schema() {
+        SchemaFactory sf =
+            SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+        try {
+            Schema schema = sf.newSchema();
+            dbf.setSchema(schema);
+            assertNotNull(dbf.getSchema());
+        } catch (SAXException sax) {
+            fail("Unexpected exception " + sax.toString());
+        }
+    }
+*/
+    /**
+     * @tests javax.xml.parsers.DocumentBuilderFactory#setValidating(boolean).
+     */
+//    public void test_setValidatingZ() {
+//        Exception parseException = null;
+//        DocumentBuilder parser = null;
+//        Document document = null;
+//
+//        ValidationErrorHandler errorHandler = new ValidationErrorHandler();
+//
+//        dbf.setValidating(false);
+//        assertFalse(dbf.isValidating());
+//
+//        // case 1: Validation is not set. Correct xml-file
+//        try {
+//
+//            parser = dbf.newDocumentBuilder();
+//            parser.setErrorHandler(errorHandler);
+//
+//            document = parser.parse(getClass().getResourceAsStream(
+//                    "/recipt.xml"));
+//
+//            parseException = errorHandler.getFirstException();
+//
+//            assertNotNull(document);
+//
+//            document = parser.parse(getClass().getResourceAsStream(
+//                    "/reciptWrong.xml"));
+//
+//            parseException = errorHandler.getFirstException();
+//
+//            assertNotNull(document);
+//
+//        } catch (Exception ex) {
+//            parseException = ex;
+//        }
+//        parser.setErrorHandler(null);
+//
+//        if (parseException != null) {
+//            fail("Unexpected exception " + parseException.getMessage());
+//        }
+//
+//        // case 2: Validation is not set. Wrong xml-file
+//        try {
+//
+//            parser = dbf.newDocumentBuilder();
+//            parser.setErrorHandler(errorHandler);
+//
+//            document = parser.parse(getClass().getResourceAsStream(
+//                    "/reciptWrong.xml"));
+//            parseException = errorHandler.getFirstException();
+//
+//            assertNotNull(document);
+//
+//        } catch (Exception ex) {
+//            parseException = ex;
+//        }
+//        parser.setErrorHandler(null);
+//
+//        if (parseException != null) {
+//            fail("Unexpected exception " + parseException.getMessage());
+//        }
+//
+//        // case 3: Validation is set. Correct xml-file
+//        dbf.setValidating(true);
+//        assertTrue(dbf.isValidating());
+//
+//        try {
+//
+//            parser = dbf.newDocumentBuilder();
+//            parser.setErrorHandler(errorHandler);
+//
+//            document = parser.parse(getClass().getResourceAsStream(
+//                    "/recipt.xml"));
+//            parseException = errorHandler.getFirstException();
+//
+//            assertNotNull(document);
+//
+//        } catch (Exception ex) {
+//            parseException = ex;
+//        }
+//        parser.setErrorHandler(null);
+//
+//        if (parseException != null) {
+//            fail("Unexpected exception " + parseException.getMessage());
+//        }
+//
+//        // case 4: Validation is set. Wrong xml-file
+//        try {
+//
+//            parser = dbf.newDocumentBuilder();
+//            parser.setErrorHandler(errorHandler);
+//
+//            document = parser.parse(getClass().getResourceAsStream(
+//                    "/reciptWrong.xml"));
+//            parseException = errorHandler.getFirstException();
+//
+//            assertNotNull(document);
+//
+//        } catch (Exception ex) {
+//            parseException = ex;
+//        }
+//        parser.setErrorHandler(null);
+//
+//        if (parseException == null) {
+//            fail("Unexpected exception " + parseException.getMessage());
+//        } else {
+//            assertTrue(parseException
+//                    .getMessage()
+//                    .contains(
+//                            "The content of element type \"collection\" must match \"(description,recipe+)\""));
+//        }
+//
+//    }
+
+    /**
+     * @tests javax.xml.parsers.DocumentBuilderFactory#setXIncludeAware().
+     */
+//    public void test_setXIncludeAware() {
+//        dbf.setXIncludeAware(true);
+//        assertTrue(dbf.isXIncludeAware());
+//
+//        try {
+//            DocumentBuilder parser = dbf.newDocumentBuilder();
+//
+//            Document document = parser.parse(getClass().getResourceAsStream(
+//                    "/recipt.xml"));
+//
+//            assertNotNull(document);
+//
+//        } catch (IOException e) {
+//            fail("Unexpected IOException " + e.getMessage());
+//        } catch (ParserConfigurationException e) {
+//            fail("Unexpected ParserConfigurationException " + e.getMessage());
+//        } catch (SAXException e) {
+//            fail("Unexpected SAXException " + e.getMessage());
+//        }
+//
+//        dbf.setXIncludeAware(false);
+//        assertFalse(dbf.isXIncludeAware());
+//
+//        try {
+//            DocumentBuilder parser = dbf.newDocumentBuilder();
+//
+//            Document document = parser.parse(getClass().getResourceAsStream(
+//                    "/recipt.xml"));
+//
+//            assertNotNull(document);
+//
+//        } catch (IOException e) {
+//            fail("Unexpected IOException " + e.getMessage());
+//        } catch (ParserConfigurationException e) {
+//            fail("Unexpected ParserConfigurationException " + e.getMessage());
+//        } catch (SAXException e) {
+//            fail("Unexpected SAXException " + e.getMessage());
+//        }
+//    }
+
+    private void goThroughDocument(Node node, String indent) {
+        String value = node.getNodeValue();
+
+        if (value != null) {
+            value = value.replaceAll(" ", "");
+            value = value.replaceAll("\n", "");
+        }
+
+        switch (node.getNodeType()) {
+        case Node.CDATA_SECTION_NODE:
+            cdataElements.add(value);
+            // System.out.println(indent + "CDATA_SECTION_NODE " + value);
+            break;
+        case Node.COMMENT_NODE:
+            commentElements.add(value);
+            // System.out.println(indent + "COMMENT_NODE " + value);
+            break;
+        case Node.DOCUMENT_FRAGMENT_NODE:
+            // System.out.println(indent + "DOCUMENT_FRAGMENT_NODE " + value);
+            break;
+        case Node.DOCUMENT_NODE:
+            // System.out.println(indent + "DOCUMENT_NODE " + value);
+            break;
+        case Node.DOCUMENT_TYPE_NODE:
+            // System.out.println(indent + "DOCUMENT_TYPE_NODE " + value);
+            break;
+        case Node.ELEMENT_NODE:
+            // System.out.println(indent + "ELEMENT_NODE " + value);
+            break;
+        case Node.ENTITY_NODE:
+            // System.out.println(indent + "ENTITY_NODE " + value);
+            break;
+        case Node.ENTITY_REFERENCE_NODE:
+            // System.out.println(indent + "ENTITY_REFERENCE_NODE " + value);
+            break;
+        case Node.NOTATION_NODE:
+            // System.out.println(indent + "NOTATION_NODE " + value);
+            break;
+        case Node.PROCESSING_INSTRUCTION_NODE:
+            // System.out.println(indent + "PROCESSING_INSTRUCTION_NODE " +
+            // value);
+            break;
+        case Node.TEXT_NODE:
+            textElements.add(value);
+            // System.out.println(indent + "TEXT_NODE " + value);
+            break;
+        default:
+            // System.out.println(indent + "Unknown node " + value);
+            break;
+        }
+        NodeList list = node.getChildNodes();
+        for (int i = 0; i < list.getLength(); i++)
+            goThroughDocument(list.item(i), indent + "   ");
+    }
+
+    private class ValidationErrorHandler implements ErrorHandler {
+        private SAXException parseException;
+
+        private int errorCount;
+
+        private int warningCount;
+
+        public ValidationErrorHandler() {
+            parseException = null;
+            errorCount = 0;
+            warningCount = 0;
+        }
+
+        public void error(SAXParseException ex) {
+            errorCount++;
+            if (parseException == null) {
+                parseException = ex;
+            }
+        }
+
+        public void warning(SAXParseException ex) {
+            warningCount++;
+        }
+
+        public void fatalError(SAXParseException ex) {
+            if (parseException == null) {
+                parseException = ex;
+            }
+        }
+
+        public SAXException getFirstException() {
+            return parseException;
+        }
+    }
+
+    private class DocumentBuilderFactoryChild extends DocumentBuilderFactory {
+        public DocumentBuilderFactoryChild() {
+            super();
+        }
+
+        public Object getAttribute(String name) {
+            return null;
+        }
+
+        public boolean getFeature(String name) {
+            return false;
+        }
+
+        public DocumentBuilder newDocumentBuilder() {
+            return null;
+        }
+
+        public void setAttribute(String name, Object value) {
+        }
+
+        public void setFeature(String name, boolean value) {
+        }
+
+    }
+}
diff --git a/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java b/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java
new file mode 100644
index 0000000..181e8f5
--- /dev/null
+++ b/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java
@@ -0,0 +1,733 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.javax.xml.parsers;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import junit.framework.TestCase;
+
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.Text;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import tests.api.org.xml.sax.support.MethodLogger;
+import tests.api.org.xml.sax.support.MockHandler;
+import tests.api.org.xml.sax.support.MockResolver;
+import dalvik.annotation.BrokenTest;
+import dalvik.annotation.KnownFailure;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+@TestTargetClass(DocumentBuilder.class) 
+public class DocumentBuilderTest extends TestCase {
+
+    private class MockDocumentBuilder extends DocumentBuilder {
+
+        public MockDocumentBuilder() {
+            super();
+        }
+
+        /*
+         * @see javax.xml.parsers.DocumentBuilder#getDOMImplementation()
+         */
+        @Override
+        public DOMImplementation getDOMImplementation() {
+            // it is a fake
+            return null;
+        }
+
+        /*
+         * @see javax.xml.parsers.DocumentBuilder#isNamespaceAware()
+         */
+        @Override
+        public boolean isNamespaceAware() {
+            // it is a fake
+            return false;
+        }
+
+        /*
+         * @see javax.xml.parsers.DocumentBuilder#isValidating()
+         */
+        @Override
+        public boolean isValidating() {
+            // it is a fake
+            return false;
+        }
+
+        /*
+         * @see javax.xml.parsers.DocumentBuilder#newDocument()
+         */
+        @Override
+        public Document newDocument() {
+            // it is a fake
+            return null;
+        }
+
+        /*
+         * @see javax.xml.parsers.DocumentBuilder#parse(org.xml.sax.InputSource)
+         */
+        @Override
+        public Document parse(InputSource is) throws SAXException, IOException {
+            // it is a fake
+            return null;
+        }
+
+        /*
+         * @see javax.xml.parsers.DocumentBuilder#setEntityResolver(
+         *  org.xml.sax.EntityResolver)
+         */
+        @Override
+        public void setEntityResolver(EntityResolver er) {
+            // it is a fake
+        }
+
+        /*
+         * @see javax.xml.parsers.DocumentBuilder#setErrorHandler(
+         *  org.xml.sax.ErrorHandler)
+         */
+        @Override
+        public void setErrorHandler(ErrorHandler eh) {
+            // it is a fake
+        }
+
+        public Object clone() throws CloneNotSupportedException {
+            return super.clone();
+        }
+    }
+
+    DocumentBuilderFactory dbf;
+
+    DocumentBuilder db;
+
+    protected void setUp() throws Exception {
+        dbf = DocumentBuilderFactory.newInstance();
+        
+        dbf.setIgnoringElementContentWhitespace(true);
+        
+        db = dbf.newDocumentBuilder();
+        super.setUp();
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "DocumentBuilder",
+        args = {}
+    )
+    public void testDocumentBuilder() {
+        try {
+            new MockDocumentBuilder();
+        } catch (Exception e) {
+            fail("unexpected exception " + e.toString());
+        }
+    }
+
+    /**
+     *  @tests javax.xml.parsers.DocumentBuilder#getSchema()
+     *  TBD getSchema() is not supported
+     */
+ /*   public void test_getSchema() {
+        assertNull(db.getSchema());
+        SchemaFactory sf =
+            SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+        try {
+            Schema schema = sf.newSchema();
+            dbf.setSchema(schema);
+            assertNotNull(dbf.newDocumentBuilder().getSchema());
+        } catch (ParserConfigurationException pce) {
+            fail("Unexpected ParserConfigurationException " + pce.toString());
+        } catch (SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+    }
+*/
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "newDocument",
+        args = { }
+    )
+    public void testNewDocument() {
+        Document d;
+        
+        try {
+            d = dbf.newDocumentBuilder().newDocument();
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        assertNotNull(d);
+        assertNull(d.getDoctype());
+        assertNull(d.getDocumentElement());
+        assertNull(d.getNamespaceURI());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "getDOMImplementation",
+        args = { }
+    )
+    public void testGetImplementation() {
+        DOMImplementation d;
+        
+        try {
+            d = dbf.newDocumentBuilder().getDOMImplementation();
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        assertNotNull(d);
+    }
+    
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "isNamespaceAware",
+        args = {}
+    )
+    public void testIsNamespaceAware() {
+        try {
+            dbf.setNamespaceAware(true);
+            assertTrue(dbf.newDocumentBuilder().isNamespaceAware());
+            dbf.setNamespaceAware(false);
+            assertFalse(dbf.newDocumentBuilder().isNamespaceAware());
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.SUFFICIENT,
+        notes = "No validating parser in Android, hence not tested",
+        method = "isValidating",
+        args = {}
+    )
+    public void testIsValidating() {
+        try {
+            dbf.setValidating(false);
+            assertFalse(dbf.newDocumentBuilder().isValidating());
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.SUFFICIENT,
+        notes = "No XInclude-aware parser in Android, hence not tested",
+        method = "isXIncludeAware",
+        args = {}
+    )
+    @KnownFailure("Should handle XIncludeAware flag more gracefully")
+    public void testIsXIncludeAware() {
+        try {
+            dbf.setXIncludeAware(false);
+            assertFalse(dbf.newDocumentBuilder().isXIncludeAware());
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    /**
+     * @tests javax.xml.parsers.DocumentBuilder#parse(java.io.File)
+     * Case 1: Try to parse correct xml document.
+     * Case 2: Try to call parse() with null argument.
+     * Case 3: Try to parse a non-existent file.
+     * Case 4: Try to parse incorrect xml file.
+     */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "parse",
+        args = {java.io.File.class}
+    )
+    @BrokenTest("Need to use XML file from correct location")
+    public void test_parseLjava_io_File() {
+        File f = new File("/tmp/xml_source/simple.xml");
+        // case 1: Trivial use.
+        try {
+            Document d = db.parse(f);
+            assertNotNull(d);
+       //      TBD getXmlEncoding() IS NOT SUPPORTED
+       //     assertEquals("ISO-8859-1", d.getXmlEncoding());
+            assertEquals(2, d.getChildNodes().getLength());
+            assertEquals("#comment",
+                    d.getChildNodes().item(0).getNodeName());
+            assertEquals("breakfast_menu",
+                    d.getChildNodes().item(1).getNodeName());
+        } catch (IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch (SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+
+        // case 2: Try to call parse with null argument
+        try {
+            db.parse((File)null);
+            fail("Expected IllegalArgumentException was not thrown");
+        } catch (IllegalArgumentException iae) {
+            // expected
+        } catch (IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch (SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+
+        // case 3: Try to parse a non-existent file
+        try {
+            db.parse(new File("_"));
+            fail("Expected IOException was not thrown");
+        } catch (IOException ioe) {
+            // expected
+        } catch (SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+
+        // case 4: Try to parse incorrect xml file
+        try {
+            f = new File("/tmp/xml_source/wrong.xml");
+            db.parse(f);
+            fail("Expected SAXException was not thrown");
+        } catch (IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch (SAXException sax) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests javax.xml.parsers.DocumentBuilder#parse(java.io.InputStream)
+     * Case 1: Try to parse correct xml document.
+     * Case 2: Try to call parse() with null argument.
+     * Case 3: Try to parse a non-existent file.
+     * Case 4: Try to parse incorrect xml file.
+     */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "parse",
+        args = {java.io.InputStream.class}
+    )
+    public void test_parseLjava_io_InputStream() {
+        InputStream is = getClass().getResourceAsStream("/simple.xml");
+        // case 1: Trivial use.
+        try {
+            Document d = db.parse(is);
+            assertNotNull(d);
+            // TBD getXmlEncoding() IS NOT SUPPORTED
+            // assertEquals("ISO-8859-1", d.getXmlEncoding());
+            assertEquals(2, d.getChildNodes().getLength());
+            assertEquals("#comment",
+                    d.getChildNodes().item(0).getNodeName());
+            assertEquals("breakfast_menu",
+                    d.getChildNodes().item(1).getNodeName());
+        } catch (IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch (SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+
+        // case 2: Try to call parse with null argument
+        try {
+            db.parse((InputStream)null);
+            fail("Expected IllegalArgumentException was not thrown");
+        } catch (IllegalArgumentException iae) {
+            // expected
+        } catch (IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch (SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+
+        // case 3: Try to parse a non-existent file
+        try {
+            db.parse(new FileInputStream("_"));
+            fail("Expected IOException was not thrown");
+        } catch (IOException ioe) {
+            // expected
+        } catch (SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+
+        // case 4: Try to parse incorrect xml file
+        try {
+            is = getClass().getResourceAsStream("/wrong.xml");
+            db.parse(is);
+            fail("Expected SAXException was not thrown");
+        } catch (IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch (SAXException sax) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests javax.xml.parsers.DocumentBuilder#parse(java.io.InputStream)
+     * Case 1: Try to parse correct xml document.
+     * Case 2: Try to call parse() with null argument.
+     * Case 3: Try to parse a non-existent file.
+     * Case 4: Try to parse incorrect xml file.
+     */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "parse",
+        args = { InputSource.class }
+    )
+    public void testParseInputSource() {
+        InputStream stream = getClass().getResourceAsStream("/simple.xml");
+        InputSource is = new InputSource(stream);
+        
+        // case 1: Trivial use.
+        try {
+            Document d = db.parse(is);
+            assertNotNull(d);
+            // TBD getXmlEncoding() IS NOT SUPPORTED
+            // assertEquals("ISO-8859-1", d.getXmlEncoding());
+            assertEquals(2, d.getChildNodes().getLength());
+            assertEquals("#comment",
+                    d.getChildNodes().item(0).getNodeName());
+            assertEquals("breakfast_menu",
+                    d.getChildNodes().item(1).getNodeName());
+        } catch (IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch (SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+
+        // case 2: Try to call parse with null argument
+        try {
+            db.parse((InputSource)null);
+            fail("Expected IllegalArgumentException was not thrown");
+        } catch (IllegalArgumentException iae) {
+            // expected
+        } catch (IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch (SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+
+        // case 3: Try to parse a non-existent file
+        try {
+            db.parse(new InputSource(new FileInputStream("_")));
+            fail("Expected IOException was not thrown");
+        } catch (IOException ioe) {
+            // expected
+        } catch (SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+
+        // case 4: Try to parse incorrect xml file
+        try {
+            is = new InputSource(getClass().getResourceAsStream("/wrong.xml"));
+            db.parse(is);
+            fail("Expected SAXException was not thrown");
+        } catch (IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch (SAXException sax) {
+            // expected
+        }
+    }
+    
+    /**
+     * @tests javax.xml.parsers.DocumentBuilder#parse(java.io.InputStream,
+     *     java.lang.String)
+     * Case 1: Try to parse correct xml document.
+     * Case 2: Try to call parse() with null argument.
+     * Case 3: Try to parse a non-existent file.
+     * Case 4: Try to parse incorrect xml file.
+     */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "parse",
+        args = {java.io.InputStream.class, java.lang.String.class}
+    )
+    public void test_parseLjava_io_InputStreamLjava_lang_String() {
+        InputStream is = getClass().getResourceAsStream("/systemid.xml");
+        // case 1: Trivial use.
+        try {
+            Document d = db.parse(is, SAXParserTestSupport.XML_SYSTEM_ID);
+            assertNotNull(d);
+//           TBD getXmlEncoding() is not supported
+//           assertEquals("UTF-8", d.getXmlEncoding());
+            assertEquals(4, d.getChildNodes().getLength());
+            assertEquals("collection",
+                    d.getChildNodes().item(0).getNodeName());
+            assertEquals("#comment",
+                    d.getChildNodes().item(1).getNodeName());
+            assertEquals("collection",
+                    d.getChildNodes().item(2).getNodeName());
+            assertEquals("#comment",
+                    d.getChildNodes().item(3).getNodeName());
+        } catch (IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch (SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+
+        // case 2: Try to call parse with null argument
+        try {
+            db.parse((InputStream)null, SAXParserTestSupport.XML_SYSTEM_ID);
+            fail("Expected IllegalArgumentException was not thrown");
+        } catch (IllegalArgumentException iae) {
+            // expected
+        } catch (IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch (SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+
+        // case 3: Try to parse a non-existent file
+// Doesn't make sense this way...
+//        try {
+//            db.parse(is, "/");
+//            fail("Expected IOException was not thrown");
+//        } catch (IOException ioe) {
+//            // expected
+//        } catch (SAXException sax) {
+//            fail("Unexpected SAXException " + sax.toString());
+//        }
+
+        // case 4: Try to parse incorrect xml file
+        try {
+            is = getClass().getResourceAsStream("/wrong.xml");
+            db.parse(is, SAXParserTestSupport.XML_SYSTEM_ID);
+            fail("Expected SAXException was not thrown");
+        } catch (IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch (SAXException sax) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests javax.xml.parsers.DocumentBuilder#parse(java.lang.String)
+     * Case 1: Try to parse correct xml document.
+     * Case 2: Try to call parse() with null argument.
+     * Case 3: Try to parse a non-existent uri.
+     * Case 4: Try to parse incorrect xml file.
+     */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "parse",
+        args = {java.lang.String.class}
+    )
+    @KnownFailure("Android DocumentBuilder should support File sources")
+    public void test_parseLjava_lang_String() {
+        // case 1: Trivial use.
+        File f = new File(getClass().getResource("/simple.xml").getFile());
+        try {
+            Document d = db.parse(f.getAbsolutePath());
+            assertNotNull(d);
+//          TBD  getXmlEncoding() is not supported
+//          assertEquals("ISO-8859-1", d.getXmlEncoding());
+            assertEquals(2, d.getChildNodes().getLength());
+            assertEquals("#comment",
+                    d.getChildNodes().item(0).getNodeName());
+            assertEquals("breakfast_menu",
+                    d.getChildNodes().item(1).getNodeName());
+        } catch (IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch (SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+
+        // case 2: Try to call parse with null argument
+        try {
+            db.parse((String)null);
+            fail("Expected IllegalArgumentException was not thrown");
+        } catch (IllegalArgumentException iae) {
+            // expected
+        } catch (IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch (SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+
+        // case 3: Try to parse a non-existent uri
+        try {
+            db.parse("_");
+            fail("Expected IOException was not thrown");
+        } catch (IOException ioe) {
+            // expected
+        } catch (SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+
+        // case 4: Try to parse incorrect xml file
+        try {
+            f = new File(getClass().getResource("/wrong.xml").getFile());
+            db.parse(f.getAbsolutePath());
+            fail("Expected SAXException was not thrown");
+        } catch (IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch (SAXException sax) {
+            // expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "reset",
+        args = { }
+    )
+    @KnownFailure("Android DocumentBuilder should implement reset() properly")
+    public void testReset() {
+        // Make sure EntityResolver gets reset
+        InputStream source = new ByteArrayInputStream("<a>&foo;</a>".getBytes());
+        InputStream entity = new ByteArrayInputStream("bar".getBytes());
+        
+        MockResolver resolver = new MockResolver();
+        resolver.addEntity("foo", "foo", new InputSource(entity));
+
+        Document d;
+        
+        try {
+            db = dbf.newDocumentBuilder();
+            db.setEntityResolver(resolver);
+            db.reset();
+            d = db.parse(source);
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        Element root = (Element)d.getElementsByTagName("a").item(0);
+        assertEquals("foo", ((EntityReference)root.getFirstChild()).getNodeName());
+
+        // Make sure ErrorHandler gets reset
+        source = new ByteArrayInputStream("</a>".getBytes());
+
+        MethodLogger logger = new MethodLogger();
+        ErrorHandler handler = new MockHandler(logger);
+        
+        try {
+            db = dbf.newDocumentBuilder();
+            db.setErrorHandler(handler);
+            db.reset();
+            d = db.parse(source);
+        } catch (SAXParseException e) {
+            // Expected
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);            
+        }
+
+        assertEquals(0, logger.size());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setErrorHandler",
+        args = { ErrorHandler.class }
+    )
+    public void testSetErrorHandler() {
+        // Ordinary case
+        InputStream source = new ByteArrayInputStream("</a>".getBytes());
+
+        MethodLogger logger = new MethodLogger();
+        ErrorHandler handler = new MockHandler(logger);
+        
+        try {
+            db = dbf.newDocumentBuilder();
+            db.setErrorHandler(handler);
+            db.parse(source);
+        } catch (SAXParseException e) {
+            // Expected, ErrorHandler does not mask exception
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);            
+        }
+
+        assertEquals("error", logger.getMethod());
+        assertTrue(logger.getArgs()[0] instanceof SAXParseException);
+        
+        // null case 
+        source = new ByteArrayInputStream("</a>".getBytes());
+
+        try {
+            db = dbf.newDocumentBuilder();
+            db.setErrorHandler(null);
+            db.parse(source);
+        } catch (SAXParseException e) {
+            // Expected
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);            
+        }
+    }
+    
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setEntityResolver",
+        args = { EntityResolver.class }
+    )
+    @KnownFailure("Android DocumentBuilder should support entity resolving")
+    public void testSetEntityResolver() {
+        // Ordinary case
+        InputStream source = new ByteArrayInputStream("<a>&foo;</a>".getBytes());
+        InputStream entity = new ByteArrayInputStream("bar".getBytes());
+        
+        MockResolver resolver = new MockResolver();
+        resolver.addEntity("foo", "foo", new InputSource(entity));
+
+        Document d;
+        
+        try {
+            db = dbf.newDocumentBuilder();
+            db.setEntityResolver(resolver);
+            d = db.parse(source);
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        Element root = (Element)d.getElementsByTagName("a").item(0);
+        assertEquals("bar", ((Text)root.getFirstChild()).getData());
+        
+        // null case 
+        source = new ByteArrayInputStream("<a>&foo;</a>".getBytes());
+        
+        try {
+            db = dbf.newDocumentBuilder();
+            db.setEntityResolver(null);
+            d = db.parse(source);
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        root = (Element)d.getElementsByTagName("a").item(0);
+        assertEquals("foo", ((EntityReference)root.getFirstChild()).getNodeName());
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/javax/xml/parsers/FactoryConfigurationErrorTest.java b/xml/src/test/java/tests/api/javax/xml/parsers/FactoryConfigurationErrorTest.java
new file mode 100644
index 0000000..0b5f230
--- /dev/null
+++ b/xml/src/test/java/tests/api/javax/xml/parsers/FactoryConfigurationErrorTest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.javax.xml.parsers;
+
+import javax.xml.parsers.FactoryConfigurationError;
+
+import junit.framework.TestCase;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+@TestTargetClass(FactoryConfigurationError.class) 
+public class FactoryConfigurationErrorTest extends TestCase {
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "FactoryConfigurationError",
+        args = {}
+    )
+    public void test_Constructor() {
+        FactoryConfigurationError fce = new FactoryConfigurationError();
+        assertNull(fce.getMessage());
+        assertNull(fce.getLocalizedMessage());
+        assertNull(fce.getCause());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "FactoryConfigurationError",
+        args = {java.lang.Exception.class}
+    )
+    public void test_ConstructorLjava_lang_Exception() {
+        Exception e = new Exception();
+        // case 1: Try to create FactoryConfigurationError
+        // which is based on Exception without parameters.
+        FactoryConfigurationError fce = new FactoryConfigurationError(e);
+        assertNotNull(fce.getMessage());
+        assertNotNull(fce.getLocalizedMessage());
+        assertEquals(e.getCause(), fce.getCause());
+
+        // case 2: Try to create FactoryConfigurationError
+        // which is based on Exception with String parameter.
+        e = new Exception("test message");
+        fce = new FactoryConfigurationError(e);
+        assertEquals(e.toString(), fce.getMessage());
+        assertEquals(e.toString(), fce.getLocalizedMessage());
+        assertEquals(e.getCause(), fce.getCause());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "FactoryConfigurationError",
+        args = {java.lang.Exception.class, java.lang.String.class}
+    )
+    public void test_ConstructorLjava_lang_ExceptionLjava_lang_String() {
+        Exception e = new Exception();
+        // case 1: Try to create FactoryConfigurationError
+        // which is based on Exception without parameters.
+        FactoryConfigurationError fce = new FactoryConfigurationError(e, "msg");
+        assertNotNull(fce.getMessage());
+        assertNotNull(fce.getLocalizedMessage());
+        assertEquals(e.getCause(), fce.getCause());
+
+        // case 2: Try to create FactoryConfigurationError
+        // which is based on Exception with String parameter.
+        e = new Exception("test message");
+        fce = new FactoryConfigurationError(e, "msg");
+        assertEquals("msg", fce.getMessage());
+        assertEquals("msg", fce.getLocalizedMessage());
+        assertEquals(e.getCause(), fce.getCause());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "FactoryConfigurationError",
+        args = {java.lang.String.class}
+    )
+    public void test_ConstructorLjava_lang_String() {
+        FactoryConfigurationError fce = new FactoryConfigurationError("Oops!");
+        assertEquals("Oops!", fce.getMessage());
+        assertEquals("Oops!", fce.getLocalizedMessage());
+        assertNull(fce.getCause());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "getException",
+        args = {}
+    )
+    public void test_getException() {
+        FactoryConfigurationError fce = new FactoryConfigurationError();
+        assertNull(fce.getException());
+        fce = new FactoryConfigurationError("test");
+        assertNull(fce.getException());
+        Exception e = new Exception("msg");
+        fce = new FactoryConfigurationError(e);
+        assertEquals(e, fce.getException());
+        NullPointerException npe = new NullPointerException();
+        fce = new FactoryConfigurationError(npe);
+        assertEquals(npe, fce.getException());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "getMessage",
+        args = {}
+    )
+    public void test_getMessage() {
+        assertNull(new FactoryConfigurationError().getMessage());
+        assertEquals("msg1",
+                new FactoryConfigurationError("msg1").getMessage());
+        assertEquals(new Exception("msg2").toString(),
+                new FactoryConfigurationError(
+                        new Exception("msg2")).getMessage());
+        assertEquals(new NullPointerException().toString(),
+                new FactoryConfigurationError(
+                        new NullPointerException()).getMessage());
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/javax/xml/parsers/ParserConfigurationExceptionTest.java b/xml/src/test/java/tests/api/javax/xml/parsers/ParserConfigurationExceptionTest.java
new file mode 100644
index 0000000..63b87a7
--- /dev/null
+++ b/xml/src/test/java/tests/api/javax/xml/parsers/ParserConfigurationExceptionTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.javax.xml.parsers;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import junit.framework.TestCase;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+@TestTargetClass(ParserConfigurationException.class) 
+public class ParserConfigurationExceptionTest extends TestCase{
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "ParserConfigurationException",
+        args = {}
+    )
+    public void test_Constructor() {
+        ParserConfigurationException pce = new ParserConfigurationException();
+        assertNull(pce.getMessage());
+        assertNull(pce.getLocalizedMessage());
+        assertNull(pce.getCause());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "ParserConfigurationException",
+        args = {java.lang.String.class}
+    )
+    public void test_ConstructorLjava_lang_String() {
+        ParserConfigurationException pce =
+            new ParserConfigurationException("Oops!");
+        assertEquals("Oops!", pce.getMessage());
+        assertEquals("Oops!", pce.getLocalizedMessage());
+        assertNull(pce.getCause());
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserFactoryTest.java b/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserFactoryTest.java
new file mode 100644
index 0000000..5d41356
--- /dev/null
+++ b/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserFactoryTest.java
@@ -0,0 +1,547 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.javax.xml.parsers;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Properties;
+import java.util.Vector;
+
+import javax.xml.parsers.FactoryConfigurationError;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import dalvik.annotation.AndroidOnly;
+import dalvik.annotation.KnownFailure;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+@TestTargetClass(SAXParserFactory.class) 
+public class SAXParserFactoryTest extends TestCase {
+
+    SAXParserFactory spf;
+
+    InputStream is1;
+
+    static HashMap<String, String> ns;
+
+    static Vector<String> el;
+
+    static HashMap<String, String> attr;
+
+    public void setUp() throws Exception {
+        spf = SAXParserFactory.newInstance();
+
+        is1 = getClass().getResourceAsStream("/simple.xml");
+
+        ns = new HashMap<String, String>();
+        attr = new HashMap<String, String>();
+        el = new Vector<String>();
+    }
+
+    public void tearDown() throws Exception {
+        is1.close();
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "SAXParserFactory",
+        args = {}
+    )
+    @AndroidOnly("Android SAX implementation is non-validating")
+    public void test_Constructor() {
+        MySAXParserFactory mpf = new MySAXParserFactory();
+        assertTrue(mpf instanceof SAXParserFactory);
+        assertFalse(mpf.isValidating());
+    }
+
+    /**
+     * @tests javax.xml.parsers.SAXParserFactory#getSchema().
+     * TBD getSchema() IS NOT SUPPORTED
+     */
+    /*   public void test_getSchema() {
+        assertNull(spf.getSchema());
+        SchemaFactory sf =
+            SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+        try {
+            Schema schema = sf.newSchema();
+            spf.setSchema(schema);
+            assertNotNull(spf.getSchema());
+        } catch (SAXException sax) {
+            fail("Unexpected exception " + sax.toString());
+        }
+    }
+     */
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            notes = "",
+            method = "isNamespaceAware",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            notes = "",
+            method = "setNamespaceAware",
+            args = {boolean.class}
+        )
+    })
+    public void test_setIsNamespaceAware() {
+        spf.setNamespaceAware(true);
+        assertTrue(spf.isNamespaceAware());
+        spf.setNamespaceAware(false);
+        assertFalse(spf.isNamespaceAware());
+        spf.setNamespaceAware(true);
+        assertTrue(spf.isNamespaceAware());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            notes = "",
+            method = "isValidating",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.SUFFICIENT,
+            notes = "",
+            method = "setValidating",
+            args = {boolean.class}
+        )
+    })
+    public void test_setIsValidating() {
+        spf.setValidating(true);
+        assertTrue(spf.isValidating());
+        spf.setValidating(false);
+        assertFalse(spf.isValidating());
+        spf.setValidating(true);
+        assertTrue(spf.isValidating());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            notes = "",
+            method = "isXIncludeAware",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.SUFFICIENT,
+            notes = "",
+            method = "setXIncludeAware",
+            args = {boolean.class}
+        )
+    })
+    @KnownFailure("Should handle XIncludeAware flag more gracefully")
+    public void test_setIsXIncludeAware() {
+        spf.setXIncludeAware(true);
+        assertTrue(spf.isXIncludeAware());
+        spf.setXIncludeAware(false);
+        assertFalse(spf.isXIncludeAware());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "newInstance",
+        args = {}
+    )
+    public void test_newInstance() {
+        String className = null;
+        try {
+            SAXParserFactory dtf = SAXParserFactory.newInstance();
+            assertNotNull("New Instance of DatatypeFactory is null", dtf);
+
+            className = System.getProperty("javax.xml.parsers.SAXParserFactory");
+
+            System.setProperty("javax.xml.parsers.SAXParserFactory",
+            "org.apache.harmony.xml.parsers.SAXParserFactoryImpl");
+
+            SAXParserFactory spf1 = SAXParserFactory.newInstance();
+            assertTrue(spf1 instanceof org.apache.harmony.xml.parsers.SAXParserFactoryImpl);
+
+            String key = "javax.xml.parsers.SAXParserFactory = org.apache.harmony.xml.parsers.SAXParserFactoryImpl";
+
+            ByteArrayInputStream bis = new ByteArrayInputStream(key.getBytes());
+            Properties prop = System.getProperties();
+            prop.load(bis);
+            SAXParserFactory spf2 = SAXParserFactory.newInstance();
+            assertTrue(spf2 instanceof org.apache.harmony.xml.parsers.SAXParserFactoryImpl);
+
+            System.setProperty("javax.xml.parsers.SAXParserFactory", "");
+            try {
+                SAXParserFactory.newInstance();
+                fail("Expected FactoryConfigurationError was not thrown");
+            } catch (FactoryConfigurationError e) {
+                // expected
+            }
+        } catch (IOException ioe) {
+            fail("Unexpected exception " + ioe.toString());
+        } finally {
+            if (className == null) {
+                System.clearProperty("javax.xml.parsers.SAXParserFactory");
+            } else {
+                System.setProperty("javax.xml.parsers.SAXParserFactory",
+                        className);
+            }
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.SUFFICIENT,
+        notes = "SAXException untested; unused on Android",
+        method = "newSAXParser",
+        args = {}
+    )
+    public void test_newSAXParser() {
+        // Ordinary case
+        try {
+            SAXParser sp = spf.newSAXParser();
+            assertTrue(sp instanceof SAXParser);
+            sp.parse(is1, new MyHandler());
+        } catch(Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        // Exception case
+        spf.setValidating(true);
+        try {
+            SAXParser sp = spf.newSAXParser();
+        } catch(ParserConfigurationException e) {
+            // Expected, since Android doesn't have a validating parser.
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.SUFFICIENT,
+            method = "setFeature",
+            notes = "ParserConfigurationException untested; unused on Android",
+            args = {java.lang.String.class, boolean.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.SUFFICIENT,
+            method = "getFeature",
+            notes = "ParserConfigurationException untested; unused on Android",
+            args = {java.lang.String.class}
+        )
+    })        
+    public void test_setFeatureLjava_lang_StringZ() {
+        // We can't verify ParserConfigurationException and
+        // SAXNotSupportedException since these are never
+        // thrown by Android.
+        
+        String[] features = {
+                "http://xml.org/sax/features/namespaces",
+                "http://xml.org/sax/features/validation" };
+        for (int i = 0; i < features.length; i++) {
+            try {
+                spf.setFeature(features[i], true);
+                assertTrue(spf.getFeature(features[i]));
+                spf.setFeature(features[i], false);
+                assertFalse(spf.getFeature(features[i]));
+            } catch (ParserConfigurationException pce) {
+                fail("ParserConfigurationException is thrown");
+            } catch (SAXNotRecognizedException snre) {
+                fail("SAXNotRecognizedException is thrown");
+            } catch (SAXNotSupportedException snse) {
+                fail("SAXNotSupportedException is thrown");
+            }
+        }
+
+        try {
+            spf.setFeature("", true);
+            fail("SAXNotRecognizedException is not thrown");
+        } catch (ParserConfigurationException pce) {
+            fail("ParserConfigurationException is thrown");
+        } catch (SAXNotRecognizedException snre) {
+            //expected
+        } catch (SAXNotSupportedException snse) {
+            fail("SAXNotSupportedException is thrown");
+        } catch (NullPointerException npe) {
+            fail("NullPointerException is thrown");
+        }
+
+        try {
+            spf.setFeature("http://xml.org/sax/features/unknown-feature", true);
+        } catch (ParserConfigurationException pce) {
+            fail("ParserConfigurationException is thrown");
+        } catch (SAXNotRecognizedException snre) {
+            fail("SAXNotRecognizedException is thrown");
+        } catch (SAXNotSupportedException snse) {
+            // Acceptable, although this doesn't happen an Android.
+        } catch (NullPointerException npe) {
+            fail("NullPointerException is thrown");
+        }
+
+        try {
+            spf.setFeature(null, true);
+            fail("NullPointerException is not thrown");
+        } catch (ParserConfigurationException pce) {
+            fail("ParserConfigurationException is thrown");
+        } catch (SAXNotRecognizedException snre) {
+            fail("SAXNotRecognizedException is thrown");
+        } catch (SAXNotSupportedException snse) {
+            fail("SAXNotSupportedException is thrown");
+        } catch (NullPointerException npe) {
+            // expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setNamespaceAware",
+        args = {boolean.class}
+    )
+    @KnownFailure("Error in namespace feature handling (for ExpatParser)")
+    public void test_setNamespaceAwareZ() {
+
+        spf.setNamespaceAware(true);
+        MyHandler mh = new MyHandler();
+        InputStream is = getClass().getResourceAsStream("/simple_ns.xml");
+        try {
+            spf.newSAXParser().parse(is, mh);
+        } catch(javax.xml.parsers.ParserConfigurationException pce) {
+            fail("ParserConfigurationException was thrown during parsing");
+        } catch(org.xml.sax.SAXException se) {
+            fail("SAXException was thrown during parsing");
+        } catch(IOException ioe) {
+            fail("IOException was thrown during parsing");
+        } finally {
+            try {
+                is.close();
+            } catch(Exception e) {}
+        }
+        spf.setNamespaceAware(false);
+        is = getClass().getResourceAsStream("/simple_ns.xml");
+        try {
+            is = getClass().getResourceAsStream("/simple_ns.xml");
+            spf.newSAXParser().parse(is, mh);
+        } catch(javax.xml.parsers.ParserConfigurationException pce) {
+            fail("ParserConfigurationException was thrown during parsing");
+        } catch(org.xml.sax.SAXException se) {
+            se.printStackTrace();
+            fail("SAXException was thrown during parsing");
+        } catch(IOException ioe) {
+            fail("IOException was thrown during parsing");
+        } finally {
+            try {
+                is.close();
+            } catch(Exception ioee) {}
+        }
+        is = getClass().getResourceAsStream("/simple_ns.xml");
+        try {
+            spf.setNamespaceAware(true);
+            spf.newSAXParser().parse(is, mh);
+        } catch(javax.xml.parsers.ParserConfigurationException pce) {
+            fail("ParserConfigurationException was thrown during parsing");
+        } catch(org.xml.sax.SAXException se) {
+            fail("SAXException was thrown during parsing");
+        } catch(IOException ioe) {
+            fail("IOException was thrown during parsing");
+        } finally {
+            try {
+                is.close();
+            } catch(Exception ioee) {}
+        }
+    }
+
+    /*   public void test_setSchemaLjavax_xml_validation_Schema() {
+        SchemaFactory sf =
+            SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+        try {
+            Schema schema = sf.newSchema();
+            spf.setSchema(schema);
+            assertNotNull(spf.getSchema());
+        } catch (SAXException sax) {
+            fail("Unexpected exception " + sax.toString());
+        }
+    }
+     */
+
+//    public void test_setValidatingZ() {
+//        MyHandler mh = new MyHandler();
+//        InputStream is2 = getClass().getResourceAsStream("/recipe.xml");
+//        try {
+//            spf.setValidating(true);
+//            assertTrue(spf.isValidating());
+//            spf.newSAXParser().parse(is2, mh);
+//        } catch (org.xml.sax.SAXException se) {
+//            fail("SAXException was thrown during parsing");
+//        } catch (javax.xml.parsers.ParserConfigurationException pce) {
+//            fail("ParserConfigurationException was thrown during parsing");
+//        } catch (IOException ioe) {
+//            fail("IOException was thrown during parsing");
+//        } finally {
+//            try {
+//                is2.close();
+//            } catch(Exception ioee) {}
+//        }
+//        InputStream is3 = getClass().getResourceAsStream("/recipe1.xml");
+//        try {
+//            assertTrue(spf.isValidating());
+//            spf.newSAXParser().parse(is3, mh);
+//        } catch (org.xml.sax.SAXException se) {
+//            fail("SAXException was thrown during parsing");
+//        } catch (javax.xml.parsers.ParserConfigurationException pce) {
+//            fail("ParserConfigurationException was thrown during parsing");
+//        } catch (IOException ioe) {
+//            fail("IOEXception was thrown during parsing: " + ioe.getMessage());
+//        } finally {
+//            try {
+//                is3.close();
+//            } catch(Exception ioee) {}
+//        }
+//        is2 = getClass().getResourceAsStream("/recipe.xml");
+//        try {
+//            spf.setValidating(false);
+//            assertFalse(spf.isValidating());
+//            spf.newSAXParser().parse(is2, mh);
+//        } catch (org.xml.sax.SAXException se) {
+//            fail("SAXException was thrown during parsing");
+//        } catch (javax.xml.parsers.ParserConfigurationException pce) {
+//            fail("ParserConfigurationException was thrown during parsing");
+//        } catch (IOException ioe) {
+//            fail("IOException was thrown during parsing");
+//        } finally {
+//            try {
+//                is2.close();
+//            } catch(Exception ioee) {}
+//        }
+//        is3 = getClass().getResourceAsStream("/recipe1.xml");
+//        try {
+//            assertFalse(spf.isValidating());
+//            spf.newSAXParser().parse(is3, mh);
+//        } catch (org.xml.sax.SAXException se) {
+//            fail("SAXException was thrown during parsing");
+//        } catch (javax.xml.parsers.ParserConfigurationException pce) {
+//            fail("ParserConfigurationException was thrown during parsing");
+//        } catch (IOException ioe) {
+//            fail("IOEXception was thrown during parsing: " + ioe.getMessage());
+//        } finally {
+//            try {
+//                is3.close();
+//            } catch(Exception ioee) {}
+//        }
+//    }
+
+//    public void test_setXIncludeAwareZ() {
+//        spf.setXIncludeAware(true);
+//        MyHandler mh = new MyHandler();
+//        InputStream is = getClass().getResourceAsStream("/simple_ns.xml");
+//        try {
+//            spf.newSAXParser().parse(is, mh);
+//        } catch(javax.xml.parsers.ParserConfigurationException pce) {
+//            fail("ParserConfigurationException was thrown during parsing");
+//        } catch(org.xml.sax.SAXException se) {
+//            fail("SAXException was thrown during parsing");
+//        } catch(IOException ioe) {
+//            fail("IOException was thrown during parsing");
+//        } finally {
+//            try {
+//                is.close();
+//            } catch(Exception ioee) {}
+//        }
+//        spf.setXIncludeAware(false);
+//        is = getClass().getResourceAsStream("/simple_ns.xml");
+//        try {
+//            is = getClass().getResourceAsStream("/simple_ns.xml");
+//            spf.newSAXParser().parse(is, mh);
+//        } catch(javax.xml.parsers.ParserConfigurationException pce) {
+//            fail("ParserConfigurationException was thrown during parsing");
+//        } catch(org.xml.sax.SAXException se) {
+//            fail("SAXException was thrown during parsing");
+//        } catch(IOException ioe) {
+//            fail("IOException was thrown during parsing");
+//        } finally {
+//            try {
+//                is.close();
+//            } catch(Exception ioee) {}
+//        }
+//        is = getClass().getResourceAsStream("/simple_ns.xml");
+//        try {
+//            spf.setXIncludeAware(true);
+//            spf.newSAXParser().parse(is, mh);
+//        } catch(javax.xml.parsers.ParserConfigurationException pce) {
+//            fail("ParserConfigurationException was thrown during parsing");
+//        } catch(org.xml.sax.SAXException se) {
+//            fail("SAXException was thrown during parsing");
+//        } catch(IOException ioe) {
+//            fail("IOException was thrown during parsing");
+//        } finally {
+//            try {
+//                is.close();
+//            } catch(Exception ioee) {}
+//        }
+//    }
+
+    static class MyHandler extends DefaultHandler {
+
+        public void startElement(String uri, String localName, String qName,
+                Attributes atts) {
+
+            el.add(qName);
+            if (!uri.equals(""))
+                ns.put(qName, uri);
+            for (int i = 0; i < atts.getLength(); i++) {
+                attr.put(atts.getQName(i), atts.getValue(i));
+            }
+
+        }
+    }
+
+    class MySAXParserFactory extends SAXParserFactory {
+
+        public MySAXParserFactory() {
+            super();
+        }
+
+        public SAXParser newSAXParser() {
+            return null;
+        }
+
+        public void setFeature(String name, boolean value) throws
+                ParserConfigurationException, SAXNotRecognizedException,
+                SAXNotSupportedException {
+
+        }
+
+        public boolean getFeature(String name) throws 
+                ParserConfigurationException, SAXNotRecognizedException,
+                SAXNotSupportedException {
+            return true;
+        }
+
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTest.java b/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTest.java
new file mode 100644
index 0000000..4ca0f1f
--- /dev/null
+++ b/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTest.java
@@ -0,0 +1,1171 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.javax.xml.parsers;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Vector;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.HandlerBase;
+import org.xml.sax.InputSource;
+import org.xml.sax.Parser;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.helpers.DefaultHandler;
+
+import tests.api.javax.xml.parsers.SAXParserTestSupport.MyDefaultHandler;
+import tests.api.javax.xml.parsers.SAXParserTestSupport.MyHandler;
+import tests.api.org.xml.sax.support.BrokenInputStream;
+import tests.api.org.xml.sax.support.MethodLogger;
+import tests.api.org.xml.sax.support.MockHandler;
+import dalvik.annotation.KnownFailure;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+@SuppressWarnings("deprecation")
+@TestTargetClass(SAXParser.class) 
+public class SAXParserTest extends TestCase {
+
+    private class MockSAXParser extends SAXParser {
+        public MockSAXParser() {
+            super();
+        }
+
+        /*
+         * @see javax.xml.parsers.SAXParser#getParser()
+         */
+        @Override
+        public Parser getParser() throws SAXException {
+            // it is a fake
+            return null;
+        }
+
+        /*
+         * @see javax.xml.parsers.SAXParser#getProperty(java.lang.String)
+         */
+        @Override
+        public Object getProperty(String name) throws SAXNotRecognizedException,
+                SAXNotSupportedException {
+            // it is a fake
+            return null;
+        }
+
+        /*
+         * @see javax.xml.parsers.SAXParser#getXMLReader()
+         */
+        @Override
+        public XMLReader getXMLReader() throws SAXException {
+            // it is a fake
+            return null;
+        }
+
+        /*
+         * @see javax.xml.parsers.SAXParser#isNamespaceAware()
+         */
+        @Override
+        public boolean isNamespaceAware() {
+            // it is a fake
+            return false;
+        }
+
+        /*
+         * @see javax.xml.parsers.SAXParser#isValidating()
+         */
+        @Override
+        public boolean isValidating() {
+            // it is a fake
+            return false;
+        }
+
+        /*
+         * @see javax.xml.parsers.SAXParser#setProperty(java.lang.String,
+         * java.lang.Object)
+         */
+        @Override
+        public void setProperty(String name, Object value) throws
+                SAXNotRecognizedException, SAXNotSupportedException {
+            // it is a fake
+        }
+    }
+
+    private static final String LEXICAL_HANDLER_PROPERTY
+            = "http://xml.org/sax/properties/lexical-handler";
+    
+    SAXParserFactory spf;
+
+    SAXParser parser;
+
+    static HashMap<String, String> ns;
+
+    static Vector<String> el;
+
+    static HashMap<String, String> attr;
+
+    SAXParserTestSupport sp = new SAXParserTestSupport();
+
+    File [] list_wf;
+    File [] list_nwf;
+    File [] list_out_dh;
+    File [] list_out_hb;
+
+    boolean validating = false;
+
+    private InputStream getResource(String name) {
+        return this.getClass().getResourceAsStream(name);        
+    }
+    
+    public SAXParserTest() throws Exception{
+        // we differntiate between a validating and a non validating parser
+        try {
+            SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
+            validating = parser.isValidating();
+        } catch (Exception e) {
+            fail("could not obtain a SAXParser");
+        }
+
+        // nwf = non well formed, wf = well formed 
+        list_wf = new File[] {File.createTempFile(
+                SAXParserTestSupport.XML_WF + "staff","xml")};
+        list_nwf = new File[] {File.createTempFile(
+                SAXParserTestSupport.XML_NWF + "staff","xml")};
+
+        copyFile(getResource(SAXParserTestSupport.XML_WF + "staff.xml"),
+                list_wf[0].getAbsolutePath());
+        copyFile(getResource(SAXParserTestSupport.XML_WF + "staff.dtd"),
+                File.createTempFile(SAXParserTestSupport.XML_WF + "staff",
+                        "dtd").getAbsolutePath());
+        copyFile(getResource(SAXParserTestSupport.XML_NWF + "staff.xml"),
+                list_nwf[0].getAbsolutePath());
+        copyFile(getResource(SAXParserTestSupport.XML_NWF + "staff.dtd"),
+                File.createTempFile(SAXParserTestSupport.XML_NWF + "staff",
+                        "dtd").getAbsolutePath());
+
+        list_out_dh = new File[] {File.createTempFile(
+                SAXParserTestSupport.XML_WF_OUT_DH + "staff", "out")};
+        list_out_hb = new File[] {File.createTempFile(
+                SAXParserTestSupport.XML_WF_OUT_HB + "staff", "out")};
+        copyFile(getResource(SAXParserTestSupport.XML_WF_OUT_HB + "staff.out"),
+                list_out_hb[0].getAbsolutePath());
+        copyFile(getResource(SAXParserTestSupport.XML_WF_OUT_DH + "staff.out"),
+                list_out_dh[0].getAbsolutePath());
+    }
+
+    private void copyFile(InputStream toCopy, String target) throws Exception {
+        new File(target).getParentFile().mkdirs();
+        OutputStream writer = new FileOutputStream(target);
+        byte[] buffer = new byte[512];
+        int i = toCopy.read(buffer);
+        while (i >= 0) {
+            writer.write(buffer,0,i);
+            i = toCopy.read(buffer);
+        }
+        writer.flush();
+        writer.close();
+        toCopy.close();
+    }
+    
+    @Override
+    protected void setUp() throws Exception {
+        spf = SAXParserFactory.newInstance();
+        parser = spf.newSAXParser(); 
+        assertNotNull(parser);
+
+        ns = new HashMap<String, String>();
+        attr = new HashMap<String, String>();
+        el = new Vector<String>();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+    }
+    
+//    public static void main(String[] args) throws Exception {
+//        SAXParserTest st = new SAXParserTest();
+//        st.setUp();
+//        st.generateDataFromReferenceImpl();
+//        
+//    }
+//    
+//    private void generateDataFromReferenceImpl() {
+//        try {
+//            for(int i = 0; i < list_wf.length; i++) {
+//                MyDefaultHandler dh = new MyDefaultHandler();
+//                InputStream is = new FileInputStream(list_wf[i]);
+//                parser.parse(is, dh, ParsingSupport.XML_SYSTEM_ID);
+//                HashMap refHm = dh.createData();
+//                
+//                StringBuilder sb = new StringBuilder();
+//                for (int j = 0; j < ParsingSupport.KEYS.length; j++) {
+//                    String key = ParsingSupport.KEYS[j];
+//                    sb.append(refHm.get(key)).append(
+//                            ParsingSupport.SEPARATOR_DATA);
+//                }
+//                FileWriter fw = new FileWriter("/tmp/build_dh"+i+".out");
+//                fw.append(sb.toString());
+//                fw.close();
+//            }
+//            
+//            for(int i = 0; i < list_nwf.length; i++) {
+//                MyHandler hb = new MyHandler();
+//                InputStream is = new FileInputStream(list_wf[i]);
+//                parser.parse(is, hb, ParsingSupport.XML_SYSTEM_ID);
+//                HashMap refHm = hb.createData();
+//                
+//                StringBuilder sb = new StringBuilder();
+//                for (int j = 0; j < ParsingSupport.KEYS.length; j++) {
+//                    String key = ParsingSupport.KEYS[j];
+//                    sb.append(refHm.get(key)).append(
+//                            ParsingSupport.SEPARATOR_DATA);
+//                }
+//                FileWriter fw = new FileWriter("/tmp/build_hb"+i+".out");
+//                fw.append(sb.toString());
+//                fw.close();
+//            }
+//
+//            
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//        }
+//    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "SAXParser",
+        args = {}
+    )
+    public void testSAXParser() {
+        try {
+            new MockSAXParser();
+        } catch (Exception e) {
+            fail("unexpected exception " + e.toString());
+        }
+    }
+
+    /**
+     * @tests javax.xml.parser.SAXParser#getSchema().
+     * TODO getSchema() IS NOT SUPPORTED
+     */
+    /*   public void test_getSchema() {
+        assertNull(parser.getSchema());
+        SchemaFactory sf =
+            SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+        try {
+            Schema schema = sf.newSchema();
+            spf.setSchema(schema);
+            assertNotNull(spf.newSAXParser().getSchema());
+        } catch (ParserConfigurationException pce) {
+            fail("Unexpected ParserConfigurationException " + pce.toString());
+        } catch (SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+    }
+     */
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "isNamespaceAware",
+        args = {}
+    )
+    public void testIsNamespaceAware() {
+        try {
+            spf.setNamespaceAware(true);
+            assertTrue(spf.newSAXParser().isNamespaceAware());
+            spf.setNamespaceAware(false);
+            assertFalse(spf.newSAXParser().isNamespaceAware());
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.SUFFICIENT,
+        notes = "No validating parser in Android, hence not tested",
+        method = "isValidating",
+        args = {}
+    )
+    public void testIsValidating() {
+        try {
+            spf.setValidating(false);
+            assertFalse(spf.newSAXParser().isValidating());
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.SUFFICIENT,
+        notes = "No XInclude-aware parser in Android, hence not tested",
+        method = "isXIncludeAware",
+        args = {}
+    )
+    @KnownFailure("Should handle XIncludeAware flag more gracefully")
+    public void testIsXIncludeAware() {
+        try {
+            spf.setXIncludeAware(false);
+            assertFalse(spf.newSAXParser().isXIncludeAware());
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    /**
+     * @test javax.xml.parsers.SAXParser#parse(java.io.File,
+     *     org.xml.sax.helpers.DefaultHandler)
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify positive functionality properly; not all exceptions are verified.",
+        method = "parse",
+        args = {java.io.File.class, org.xml.sax.helpers.DefaultHandler.class}
+    )
+    public void _test_parseLjava_io_FileLorg_xml_sax_helpers_DefaultHandler()
+    throws Exception {
+
+        for(int i = 0; i < list_wf.length; i++) {
+            HashMap<String, String> hm =
+                new SAXParserTestSupport().readFile(list_out_dh[i].getPath());
+            MyDefaultHandler dh = new MyDefaultHandler();
+            parser.parse(list_wf[i], dh);
+            assertTrue(SAXParserTestSupport.equalsMaps(hm, dh.createData()));
+        }
+
+        for(int i = 0; i < list_nwf.length; i++) {
+            try {
+                MyDefaultHandler dh = new MyDefaultHandler();
+                parser.parse(list_nwf[i], dh);
+                fail("SAXException is not thrown");
+            } catch(org.xml.sax.SAXException se) {
+                //expected
+            }
+        }
+
+        try {
+            MyDefaultHandler dh = new MyDefaultHandler();
+            parser.parse((File) null, dh);
+            fail("java.lang.IllegalArgumentException is not thrown");
+        } catch(java.lang.IllegalArgumentException iae) {
+            //expected
+        }
+
+        try {
+            parser.parse(list_wf[0], (DefaultHandler) null);
+        } catch(java.lang.IllegalArgumentException iae) {
+            fail("java.lang.IllegalArgumentException is thrown");
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.SUFFICIENT,
+        notes = "Sufficient while XML parser situation is still unclear",
+        method = "parse",
+        args = {java.io.File.class, org.xml.sax.HandlerBase.class}
+    )
+    public void testParseFileHandlerBase() {
+        for(int i = 0; i < list_wf.length; i++) {
+            try {
+                HashMap<String, String> hm = sp.readFile(
+                        list_out_hb[i].getPath());
+                MyHandler dh = new MyHandler();
+                parser.parse(list_wf[i], dh);
+                assertTrue(SAXParserTestSupport.equalsMaps(hm, 
+                        dh.createData()));
+            } catch (IOException ioe) {
+                fail("Unexpected IOException " + ioe.toString());
+            } catch (SAXException sax) {
+                fail("Unexpected SAXException " + sax.toString());
+            }
+        }
+
+        for(int i = 0; i < list_nwf.length; i++) {
+            try {
+                MyHandler dh = new MyHandler();
+                parser.parse(list_nwf[i], dh);
+                fail("SAXException is not thrown");
+            } catch(org.xml.sax.SAXException se) {
+                //expected
+            } catch (FileNotFoundException fne) {
+                fail("Unexpected FileNotFoundException " + fne.toString());
+            } catch (IOException ioe) {
+                fail("Unexpected IOException " + ioe.toString());
+            }
+        }
+
+        try {
+            MyHandler dh = new MyHandler();
+            parser.parse((File) null, dh);
+            fail("java.lang.IllegalArgumentException is not thrown");
+        } catch(java.lang.IllegalArgumentException iae) {
+            //expected
+        } catch (IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch(SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+
+        try {
+            parser.parse(list_wf[0], (HandlerBase) null);
+        } catch(java.lang.IllegalArgumentException iae) {
+            fail("java.lang.IllegalArgumentException is thrown");
+        } catch (FileNotFoundException fne) {
+            fail("Unexpected FileNotFoundException " + fne.toString());
+        } catch(IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch(SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+    }
+
+    /**
+     * @test javax.xml.parsers.SAXParser#parse(org.xml.sax.InputSource,
+     *     org.xml.sax.helpers.DefaultHandler)
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify IOException.",
+        method = "parse",
+        args = {org.xml.sax.InputSource.class, org.xml.sax.helpers.DefaultHandler.class}
+    )
+    
+    public void _test_parseLorg_xml_sax_InputSourceLorg_xml_sax_helpers_DefaultHandler()
+    throws Exception {
+
+        for(int i = 0; i < list_wf.length; i++) {
+
+            HashMap<String, String> hm = new SAXParserTestSupport().readFile(
+                    list_out_dh[i].getPath());
+            MyDefaultHandler dh = new MyDefaultHandler();
+            InputSource is = new InputSource(new FileInputStream(list_wf[i]));
+            parser.parse(is, dh);
+            assertTrue(SAXParserTestSupport.equalsMaps(hm, dh.createData()));
+        }
+
+        for(int i = 0; i < list_nwf.length; i++) {
+            try {
+                MyDefaultHandler dh = new MyDefaultHandler();
+                InputSource is = new InputSource(
+                        new FileInputStream(list_nwf[i]));
+                parser.parse(is, dh);
+                fail("SAXException is not thrown");
+            } catch(org.xml.sax.SAXException se) {
+                //expected
+            }
+        }
+
+        try {
+            MyDefaultHandler dh = new MyDefaultHandler();
+            parser.parse((InputSource) null, dh);
+            fail("java.lang.IllegalArgumentException is not thrown");
+        } catch(java.lang.IllegalArgumentException iae) {
+            //expected
+        }
+
+        try {
+            InputSource is = new InputSource(new FileInputStream(list_wf[0]));
+            parser.parse(is, (DefaultHandler) null);
+        } catch(java.lang.IllegalArgumentException iae) {
+            fail("java.lang.IllegalArgumentException is thrown");
+        }
+        
+        try {
+            InputSource is = new InputSource(new BrokenInputStream(new FileInputStream(list_wf[0]), 10));
+            parser.parse(is, (DefaultHandler) null);
+            fail("IOException expected");
+        } catch(IOException e) {
+            // Expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.SUFFICIENT,
+        notes = "Sufficient while XML parser situation is still unclear",
+        method = "parse",
+        args = {org.xml.sax.InputSource.class, org.xml.sax.HandlerBase.class}
+    )
+    public void testParseInputSourceHandlerBase() {
+        for(int i = 0; i < list_wf.length; i++) {
+            try {
+                HashMap<String, String> hm = sp.readFile(
+                        list_out_hb[i].getPath());
+                MyHandler dh = new MyHandler();
+                InputSource is = new InputSource(new FileInputStream(list_wf[i]));
+                parser.parse(is, dh);
+                assertTrue(SAXParserTestSupport.equalsMaps(hm, 
+                        dh.createData()));
+            } catch (IOException ioe) {
+                fail("Unexpected IOException " + ioe.toString());
+            } catch (SAXException sax) {
+                fail("Unexpected SAXException " + sax.toString());
+            }
+        }
+
+        for(int i = 0; i < list_nwf.length; i++) {
+            try {
+                MyHandler dh = new MyHandler();
+                InputSource is = new InputSource(new FileInputStream(list_nwf[i]));
+                parser.parse(is, dh);
+                fail("SAXException is not thrown");
+            } catch(org.xml.sax.SAXException se) {
+                //expected
+            } catch (FileNotFoundException fne) {
+                fail("Unexpected FileNotFoundException " + fne.toString());
+            } catch (IOException ioe) {
+                fail("Unexpected IOException " + ioe.toString());
+            }
+        }
+
+        try {
+            MyHandler dh = new MyHandler();
+            parser.parse((InputSource) null, dh);
+            fail("java.lang.IllegalArgumentException is not thrown");
+        } catch(java.lang.IllegalArgumentException iae) {
+            //expected
+        } catch (IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch(SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+
+        try {
+            InputSource is = new InputSource(new FileInputStream(list_wf[0]));
+            parser.parse(is, (HandlerBase) null);
+        } catch(java.lang.IllegalArgumentException iae) {
+            fail("java.lang.IllegalArgumentException is thrown");
+        } catch (FileNotFoundException fne) {
+            fail("Unexpected FileNotFoundException " + fne.toString());
+        } catch(IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch(SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+
+        // Reader case
+        try {
+            InputSource is = new InputSource(new InputStreamReader(
+                    new FileInputStream(list_wf[0])));
+            parser.parse(is, (HandlerBase) null);
+        } catch(java.lang.IllegalArgumentException iae) {
+            fail("java.lang.IllegalArgumentException is thrown");
+        } catch (FileNotFoundException fne) {
+            fail("Unexpected FileNotFoundException " + fne.toString());
+        } catch(IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch(SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+        
+        // SystemID case
+        try {
+            InputSource is = new InputSource(list_wf[0].toURI().toString());
+            parser.parse(is, (HandlerBase) null);
+        } catch(java.lang.IllegalArgumentException iae) {
+            fail("java.lang.IllegalArgumentException is thrown");
+        } catch (FileNotFoundException fne) {
+            fail("Unexpected FileNotFoundException " + fne.toString());
+        } catch(IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch(SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+        
+        // Inject IOException
+        try {
+            InputStream is = new BrokenInputStream(
+                    new FileInputStream(list_wf[0]), 10);
+            parser.parse(is, (HandlerBase) null, 
+                    SAXParserTestSupport.XML_SYSTEM_ID);
+            fail("IOException expected");
+        } catch(IOException e) {
+            // Expected
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    /**
+     * @test javax.xml.parsers.SAXParser#parse(java.io.InputStream,
+     *     org.xml.sax.helpers.DefaultHandler)
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify IOException.",
+        method = "parse",
+        args = {java.io.InputStream.class, org.xml.sax.helpers.DefaultHandler.class}
+    )
+    public void _test_parseLjava_io_InputStreamLorg_xml_sax_helpers_DefaultHandler()
+    throws Exception {
+
+        for(int i = 0; i < list_wf.length; i++) {
+
+            HashMap<String, String> hm = new SAXParserTestSupport().readFile(
+                    list_out_dh[i].getPath());
+            MyDefaultHandler dh = new MyDefaultHandler();
+            InputStream is = new FileInputStream(list_wf[i]);
+            parser.parse(is, dh);
+            assertTrue(SAXParserTestSupport.equalsMaps(hm, dh.createData()));
+        }
+
+        for(int i = 0; i < list_nwf.length; i++) {
+            try {
+                MyDefaultHandler dh = new MyDefaultHandler();
+                InputStream is = new FileInputStream(list_nwf[i]);
+                parser.parse(is, dh);
+                fail("SAXException is not thrown");
+            } catch(org.xml.sax.SAXException se) {
+                //expected
+            }
+        }
+
+        try {
+            MyDefaultHandler dh = new MyDefaultHandler();
+            parser.parse((InputStream) null, dh);
+            fail("java.lang.IllegalArgumentException is not thrown");
+        } catch(java.lang.IllegalArgumentException iae) {
+            //expected
+        }
+
+        try {
+            InputStream is = new FileInputStream(list_wf[0]);
+            parser.parse(is, (DefaultHandler) null);
+        } catch(java.lang.IllegalArgumentException iae) {
+            fail("java.lang.IllegalArgumentException is thrown");
+        }
+    }
+
+    /**
+     * @test javax.xml.parsers.SAXParser#parse(java.io.InputStream,
+     *     org.xml.sax.helpers.DefaultHandler, java.lang.String)
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify  IOException.",
+        method = "parse",
+        args = {java.io.InputStream.class, org.xml.sax.helpers.DefaultHandler.class, java.lang.String.class}
+    )
+    public void _test_parseLjava_io_InputStreamLorg_xml_sax_helpers_DefaultHandlerLjava_lang_String() {
+        for(int i = 0; i < list_wf.length; i++) {
+            try {
+                HashMap<String, String> hm = sp.readFile(
+                        list_out_hb[i].getPath());
+                MyDefaultHandler dh = new MyDefaultHandler();
+                InputStream is = new FileInputStream(list_wf[i]);
+                parser.parse(is, dh, SAXParserTestSupport.XML_SYSTEM_ID);
+                assertTrue(SAXParserTestSupport.equalsMaps(hm, 
+                        dh.createData()));
+            } catch (IOException ioe) {
+                fail("Unexpected IOException " + ioe.toString());
+            } catch (SAXException sax) {
+                fail("Unexpected SAXException " + sax.toString());
+            }
+        }
+
+        for(int i = 0; i < list_nwf.length; i++) {
+            try {
+                MyDefaultHandler dh = new MyDefaultHandler();
+                InputStream is = new FileInputStream(list_nwf[i]);
+                parser.parse(is, dh, SAXParserTestSupport.XML_SYSTEM_ID);
+                fail("SAXException is not thrown");
+            } catch(org.xml.sax.SAXException se) {
+                //expected
+            } catch (FileNotFoundException fne) {
+                fail("Unexpected FileNotFoundException " + fne.toString());
+            } catch (IOException ioe) {
+                fail("Unexpected IOException " + ioe.toString());
+            }
+        }
+
+        try {
+            MyDefaultHandler dh = new MyDefaultHandler();
+            parser.parse((InputStream) null, dh, 
+                    SAXParserTestSupport.XML_SYSTEM_ID);
+            fail("java.lang.IllegalArgumentException is not thrown");
+        } catch(java.lang.IllegalArgumentException iae) {
+            //expected
+        } catch (IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch(SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+
+        try {
+            InputStream is = new FileInputStream(list_wf[0]);
+            parser.parse(is, (DefaultHandler) null, 
+                    SAXParserTestSupport.XML_SYSTEM_ID);
+        } catch(java.lang.IllegalArgumentException iae) {
+            fail("java.lang.IllegalArgumentException is thrown");
+        } catch (FileNotFoundException fne) {
+            fail("Unexpected FileNotFoundException " + fne.toString());
+        } catch(IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch(SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+//        
+//        for(int i = 0; i < list_wf.length; i++) {
+//
+//            HashMap<String, String> hm = new SAXParserTestSupport().readFile(
+//                    list_out_dh[i].getPath());
+//            MyDefaultHandler dh = new MyDefaultHandler();
+//            InputStream is = new FileInputStream(list_wf[i]);
+//            parser.parse(is, dh, SAXParserTestSupport.XML_SYSTEM_ID);
+//            assertTrue(SAXParserTestSupport.equalsMaps(hm, dh.createData()));
+//        }
+//
+//        for(int i = 0; i < list_nwf.length; i++) {
+//            try {
+//                MyDefaultHandler dh = new MyDefaultHandler();
+//                InputStream is = new FileInputStream(list_nwf[i]);
+//                parser.parse(is, dh, SAXParserTestSupport.XML_SYSTEM_ID);
+//                fail("SAXException is not thrown");
+//            } catch(org.xml.sax.SAXException se) {
+//                //expected
+//            }
+//        }
+//
+//        try {
+//            MyDefaultHandler dh = new MyDefaultHandler();
+//            parser.parse((InputStream) null, dh,
+//                    SAXParserTestSupport.XML_SYSTEM_ID);
+//            fail("java.lang.IllegalArgumentException is not thrown");
+//        } catch(java.lang.IllegalArgumentException iae) {
+//            //expected
+//        }
+//
+//        try {
+//            InputStream is = new FileInputStream(list_wf[0]);
+//            parser.parse(is, (DefaultHandler) null, 
+//                    SAXParserTestSupport.XML_SYSTEM_ID);
+//        } catch(java.lang.IllegalArgumentException iae) {
+//            fail("java.lang.IllegalArgumentException is thrown");
+//        }
+//
+//        // TODO commented out since our parser is nonvalidating and thus never
+//        // tries to load staff.dtd in "/" ... and therefore never can fail with
+//        // an IOException
+//        /*try {
+//            MyDefaultHandler dh = new MyDefaultHandler();
+//            InputStream is = new FileInputStream(list_wf[0]);
+//            parser.parse(is, dh, "/");
+//            fail("Expected IOException was not thrown");
+//        } catch(IOException ioe) {
+//            // expected
+//        }*/
+    }
+
+    @TestTargetNew(
+        level = TestLevel.SUFFICIENT,
+        notes = "Sufficient while XML parser situation is still unclear",
+        method = "parse",
+        args = {java.io.InputStream.class, org.xml.sax.HandlerBase.class}
+    )
+    public void testParseInputStreamHandlerBase() {
+        for(int i = 0; i < list_wf.length; i++) {
+            try {
+                HashMap<String, String> hm = sp.readFile(
+                        list_out_hb[i].getPath());
+                MyHandler dh = new MyHandler();
+                InputStream is = new FileInputStream(list_wf[i]);
+                parser.parse(is, dh);
+                assertTrue(SAXParserTestSupport.equalsMaps(hm, 
+                        dh.createData()));
+            } catch (IOException ioe) {
+                fail("Unexpected IOException " + ioe.toString());
+            } catch (SAXException sax) {
+                fail("Unexpected SAXException " + sax.toString());
+            }
+        }
+
+        for(int i = 0; i < list_nwf.length; i++) {
+            try {
+                MyHandler dh = new MyHandler();
+                InputStream is = new FileInputStream(list_nwf[i]);
+                parser.parse(is, dh);
+                fail("SAXException is not thrown");
+            } catch(org.xml.sax.SAXException se) {
+                //expected
+            } catch (FileNotFoundException fne) {
+                fail("Unexpected FileNotFoundException " + fne.toString());
+            } catch (IOException ioe) {
+                fail("Unexpected IOException " + ioe.toString());
+            }
+        }
+
+        try {
+            MyHandler dh = new MyHandler();
+            parser.parse((InputStream) null, dh);
+            fail("java.lang.IllegalArgumentException is not thrown");
+        } catch(java.lang.IllegalArgumentException iae) {
+            //expected
+        } catch (IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch(SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+
+        try {
+            InputStream is = new FileInputStream(list_wf[0]);
+            parser.parse(is, (HandlerBase) null);
+        } catch(java.lang.IllegalArgumentException iae) {
+            fail("java.lang.IllegalArgumentException is thrown");
+        } catch (FileNotFoundException fne) {
+            fail("Unexpected FileNotFoundException " + fne.toString());
+        } catch(IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch(SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+        
+        // Inject IOException
+        try {
+            InputStream is = new BrokenInputStream(
+                    new FileInputStream(list_wf[0]), 10);
+            parser.parse(is, (HandlerBase) null);
+            fail("IOException expected");
+        } catch(IOException e) {
+            // Expected
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.SUFFICIENT,
+        notes = "Sufficient while XML parser situation is still unclear",
+        method = "parse",
+        args = {java.io.InputStream.class, org.xml.sax.HandlerBase.class, java.lang.String.class}
+    )
+    public void testParseInputStreamHandlerBaseString() {
+        for(int i = 0; i < list_wf.length; i++) {
+            try {
+                HashMap<String, String> hm = sp.readFile(
+                        list_out_hb[i].getPath());
+                MyHandler dh = new MyHandler();
+                InputStream is = new FileInputStream(list_wf[i]);
+                parser.parse(is, dh, SAXParserTestSupport.XML_SYSTEM_ID);
+                assertTrue(SAXParserTestSupport.equalsMaps(hm, 
+                        dh.createData()));
+            } catch (IOException ioe) {
+                fail("Unexpected IOException " + ioe.toString());
+            } catch (SAXException sax) {
+                fail("Unexpected SAXException " + sax.toString());
+            }
+        }
+
+        for(int i = 0; i < list_nwf.length; i++) {
+            try {
+                MyHandler dh = new MyHandler();
+                InputStream is = new FileInputStream(list_nwf[i]);
+                parser.parse(is, dh, SAXParserTestSupport.XML_SYSTEM_ID);
+                fail("SAXException is not thrown");
+            } catch(org.xml.sax.SAXException se) {
+                //expected
+            } catch (FileNotFoundException fne) {
+                fail("Unexpected FileNotFoundException " + fne.toString());
+            } catch (IOException ioe) {
+                fail("Unexpected IOException " + ioe.toString());
+            }
+        }
+
+        try {
+            MyHandler dh = new MyHandler();
+            parser.parse((InputStream) null, dh, 
+                    SAXParserTestSupport.XML_SYSTEM_ID);
+            fail("java.lang.IllegalArgumentException is not thrown");
+        } catch(java.lang.IllegalArgumentException iae) {
+            //expected
+        } catch (IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch(SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+
+        try {
+            InputStream is = new FileInputStream(list_wf[0]);
+            parser.parse(is, (HandlerBase) null, 
+                    SAXParserTestSupport.XML_SYSTEM_ID);
+        } catch(java.lang.IllegalArgumentException iae) {
+            fail("java.lang.IllegalArgumentException is thrown");
+        } catch (FileNotFoundException fne) {
+            fail("Unexpected FileNotFoundException " + fne.toString());
+        } catch(IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch(SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+        
+        // Inject IOException
+        try {
+            InputStream is = new BrokenInputStream(
+                    new FileInputStream(list_wf[0]), 10);
+            parser.parse(is, (HandlerBase) null, 
+                    SAXParserTestSupport.XML_SYSTEM_ID);
+            fail("IOException expected");
+        } catch(IOException e) {
+            // Expected
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    /**
+     * @test javax.xml.parsers.SAXParser#parse(java.lang.String,
+     *     org.xml.sax.helpers.DefaultHandler)
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify IOException.",
+        method = "parse",
+        args = {java.lang.String.class, org.xml.sax.helpers.DefaultHandler.class}
+    )
+    public void _test_parseLjava_lang_StringLorg_xml_sax_helpers_DefaultHandler()
+    throws Exception {
+
+        for(int i = 0; i < list_wf.length; i++) {
+
+            HashMap<String, String> hm = new SAXParserTestSupport().readFile(
+                    list_out_dh[i].getPath());
+            MyDefaultHandler dh = new MyDefaultHandler();
+            parser.parse(list_wf[i].getPath(), dh);
+            assertTrue(SAXParserTestSupport.equalsMaps(hm, dh.createData()));
+        }
+
+        for(int i = 0; i < list_nwf.length; i++) {
+            try {
+                MyDefaultHandler dh = new MyDefaultHandler();
+                parser.parse(list_nwf[i].getPath(), dh);
+                fail("SAXException is not thrown");
+            } catch(org.xml.sax.SAXException se) {
+                //expected
+            }
+        }
+
+        try {
+            MyDefaultHandler dh = new MyDefaultHandler();
+            parser.parse((String) null, dh);
+            fail("java.lang.IllegalArgumentException is not thrown");
+        } catch(java.lang.IllegalArgumentException iae) {
+            //expected
+        }
+
+        try {
+            parser.parse(list_wf[0].getPath(), (DefaultHandler) null);
+        } catch(java.lang.IllegalArgumentException iae) {
+            fail("java.lang.IllegalArgumentException is thrown");
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.SUFFICIENT,
+        notes = "Sufficient while XML parser situation is still unclear",
+        method = "parse",
+        args = {java.lang.String.class, org.xml.sax.HandlerBase.class}
+    )
+    public void testParseStringHandlerBase() {
+        for(int i = 0; i < list_wf.length; i++) {
+            try {
+                HashMap<String, String> hm = sp.readFile(
+                        list_out_hb[i].getPath());
+                MyHandler dh = new MyHandler();
+                parser.parse(list_wf[i].toURI().toString(), dh);
+                assertTrue(SAXParserTestSupport.equalsMaps(hm, 
+                        dh.createData()));
+            } catch (IOException ioe) {
+                fail("Unexpected IOException " + ioe.toString());
+            } catch (SAXException sax) {
+                fail("Unexpected SAXException " + sax.toString());
+            }
+        }
+
+        for(int i = 0; i < list_nwf.length; i++) {
+            try {
+                MyHandler dh = new MyHandler();
+                parser.parse(list_nwf[i].toURI().toString(), dh);
+                fail("SAXException is not thrown");
+            } catch(org.xml.sax.SAXException se) {
+                //expected
+            } catch (FileNotFoundException fne) {
+                fail("Unexpected FileNotFoundException " + fne.toString());
+            } catch (IOException ioe) {
+                fail("Unexpected IOException " + ioe.toString());
+            }
+        }
+
+        try {
+            MyHandler dh = new MyHandler();
+            parser.parse((String) null, dh);
+            fail("java.lang.IllegalArgumentException is not thrown");
+        } catch(java.lang.IllegalArgumentException iae) {
+            //expected
+        } catch (IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch(SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+
+        try {
+            parser.parse(list_wf[0].toURI().toString(), (HandlerBase) null);
+        } catch(java.lang.IllegalArgumentException iae) {
+            fail("java.lang.IllegalArgumentException is thrown");
+        } catch (FileNotFoundException fne) {
+            fail("Unexpected FileNotFoundException " + fne.toString());
+        } catch(IOException ioe) {
+            fail("Unexpected IOException " + ioe.toString());
+        } catch(SAXException sax) {
+            fail("Unexpected SAXException " + sax.toString());
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "reset",
+        args = { }
+    )
+    @KnownFailure("Android DocumentBuilder should implement reset() properly")
+    public void testReset() {
+        try {
+            spf = SAXParserFactory.newInstance();
+            parser = spf.newSAXParser();
+
+            parser.setProperty(LEXICAL_HANDLER_PROPERTY, new MockHandler(new MethodLogger()));
+            parser.reset();
+            assertEquals(null, parser.getProperty(LEXICAL_HANDLER_PROPERTY));
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getParser",
+        args = { }
+    )
+    public void testGetParser() {
+        spf = SAXParserFactory.newInstance();
+        try {
+            Parser parser = spf.newSAXParser().getParser();
+            assertNotNull(parser);
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getXMLReader",
+        args = { }
+    )
+    public void testGetReader() {
+        spf = SAXParserFactory.newInstance();
+        try {
+            XMLReader reader = spf.newSAXParser().getXMLReader();
+            assertNotNull(reader);
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getProperty",
+            args = { String.class }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setProperty",
+            args = { String.class, Object.class }
+        )
+    })
+    @KnownFailure("ExpatParser should allow to clear properties")
+    public void testSetGetProperty() {
+        // Ordinary case
+        String validName = "http://xml.org/sax/properties/lexical-handler";
+        LexicalHandler validValue = new MockHandler(new MethodLogger());            
+
+        try {
+            SAXParser parser = spf.newSAXParser();
+            parser.setProperty(validName, validValue);
+            assertEquals(validValue, parser.getProperty(validName));
+            
+            parser.setProperty(validName, null);
+            assertEquals(null, parser.getProperty(validName));
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        // Unsupported property
+        try {
+            SAXParser parser = spf.newSAXParser();
+            parser.setProperty("foo", "bar");
+            fail("SAXNotRecognizedException expected");
+        } catch (SAXNotRecognizedException e) {
+            // Expected
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        try {
+            SAXParser parser = spf.newSAXParser();
+            parser.getProperty("foo");
+            fail("SAXNotRecognizedException expected");
+        } catch (SAXNotRecognizedException e) {
+            // Expected
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        // No name case
+        try {
+            SAXParser parser = spf.newSAXParser();
+            parser.setProperty(null, "bar");
+            fail("NullPointerException expected");
+        } catch (NullPointerException e) {
+            // Expected
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        try {
+            SAXParser parser = spf.newSAXParser();
+            parser.getProperty(null);
+            fail("NullPointerException expected");
+        } catch (NullPointerException e) {
+            // Expected
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+    
+}
+
diff --git a/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTestSupport.java b/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTestSupport.java
new file mode 100644
index 0000000..bc5e6a1
--- /dev/null
+++ b/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTestSupport.java
@@ -0,0 +1,492 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.javax.xml.parsers;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.HandlerBase;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * Support for SAXParserTest. Shares the element keys used in the golden files. 
+ * Compares the result of the parser with golden data.
+ * Contains the handler classes used to track the output of the parser.
+ */
+class SAXParserTestSupport {
+
+    public static final char SEPARATOR_ELEMENT = '^';
+    public static final char SEPARATOR_STRING = '$';
+    public static final char SEPARATOR_DATA = '#';
+
+    public static final String XML_WF = "/wf/";
+    public static final String XML_NWF = "/nwf/";
+
+    public static final String XML_WF_OUT_DH = "/out_dh/";
+    public static final String XML_WF_OUT_HB = "/out_hb/";
+
+    public static final String XML_SYSTEM_ID = "." + "/systemid/";
+
+    public static final String KEY_IS_START_DOC = "isEndDocument";
+    public static final String KEY_IS_END_DOC = "isStartDocument";
+    public static final String KEY_TEXT = "text";
+    public static final String KEY_ERROR = "error";
+    public static final String KEY_FATAL_ERROR = "fatalError";
+    public static final String KEY_WARNING = "warning";
+    public static final String KEY_END_ELEMENT = "endEement";
+    public static final String KEY_END_PREFIX_MAPPING = "endPrefixMapping";
+    public static final String KEY_IGNORABLE_WHITE_SPACE = 
+        "ignorableWhitespace";
+    public static final String KEY_NOTATION_DECL = "notationDecl";
+    public static final String KEY_PROCESSING_INSTRUCTION = 
+        "processingInstruction";
+    public static final String KEY_RESOLVE_ENTITY = "resolveEntity";
+    public static final String KEY_DOCUMENT_LOCATORS = "documentLocators";
+    public static final String KEY_SKIPPED_ENTITY = "skippedEntity";
+    public static final String KEY_START_ELEMENT = "startElement";
+    public static final String KEY_START_PREFIX_MAPPING = "startPrefixMapping";
+    public static final String KEY_UNPARSED_ENTITY_DECL = "unparsedEntityDecl";
+
+    static String [] KEYS = {KEY_IS_START_DOC, KEY_IS_END_DOC, KEY_TEXT, 
+            KEY_ERROR, KEY_FATAL_ERROR, KEY_WARNING, KEY_END_ELEMENT,
+            KEY_END_PREFIX_MAPPING, KEY_PROCESSING_INSTRUCTION,
+            KEY_SKIPPED_ENTITY, KEY_START_ELEMENT,
+            KEY_START_PREFIX_MAPPING};
+
+    static {
+        String tmp = System.getProperty("java.io.tmpdir", ".");
+        
+        new File(tmp).mkdirs();
+        new File(tmp, XML_WF).mkdirs();
+        new File(tmp, XML_NWF).mkdirs();
+        new File(tmp, XML_WF_OUT_DH).mkdirs();
+        new File(tmp, XML_WF_OUT_HB).mkdirs();
+    }
+    
+    /**
+     * Initialize the SAXParserTest reference by filling in the data from the
+     * file passed to the method. This will be the reference to compare
+     * against with the output of the parser.
+     */
+    public HashMap<String, String> readFile(String fileName) {
+        HashMap<String, String> storage = new HashMap<String, String>();
+        try {
+
+            InputStream is = new FileInputStream(fileName);
+
+            int c = is.read();
+
+            StringBuffer str = new StringBuffer();
+            int i = 0;
+            while(c != -1) {
+                if((char)c == SEPARATOR_DATA) {
+                  //  if(str.length() > 0) {
+                        if(i < KEYS.length) {
+                            storage.put(KEYS[i], str.toString());
+                        //    System.out.println(str.toString());
+                            str.setLength(0);
+                            i++;
+                        }
+                  //  }
+                } else {
+                    str.append((char)c);
+                }
+                try {
+                    c = is.read();
+                } catch (Exception e) {
+                    c = -1;
+                }
+            }
+            try {
+                is.close();
+            } catch (IOException e) {
+            }
+
+        } catch(IOException ioe) {
+            System.out.println("IOException during processing the file: "
+                    + fileName);
+        }
+        return storage;
+    }
+
+    /**
+     * Compares the content of two HashMaps. One map should be the reference
+     * containing the correct string for each xml document element and the other
+     * should contain the elements filled with output from the parser.
+     * 
+     * @param original the reference
+     * @param result the result of the parser
+     * @return true if they're equal.
+     */
+    public static boolean equalsMaps(HashMap<String, String> original, 
+            HashMap<String, String> result) {
+
+        if(original == null && result == null) {
+            return true;
+        } else {
+            if(original.size() != result.size()) return false;
+
+            for(int i = 0; i < KEYS.length; i++) {
+                if(!original.get(KEYS[i]).equals(result.get(KEYS[i]))) {
+                    System.out.println("for "+KEYS[i]+": original:" + 
+                            original.get(KEYS[i]));
+                    System.out.println();
+                    System.out.println("  result:" + result.get(KEYS[i]));
+                    System.out.println();
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
+    static class MyDefaultHandler extends DefaultHandler {
+
+        public StringBuffer data_isEndDocument = new StringBuffer();
+        public StringBuffer data_isStartDocument = new StringBuffer();
+        public StringBuffer data_text = new StringBuffer();
+        public StringBuffer data_error = new StringBuffer();
+        public StringBuffer data_fatalError = new StringBuffer();
+        public StringBuffer data_warning = new StringBuffer();
+        public StringBuffer data_endElement = new StringBuffer();
+        public StringBuffer data_endPrefixMapping = new StringBuffer();
+        public StringBuffer data_processingInstruction = new StringBuffer();
+        public StringBuffer data_skippedEntity = new StringBuffer();
+        public StringBuffer data_startElement = new StringBuffer();
+        public StringBuffer data_startPrefixMapping = new StringBuffer();
+
+        public HashMap<String, String> createData() {
+            HashMap<String, String> hm = new HashMap<String, String>();
+            hm.put(KEY_IS_END_DOC, data_isEndDocument.toString());
+            hm.put(KEY_IS_START_DOC, data_isStartDocument.toString());
+            hm.put(KEY_TEXT, data_text.toString());
+            hm.put(KEY_ERROR, data_error.toString());
+            hm.put(KEY_FATAL_ERROR, data_fatalError.toString());
+            hm.put(KEY_WARNING, data_warning.toString());
+            hm.put(KEY_END_ELEMENT, data_endElement.toString());
+            hm.put(KEY_END_PREFIX_MAPPING, data_endPrefixMapping.toString());
+
+            hm.put(KEY_PROCESSING_INSTRUCTION,
+                    data_processingInstruction.toString());
+            hm.put(KEY_SKIPPED_ENTITY, data_skippedEntity.toString());
+            hm.put(KEY_START_ELEMENT, data_startElement.toString());
+            hm.put(KEY_START_PREFIX_MAPPING,
+                    data_startPrefixMapping.toString());
+            return hm;
+        }
+
+        public void printMap() {
+            System.out.print(data_isStartDocument.toString() + SEPARATOR_DATA +
+                    data_isEndDocument.toString() + SEPARATOR_DATA +
+                    data_text.toString() + SEPARATOR_DATA +
+                    data_error.toString()+ SEPARATOR_DATA +
+                    data_fatalError.toString()+ SEPARATOR_DATA +
+                    data_warning.toString()+ SEPARATOR_DATA +
+                    data_endElement.toString() + SEPARATOR_DATA+
+                    data_endPrefixMapping.toString()+ SEPARATOR_DATA +
+                    data_processingInstruction.toString() + SEPARATOR_DATA +
+                    data_skippedEntity.toString() +  SEPARATOR_DATA +
+                    data_startElement.toString() + SEPARATOR_DATA +
+                    data_startPrefixMapping.toString()+ SEPARATOR_DATA);
+        }
+
+        @Override
+        public void characters(char[] ch, int start, int length) {
+            String str = new String(ch, start, length);
+            data_text.append(str);
+            // different sax parsers are allowed to handle chunking differently,
+            // therefore we cannot rely on identical chunks being delivered.
+            //data_text.append(ParsingSupport.SEPARATOR_ELEMENT);
+        }
+
+        @Override
+        public void endDocument() {
+            data_isEndDocument.append(true);
+            data_isEndDocument.append(SEPARATOR_ELEMENT);
+        }
+
+        @Override
+        public void endElement(String uri, String localName, String qName) {
+            StringBuffer sb = new StringBuffer();
+            sb.append(uri);
+            sb.append(SEPARATOR_STRING);
+            sb.append(localName);
+            sb.append(SEPARATOR_STRING);
+            sb.append(qName);
+            data_endElement.append(sb);
+            data_endElement.append(SEPARATOR_ELEMENT);
+        }
+
+        @Override
+        public void endPrefixMapping(String prefix) {
+            data_endPrefixMapping.append(prefix);
+            data_endPrefixMapping.append(SEPARATOR_ELEMENT);
+        }
+
+        @Override
+        public void error(SAXParseException e) {
+            data_error.append(e);
+            data_error.append(SEPARATOR_ELEMENT);
+        }
+
+        @Override
+        public void fatalError(SAXParseException e) {
+            data_fatalError.append(e);
+            data_fatalError.append(SEPARATOR_ELEMENT);
+        }
+
+        @Override
+        public void ignorableWhitespace(char[] ch, int start, int length) {
+            /*    String s = new String(ch, start, length);
+            ignorableWhitespace.append(s);
+            ignorableWhitespace.append(ParsingSupport.SEPARATOR_ELEMENT);*/
+        }
+
+        @Override
+        public void notationDecl(String name, String publicId,
+                String systemId) {
+            /* data_notationDecl.append(name + ParsingSupport.SEPARATOR_STRING +
+                              publicId + ParsingSupport.SEPARATOR_STRING +
+                              systemId + ParsingSupport.SEPARATOR_STRING);
+            data_notationDecl.append(ParsingSupport.SEPARATOR_ELEMENT);*/
+        }
+
+        @Override
+        public void processingInstruction(String target, String data) {
+            data_processingInstruction.append(target + SEPARATOR_STRING + data);
+            data_processingInstruction.append(SEPARATOR_ELEMENT);
+        }
+
+        @Override
+        public InputSource    resolveEntity(String publicId, String systemId) {
+            // data_resolveEntity.append(publicId + 
+            //            ParsingSupport.SEPARATOR_STRING + systemId);
+            // data_resolveEntity.append(ParsingSupport.SEPARATOR_ELEMENT);
+            return null;
+        }
+
+        @Override
+        public void setDocumentLocator(Locator locator) {
+            //       data_documentLocators.append(locator);
+            // data_documentLocators.append(ParsingSupport.SEPARATOR_ELEMENT);
+        }
+
+        @Override
+        public void skippedEntity(String name) {
+            data_skippedEntity.append(name);
+            data_skippedEntity.append(SEPARATOR_ELEMENT);
+        }
+
+        @Override
+        public void startDocument() {
+            data_isStartDocument.append(true);
+            data_isStartDocument.append(SEPARATOR_ELEMENT);
+        }
+
+        @Override
+        public void startElement(String uri, String localName, String qName,
+                Attributes attributes) {
+            data_startElement.append(uri);
+            data_startElement.append(SEPARATOR_STRING);
+            data_startElement.append(localName);
+            data_startElement.append(SEPARATOR_STRING);
+            data_startElement.append(qName);
+
+            for(int i = 0; i < attributes.getLength(); i ++)
+                data_startElement.append(
+                        SEPARATOR_STRING +attributes.getQName(i) +
+                        SEPARATOR_STRING + attributes.getValue(i));
+
+            data_isStartDocument.append(SEPARATOR_ELEMENT);
+        }
+
+        @Override
+        public void startPrefixMapping(String prefix, String uri) {
+            data_startPrefixMapping.append(prefix + SEPARATOR_STRING + uri);
+        }
+
+        @Override
+        public void unparsedEntityDecl(String name, String publicId,
+                String systemId, String notationName) {
+            // data_unparsedEntityDecl.append(name 
+            //     + ParsingSupport.SEPARATOR_STRING + publicId 
+            //     + ParsingSupport.SEPARATOR_STRING
+            //     + systemId + ParsingSupport.SEPARATOR_STRING + notationName);
+        }
+
+        @Override
+        public void warning(SAXParseException e) {
+            data_warning.append(e);
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    static class MyHandler extends HandlerBase {
+
+        public StringBuffer data_isEndDocument = new StringBuffer();
+        public StringBuffer data_isStartDocument = new StringBuffer();
+        public StringBuffer data_text = new StringBuffer();
+        public StringBuffer data_error = new StringBuffer();
+        public StringBuffer data_fatalError = new StringBuffer();
+        public StringBuffer data_warning = new StringBuffer();
+        public StringBuffer data_endElement = new StringBuffer();
+        public StringBuffer data_endPrefixMapping = new StringBuffer();
+        public StringBuffer data_processingInstruction = new StringBuffer();
+        public StringBuffer data_skippedEntity = new StringBuffer();
+        public StringBuffer data_startElement = new StringBuffer();
+        public StringBuffer data_startPrefixMapping = new StringBuffer();
+
+        public void printMap() {
+            System.out.print(data_isStartDocument.toString() + SEPARATOR_DATA +
+                    data_isEndDocument.toString() + SEPARATOR_DATA +
+                    data_text.toString() + SEPARATOR_DATA +
+                    data_error.toString()+ SEPARATOR_DATA +
+                    data_fatalError.toString()+ SEPARATOR_DATA +
+                    data_warning.toString()+ SEPARATOR_DATA +
+                    data_endElement.toString() + SEPARATOR_DATA+
+                    data_endPrefixMapping.toString()+ SEPARATOR_DATA +
+                    data_processingInstruction.toString() + SEPARATOR_DATA +
+                    data_skippedEntity.toString() +  SEPARATOR_DATA +
+                    data_startElement.toString() + SEPARATOR_DATA +
+                    data_startPrefixMapping.toString()+ SEPARATOR_DATA);
+        }
+
+        public HashMap<String, String> createData() {
+            HashMap<String, String> hm = new HashMap<String, String>();
+            hm.put(KEY_IS_END_DOC, data_isEndDocument.toString());
+            hm.put(KEY_IS_START_DOC, data_isStartDocument.toString());
+            hm.put(KEY_TEXT, data_text.toString());
+            hm.put(KEY_ERROR, data_error.toString());
+            hm.put(KEY_FATAL_ERROR, data_fatalError.toString());
+            hm.put(KEY_WARNING, data_warning.toString());
+            hm.put(KEY_END_ELEMENT, data_endElement.toString());
+            hm.put(KEY_END_PREFIX_MAPPING, data_endPrefixMapping.toString());
+            hm.put(KEY_PROCESSING_INSTRUCTION,
+                    data_processingInstruction.toString());
+            hm.put(KEY_SKIPPED_ENTITY, data_skippedEntity.toString());
+            hm.put(KEY_START_ELEMENT, data_startElement.toString());
+            hm.put(KEY_START_PREFIX_MAPPING,
+                    data_startPrefixMapping.toString());
+            return hm;
+        }
+
+        @Override
+        public void characters(char[] ch, int start, int length) {
+            String str = new String(ch, start, length);
+            data_text.append(str);
+            // different sax parsers are allowed to handle chunking differently,
+            // therefore we cannot rely on identical chunks being delivered.
+            //data_text.append(ParsingSupport.SEPARATOR_ELEMENT);
+        }
+
+        @Override
+        public void    endDocument() {
+            data_isEndDocument.append(true);
+            data_isEndDocument.append(SEPARATOR_ELEMENT);
+        }
+
+        public void endElement(String uri, String localName, String qName) {
+            StringBuffer sb = new StringBuffer();
+            sb.append(uri);
+            sb.append(SEPARATOR_STRING);
+            sb.append(localName);
+            sb.append(SEPARATOR_STRING);
+            sb.append(qName);
+            data_endElement.append(sb);
+            data_endElement.append(SEPARATOR_ELEMENT);
+        }
+
+        @Override
+        public void error(SAXParseException e) {
+            data_error.append(e);
+            data_error.append(SEPARATOR_ELEMENT);
+        }
+
+        @Override
+        public void fatalError(SAXParseException e) {
+            data_fatalError.append(e);
+            data_fatalError.append(SEPARATOR_ELEMENT);
+        }
+
+        @Override
+        public void ignorableWhitespace(char[] ch, int start, int length) {
+
+        }
+
+        @Override
+        public void notationDecl(String name, String publicId, 
+                String systemId) {
+
+        }
+
+        @Override
+        public void processingInstruction(String target, String data) {
+            data_processingInstruction.append(target + SEPARATOR_STRING + data);
+            data_processingInstruction.append(SEPARATOR_ELEMENT);
+        }
+
+        @Override
+        public InputSource    resolveEntity(String publicId, String systemId) {
+            return null;
+        }
+
+        @Override
+        public void setDocumentLocator(Locator locator) {
+
+        }
+
+        @Override
+        public void startDocument() {
+            data_isStartDocument.append(true);
+            data_isStartDocument.append(SEPARATOR_ELEMENT);
+        }
+
+        public void startElement(String uri, String localName, String qName,
+                Attributes attributes) {
+            data_startElement.append(uri);
+            data_startElement.append(SEPARATOR_STRING);
+            data_startElement.append(localName);
+            data_startElement.append(SEPARATOR_STRING);
+            data_startElement.append(qName);
+
+            for(int i = 0; i < attributes.getLength(); i ++)
+                data_startElement.append(SEPARATOR_STRING
+                        + attributes.getQName(i) +
+                        SEPARATOR_STRING + attributes.getValue(i));
+
+            data_isStartDocument.append(SEPARATOR_ELEMENT);
+        }
+
+        @Override
+        public void unparsedEntityDecl(String name, String publicId,
+                String systemId, String notationName) {
+
+        }
+
+        @Override
+        public void warning(SAXParseException e) {
+            data_warning.append(e);
+        }
+    }
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/AllTests.java b/xml/src/test/java/tests/api/org/xml/sax/AllTests.java
new file mode 100644
index 0000000..9c29178
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/AllTests.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(AllTests.suite());
+    }
+
+    public static Test suite() {
+        TestSuite suite = tests.TestSuiteFactory.createTestSuite("Tests for org.xml.sax package");
+        // $JUnit-BEGIN$
+
+        suite.addTestSuite(HandlerBaseTest.class);
+        suite.addTestSuite(InputSourceTest.class);
+        suite.addTestSuite(SAXExceptionTest.class);
+        suite.addTestSuite(SAXNotRecognizedExceptionTest.class);
+        suite.addTestSuite(SAXNotSupportedExceptionTest.class);
+        suite.addTestSuite(SAXParseExceptionTest.class);
+
+        suite.addTest(tests.api.org.xml.sax.ext.AllTests.suite());
+        suite.addTest(tests.api.org.xml.sax.helpers.AllTests.suite());
+        
+        // $JUnit-END$
+        return suite;
+    }
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/HandlerBaseTest.java b/xml/src/test/java/tests/api/org/xml/sax/HandlerBaseTest.java
new file mode 100644
index 0000000..7c7f591
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/HandlerBaseTest.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.AttributeList;
+import org.xml.sax.HandlerBase;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.AttributeListImpl;
+import org.xml.sax.helpers.LocatorImpl;
+
+@SuppressWarnings("deprecation")
+@TestTargetClass(HandlerBase.class)
+public class HandlerBaseTest extends TestCase {
+
+    /*
+     * Note: most of the tests have to check for an empty implementation of the
+     * respective methods and, as a result, are somewhat trivial.
+     */
+    
+    private HandlerBase h = new HandlerBase();
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "resolveEntity",
+        args = { String.class, String.class }
+    )
+    public void testResolveEntity() {
+        try {
+            h.resolveEntity("publicID", "systemID");
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }        
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "notationDecl",
+        args = { String.class, String.class, String.class }
+    )
+    public void testNotationDecl() {
+        h.notationDecl("name", "publicID", "systemID");
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "unparsedEntityDecl",
+        args = { String.class, String.class, String.class, String.class }
+    )
+    public void testUnparsedEntityDecl() {
+        h.unparsedEntityDecl("name", "publicID", "systemID", "notationName");
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setDocumentLocator",
+        args = { org.xml.sax.Locator.class }
+    )
+    public void testSetDocumentLocator() {
+        h.setDocumentLocator(new LocatorImpl());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "startDocument",
+        args = { }
+    )
+    public void testStartDocument() {
+        try {
+            h.startDocument();
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "endDocument",
+        args = { }
+    )
+    public void testEndDocument() {
+        try {
+            h.endDocument();
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "startElement",
+        args = { String.class, AttributeList.class }
+    )
+    public void testStartElement() {
+        try {
+            h.startElement("name", new AttributeListImpl());
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "endElement",
+        args = { String.class }
+    )
+    public void testEndElement() {
+        try {
+            h.endElement("name");
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "characters",
+        args = { char[].class, int.class, int.class }
+    )
+    public void testCharacters() {
+        try {
+            h.characters("The quick brown fox".toCharArray(), 4, 11);
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "ignorableWhitespace",
+        args = { char[].class, int.class, int.class }
+    )
+    public void testIgnorableWhitespace() {
+        try {
+            h.ignorableWhitespace("                   ".toCharArray(), 4, 11);
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "processingInstruction",
+        args = { String.class, String.class }
+    )
+    public void testProcessingInstruction() {
+        try {
+            h.processingInstruction("target", "data");
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "warning",
+        args = { org.xml.sax.SAXParseException.class }
+    )
+    public void testWarning() {
+        try {
+            h.warning(new SAXParseException("Foo", new LocatorImpl()));
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "error",
+        args = { org.xml.sax.SAXParseException.class }
+    )
+    public void testError() {
+        try {
+            h.error(new SAXParseException("Foo", new LocatorImpl()));
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "fatalError",
+        args = { org.xml.sax.SAXParseException.class }
+    )
+    public void testFatalError() {
+        // Ordinary case
+        try {
+            h.fatalError(new SAXParseException("Foo", new LocatorImpl()));
+            fail("SAXException expected");
+        } catch (SAXException e) {
+            // Expected
+        }
+        
+        // No exception
+        try {
+            h.fatalError(null);
+            fail("NullPointerException expected");
+        } catch (SAXException e) {
+            fail("NullPointerException expected");
+        } catch (NullPointerException e) {
+            // Expected
+        }
+        
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/InputSourceTest.java b/xml/src/test/java/tests/api/org/xml/sax/InputSourceTest.java
new file mode 100644
index 0000000..7c73b52
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/InputSourceTest.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringReader;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.InputSource;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+@TestTargetClass(InputSource.class)
+public class InputSourceTest extends TestCase {
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "InputSource",
+        args = { }
+    )
+    public void testInputSource() {
+        InputSource i = new InputSource();
+        
+        assertNull(i.getByteStream());
+        assertNull(i.getCharacterStream());
+        assertNull(i.getEncoding());
+        assertNull(i.getPublicId());
+        assertNull(i.getSystemId());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "InputSource",
+        args = { String.class }
+    )
+    public void testInputSourceString() {
+        InputSource i = new InputSource("Foo");
+        
+        assertNull(i.getByteStream());
+        assertNull(i.getCharacterStream());
+        assertNull(i.getEncoding());
+        assertNull(i.getPublicId());
+        assertEquals("Foo", i.getSystemId());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "InputSource",
+        args = { InputStream.class }
+    )
+    public void testInputSourceInputStream() {
+        ByteArrayInputStream bais = new ByteArrayInputStream(new byte[0]);
+        
+        // Ordinary case
+        InputSource i = new InputSource(bais);
+        
+        assertEquals(bais, i.getByteStream());
+        assertNull(i.getCharacterStream());
+        assertNull(i.getEncoding());
+        assertNull(i.getPublicId());
+        assertNull(i.getSystemId());
+
+        // No input stream
+        i = new InputSource((InputStream)null);
+        
+        assertNull(i.getByteStream());
+        assertNull(i.getCharacterStream());
+        assertNull(i.getEncoding());
+        assertNull(i.getPublicId());
+        assertNull(i.getSystemId());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "InputSource",
+        args = { Reader.class }
+    )
+    public void testInputSourceReader() {
+        StringReader sr = new StringReader("Hello, world.");
+        
+        // Ordinary case
+        InputSource i = new InputSource(sr);
+        
+        assertNull(i.getByteStream());
+        assertEquals(sr, i.getCharacterStream());
+        assertNull(i.getEncoding());
+        assertNull(i.getPublicId());
+        assertNull(i.getSystemId());
+
+        // No reader
+        i = new InputSource((Reader)null);
+        
+        assertNull(i.getByteStream());
+        assertNull(i.getCharacterStream());
+        assertNull(i.getEncoding());
+        assertNull(i.getPublicId());
+        assertNull(i.getSystemId());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setPublicId",
+            args = { String.class }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getPublicId",
+            args = {  }
+        )
+    })
+    public void testSetPublicIdGetPublicId() {
+        InputSource i = new InputSource();
+        
+        i.setPublicId("Foo");
+        assertEquals("Foo", i.getPublicId());
+        
+        i.setPublicId(null);
+        assertNull(i.getPublicId());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setSystemId",
+            args = { String.class }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getSystemId",
+            args = {  }
+        )
+    })
+    public void testSetSystemIdGetSystemId() {
+        InputSource i = new InputSource();
+        
+        i.setSystemId("Foo");
+        assertEquals("Foo", i.getSystemId());
+        
+        i.setSystemId(null);
+        assertNull(i.getSystemId());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setByteStream",
+            args = { InputStream.class }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getByteStream",
+            args = {  }
+        )
+    })
+    public void testSetByteStreamGetByteStream() {
+        ByteArrayInputStream bais = new ByteArrayInputStream(new byte[0]);
+        
+        InputSource i = new InputSource();
+        
+        // Ordinary case
+        i.setByteStream(bais);
+        
+        assertEquals(bais, i.getByteStream());
+
+        // No input stream
+        i.setByteStream(null);
+        
+        assertNull(i.getByteStream());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEncoding",
+            args = { String.class }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getEncoding",
+            args = {  }
+        )
+    })
+    public void testSetEncodingGetEncoding() {
+        InputSource i = new InputSource();
+        
+        // Ordinary case
+        i.setEncoding("Klingon");
+        
+        assertEquals("Klingon", i.getEncoding());
+
+        // No encoding
+        i.setEncoding(null);
+        
+        assertNull(i.getEncoding());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setCharacterStream",
+            args = { Reader.class }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getCharacterStream",
+            args = {  }
+        )
+    })
+    public void testSetCharacterStreamGetCharacterStream() {
+        StringReader sr = new StringReader("Hello, world.");
+        
+        InputSource i = new InputSource();
+        
+        // Ordinary case
+        i.setCharacterStream(sr);
+        
+        assertNull(i.getByteStream());
+        assertEquals(sr, i.getCharacterStream());
+        assertNull(i.getEncoding());
+        assertNull(i.getPublicId());
+        assertNull(i.getSystemId());
+
+        // No reader
+        i.setCharacterStream(null);
+        
+        assertNull(i.getByteStream());
+        assertNull(i.getCharacterStream());
+        assertNull(i.getEncoding());
+        assertNull(i.getPublicId());
+        assertNull(i.getSystemId());
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/SAXExceptionTest.java b/xml/src/test/java/tests/api/org/xml/sax/SAXExceptionTest.java
new file mode 100644
index 0000000..afc1f8d
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/SAXExceptionTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+@TestTargetClass(SAXException.class)
+public class SAXExceptionTest extends TestCase {
+
+    public static final String ERR = "Houston, we have a problem";
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "SAXException",
+        args = { }
+    )
+    public void testSAXParseException() {
+        SAXException e = new SAXException();
+        
+        assertNull(e.getMessage());
+        assertNull(e.getException());
+    }
+    
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "SAXException",
+        args = { String.class, Exception.class }
+    )
+    public void testSAXException_String_Exception() {
+        Exception c = new Exception();
+        
+        // Ordinary case
+        SAXException e = new SAXException(ERR, c);
+        
+        assertEquals(ERR, e.getMessage());
+        assertEquals(c, e.getException());
+
+        // No message
+        e = new SAXException(null, c);
+        
+        assertNull(e.getMessage());
+        assertEquals(c, e.getException());
+        
+        // No cause
+        e = new SAXParseException(ERR, null);
+        
+        assertEquals(ERR, e.getMessage());
+        assertNull(e.getException());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "SAXException",
+        args = { String.class }
+    )
+    public void testSAXException_String() {
+        // Ordinary case
+        SAXException e = new SAXException(ERR);
+        
+        assertEquals(ERR, e.getMessage());
+        assertNull(e.getException());
+
+        // No message
+        e = new SAXException((String)null);
+        
+        assertNull(e.getMessage());
+        assertNull(e.getException());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "SAXException",
+        args = { Exception.class }
+    )
+    public void testSAXException_Exception() {
+        Exception c = new Exception();
+        
+        // Ordinary case
+        SAXException e = new SAXException(c);
+        
+        assertNull(e.getMessage());
+        assertEquals(c, e.getException());
+
+        // No cause
+        e = new SAXException((Exception)null);
+        
+        assertNull(e.getMessage());
+        assertNull(e.getException());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "toString",
+        args = { }
+    )
+    public void testToString() {
+        // Ordinary case
+        SAXException e = new SAXException(ERR);
+        String s = e.toString();
+        
+        assertTrue(s.contains(ERR));
+        
+        // No message
+        e = new SAXException();
+        s = e.toString();
+
+        assertFalse(s.contains(ERR));
+   }
+    
+}
\ No newline at end of file
diff --git a/xml/src/test/java/tests/api/org/xml/sax/SAXNotRecognizedExceptionTest.java b/xml/src/test/java/tests/api/org/xml/sax/SAXNotRecognizedExceptionTest.java
new file mode 100644
index 0000000..1fab7bf
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/SAXNotRecognizedExceptionTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.SAXNotRecognizedException;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+@TestTargetClass(SAXNotRecognizedException.class)
+public class SAXNotRecognizedExceptionTest extends TestCase {
+
+    public static final String ERR = "Houston, we have a problem";
+    
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "SAXNotRecognizedException",
+        args = { }
+    )
+    public void testSAXNotRecognizedException() {
+        SAXNotRecognizedException e = new SAXNotRecognizedException();
+        assertNull(e.getMessage());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "SAXNotRecognizedException",
+        args = { String.class }
+    )
+    public void testSAXNotRecognizedException_String() {
+        SAXNotRecognizedException e = new SAXNotRecognizedException(ERR);
+        assertEquals(ERR, e.getMessage());
+        
+        e = new SAXNotRecognizedException(null);
+        assertNull(e.getMessage());
+    }
+    
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/SAXNotSupportedExceptionTest.java b/xml/src/test/java/tests/api/org/xml/sax/SAXNotSupportedExceptionTest.java
new file mode 100644
index 0000000..9060a14
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/SAXNotSupportedExceptionTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.SAXNotSupportedException;
+
+@TestTargetClass(SAXNotSupportedException.class)
+public class SAXNotSupportedExceptionTest extends TestCase {
+
+    public static final String ERR = "Houston, we have a problem";
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "SAXNotSupportedException",
+        args = { }
+    )
+    public void testSAXNotSupportedException() {
+        SAXNotSupportedException e = new SAXNotSupportedException();
+        assertNull(e.getMessage());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "SAXNotSupportedException",
+        args = { String.class }
+    )
+    public void testSAXNotSupportedException_String() {
+        SAXNotSupportedException e = new SAXNotSupportedException(ERR);
+        assertEquals(ERR, e.getMessage());
+        
+        e = new SAXNotSupportedException(null);
+        assertNull(e.getMessage());
+    }
+    
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/SAXParseExceptionTest.java b/xml/src/test/java/tests/api/org/xml/sax/SAXParseExceptionTest.java
new file mode 100644
index 0000000..aff0c7f
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/SAXParseExceptionTest.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.Locator;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.LocatorImpl;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+@TestTargetClass(SAXParseException.class)
+public class SAXParseExceptionTest extends TestCase {
+
+    public static final String ERR = "Houston, we have a problem";
+    
+    public static final String SYS = "mySystemID";
+
+    public static final String PUB = "myPublicID";
+
+    public static final int ROW = 1;
+    
+    public static final int COL = 2;
+    
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "SAXParseException",
+            args = { String.class, Locator.class, Exception.class }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getMessage",
+            args = { }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getException",
+            args = { }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getPublicId",
+            args = { }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getSystemId",
+            args = { }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getLineNumber",
+            args = { }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getColumnNumber",
+            args = { }
+        )
+    })
+    public void testSAXParseException_String_Locator_Exception() {
+        LocatorImpl l = new LocatorImpl();
+        l.setPublicId(PUB);
+        l.setSystemId(SYS);
+        l.setLineNumber(ROW);
+        l.setColumnNumber(COL);
+        
+        Exception c = new Exception();
+        
+        // Ordinary case
+        SAXParseException e = new SAXParseException(ERR, l, c);
+        
+        assertEquals(ERR, e.getMessage());
+        assertEquals(c, e.getException());
+        
+        assertEquals(PUB, e.getPublicId());
+        assertEquals(SYS, e.getSystemId());
+        assertEquals(ROW, e.getLineNumber());
+        assertEquals(COL, e.getColumnNumber());
+
+        // No message
+        e = new SAXParseException(null, l, c);
+        
+        assertNull(e.getMessage());
+        assertEquals(c, e.getException());
+        
+        assertEquals(PUB, e.getPublicId());
+        assertEquals(SYS, e.getSystemId());
+        assertEquals(ROW, e.getLineNumber());
+        assertEquals(COL, e.getColumnNumber());
+        
+        // No locator
+        e = new SAXParseException(ERR, null, c);
+        
+        assertEquals(ERR, e.getMessage());
+        assertEquals(c, e.getException());
+        
+        assertNull(e.getPublicId());
+        assertNull(e.getSystemId());
+        assertEquals(-1, e.getLineNumber());
+        assertEquals(-1, e.getColumnNumber());
+        
+        // No cause
+        e = new SAXParseException(ERR, l, null);
+        
+        assertEquals(ERR, e.getMessage());
+        assertNull(e.getException());
+        
+        assertEquals(PUB, e.getPublicId());
+        assertEquals(SYS, e.getSystemId());
+        assertEquals(ROW, e.getLineNumber());
+        assertEquals(COL, e.getColumnNumber());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "SAXParseException",
+        args = { String.class, Locator.class }
+    )
+    public void testSAXParseException_String_Locator() {
+        LocatorImpl l = new LocatorImpl();
+        l.setPublicId(PUB);
+        l.setSystemId(SYS);
+        l.setLineNumber(ROW);
+        l.setColumnNumber(COL);
+        
+        // Ordinary case
+        SAXParseException e = new SAXParseException(ERR, l);
+        
+        assertEquals(ERR, e.getMessage());
+        assertNull(e.getException());
+        
+        assertEquals(PUB, e.getPublicId());
+        assertEquals(SYS, e.getSystemId());
+        assertEquals(ROW, e.getLineNumber());
+        assertEquals(COL, e.getColumnNumber());
+
+        // No message
+        e = new SAXParseException(null, l);
+        
+        assertNull(e.getMessage());
+        assertNull(e.getException());
+        
+        assertEquals(PUB, e.getPublicId());
+        assertEquals(SYS, e.getSystemId());
+        assertEquals(ROW, e.getLineNumber());
+        assertEquals(COL, e.getColumnNumber());
+
+        // No locator
+        e = new SAXParseException(ERR, null);
+        
+        assertEquals(ERR, e.getMessage());
+        assertNull(e.getException());
+        
+        assertNull(e.getPublicId());
+        assertNull(e.getSystemId());
+        assertEquals(-1, e.getLineNumber());
+        assertEquals(-1, e.getColumnNumber());
+        
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "SAXParseException",
+        args = { String.class, String.class, String.class, int.class, int.class,
+                 Exception.class }
+    )
+    public void testSAXParseException_String_String_String_int_int_Exception() {
+        Exception c = new Exception();
+        
+        // Ordinary case
+        SAXParseException e = new SAXParseException(ERR, PUB, SYS, ROW, COL, c);
+        
+        assertEquals(ERR, e.getMessage());
+        assertEquals(c, e.getException());
+        
+        assertEquals(PUB, e.getPublicId());
+        assertEquals(SYS, e.getSystemId());
+        assertEquals(ROW, e.getLineNumber());
+        assertEquals(COL, e.getColumnNumber());
+
+        // No message
+        e = new SAXParseException(null, PUB, SYS, ROW, COL, c);
+        
+        assertNull(e.getMessage());
+        assertEquals(c, e.getException());
+        
+        assertEquals(PUB, e.getPublicId());
+        assertEquals(SYS, e.getSystemId());
+        assertEquals(ROW, e.getLineNumber());
+        assertEquals(COL, e.getColumnNumber());
+        
+        // No locator
+        e = new SAXParseException(ERR, null, null, -1, -1, c);
+        
+        assertEquals(ERR, e.getMessage());
+        assertEquals(c, e.getException());
+        
+        assertNull(e.getPublicId());
+        assertNull(e.getSystemId());
+        assertEquals(-1, e.getLineNumber());
+        assertEquals(-1, e.getColumnNumber());
+        
+        // No cause
+        e = new SAXParseException(ERR, PUB, SYS, ROW, COL, null);
+        
+        assertEquals(ERR, e.getMessage());
+        assertNull(e.getException());
+        
+        assertEquals(PUB, e.getPublicId());
+        assertEquals(SYS, e.getSystemId());
+        assertEquals(ROW, e.getLineNumber());
+        assertEquals(COL, e.getColumnNumber());
+    }
+ 
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "SAXParseException",
+        args = { String.class, String.class, String.class, int.class,
+                 int.class }
+        )
+    public void testSAXParseException_String_String_String_int_int() {
+        // Ordinary case
+        SAXParseException e = new SAXParseException(ERR, PUB, SYS, ROW, COL);
+        
+        assertEquals(ERR, e.getMessage());
+        assertNull(e.getException());
+        
+        assertEquals(PUB, e.getPublicId());
+        assertEquals(SYS, e.getSystemId());
+        assertEquals(ROW, e.getLineNumber());
+        assertEquals(COL, e.getColumnNumber());
+
+        // No message
+        e = new SAXParseException(null, PUB, SYS, ROW, COL);
+        
+        assertNull(e.getMessage());
+        assertNull(e.getException());
+        
+        assertEquals(PUB, e.getPublicId());
+        assertEquals(SYS, e.getSystemId());
+        assertEquals(ROW, e.getLineNumber());
+        assertEquals(COL, e.getColumnNumber());
+        
+        // No locator
+        e = new SAXParseException(ERR, null, null, -1, -1);
+        
+        assertEquals(ERR, e.getMessage());
+        assertNull(e.getException());
+        
+        assertNull(e.getPublicId());
+        assertNull(e.getSystemId());
+        assertEquals(-1, e.getLineNumber());
+        assertEquals(-1, e.getColumnNumber());
+    }
+
+}
\ No newline at end of file
diff --git a/xml/src/test/java/tests/api/org/xml/sax/ext/AllTests.java b/xml/src/test/java/tests/api/org/xml/sax/ext/AllTests.java
new file mode 100644
index 0000000..f4b34b8
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/ext/AllTests.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.ext;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(AllTests.suite());
+    }
+
+    public static Test suite() {
+        TestSuite suite = tests.TestSuiteFactory.createTestSuite("Tests for org.xml.sax.ext package");
+        // $JUnit-BEGIN$
+
+        suite.addTestSuite(Attributes2ImplTest.class);
+        suite.addTestSuite(DefaultHandler2Test.class);
+        suite.addTestSuite(Locator2ImplTest.class);
+
+        // $JUnit-END$
+        return suite;
+    }
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/ext/Attributes2ImplTest.java b/xml/src/test/java/tests/api/org/xml/sax/ext/Attributes2ImplTest.java
new file mode 100644
index 0000000..9ccdc8a
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/ext/Attributes2ImplTest.java
@@ -0,0 +1,464 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.ext;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ext.Attributes2Impl;
+import org.xml.sax.helpers.AttributesImpl;
+
+import dalvik.annotation.KnownFailure;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+@TestTargetClass(Attributes2Impl.class)
+public class Attributes2ImplTest extends TestCase {
+
+    // Note: The original SAX2 implementation of Attributes2Impl is
+    // severely broken. Thus all of these tests will probably fail
+    // unless the Android implementation of the class gets fixed.
+    
+    private Attributes2Impl empty = new Attributes2Impl();
+
+    private Attributes2Impl multi = new Attributes2Impl();
+    
+    private Attributes2Impl cdata = new Attributes2Impl();
+    
+    @Override
+    public void setUp() {
+        multi.addAttribute("http://some.uri", "foo", "ns1:foo",
+                "string", "abc");
+        multi.addAttribute("http://some.uri", "bar", "ns1:bar",
+                "string", "xyz");
+        multi.addAttribute("http://some.other.uri", "answer", "ns2:answer",
+                "int", "42");
+        multi.addAttribute("http://yet.another.uri", "gabba", "ns3:gabba",
+                "string", "gabba");
+        
+        multi.setDeclared(0, false);
+        multi.setSpecified(0, false);
+        
+        multi.setDeclared(1, true);
+        multi.setSpecified(1, false);
+
+        multi.setDeclared(2, false);
+        multi.setSpecified(2, true);
+        
+        multi.setDeclared(3, true);
+        multi.setSpecified(3, true);
+        
+        cdata.addAttribute("http://yet.another.uri", "hey", "ns3:hey",
+                "CDATA", "hey");
+    }
+    
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setAttributes",
+        args = { Attributes.class }
+    )
+    public void testSetAttributes() {
+        // Ordinary case with Attributes2Impl
+        Attributes2Impl attrs = new Attributes2Impl();
+        attrs.addAttribute("", "", "john", "string", "doe");
+
+        attrs.setAttributes(empty);
+        assertEquals(0, attrs.getLength());
+
+        attrs.setAttributes(multi);
+        for (int i = 0; i < multi.getLength(); i++) {
+            assertEquals(multi.getURI(i), attrs.getURI(i));
+            assertEquals(multi.getLocalName(i), attrs.getLocalName(i));
+            assertEquals(multi.getQName(i), attrs.getQName(i));
+            assertEquals(multi.getType(i), attrs.getType(i));
+            assertEquals(multi.getValue(i), attrs.getValue(i));
+            assertEquals(multi.isDeclared(i), attrs.isDeclared(i));
+            assertEquals(multi.isSpecified(i), attrs.isSpecified(i));
+        }
+        
+        attrs.setAttributes(empty);
+        assertEquals(0, attrs.getLength());
+
+        // Ordinary case with AttributesImpl
+        attrs.setAttributes(new AttributesImpl(multi));
+        assertEquals(multi.getLength(), attrs.getLength());
+        
+        for (int i = 0; i < multi.getLength(); i++) {
+            assertEquals(multi.getURI(i), attrs.getURI(i));
+            assertEquals(multi.getLocalName(i), attrs.getLocalName(i));
+            assertEquals(multi.getQName(i), attrs.getQName(i));
+            assertEquals(multi.getType(i), attrs.getType(i));
+            assertEquals(multi.getValue(i), attrs.getValue(i));
+            assertEquals(true, attrs.isDeclared(i));
+            assertEquals(true, attrs.isSpecified(i));
+        }
+
+        // Special case with CDATA
+        attrs.setAttributes(new AttributesImpl(cdata));
+        assertEquals(1, attrs.getLength());
+        assertEquals(false, attrs.isDeclared(0));
+        assertEquals(true, attrs.isSpecified(0));
+        
+        // null case
+        try {
+            attrs.setAttributes(null);
+            fail("NullPointerException expected");
+        } catch (NullPointerException e) {
+            // Expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "addAttribute",
+        args = { String.class, String.class, String.class, String.class,
+                 String.class }
+    )
+    public void testAddAttribute() {
+        Attributes2Impl attrs = new Attributes2Impl();
+        
+        // Ordinary case
+        attrs.addAttribute("http://yet.another.uri", "doe", "john:doe",
+                "string", "abc");
+        
+        assertEquals(1, attrs.getLength());
+        
+        assertEquals("http://yet.another.uri", attrs.getURI(0));
+        assertEquals("doe", attrs.getLocalName(0));
+        assertEquals("john:doe", attrs.getQName(0));
+        assertEquals("string", attrs.getType(0));
+        assertEquals("abc", attrs.getValue(0));
+
+        assertEquals(true, attrs.isDeclared(0));
+        assertEquals(true, attrs.isSpecified(0));
+
+        // CDATA case
+        attrs.addAttribute("http://yet.another.uri", "doe", "jane:doe",
+                "CDATA", "abc");
+        
+        assertEquals(2, attrs.getLength());
+        
+        assertEquals("http://yet.another.uri", attrs.getURI(1));
+        assertEquals("doe", attrs.getLocalName(1));
+        assertEquals("jane:doe", attrs.getQName(1));
+        assertEquals("CDATA", attrs.getType(1));
+        assertEquals("abc", attrs.getValue(1));
+
+        assertEquals(false, attrs.isDeclared(1));
+        assertEquals(true, attrs.isSpecified(1));
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "removeAttribute",
+        args = { int.class }
+    )
+    public void testRemoveAttribute() {
+        Attributes2Impl attrs = new Attributes2Impl(multi);
+        
+        // Ordinary case
+        attrs.removeAttribute(1);
+
+        assertEquals(3, attrs.getLength());
+        
+        assertEquals(multi.getURI(0), attrs.getURI(0));
+        assertEquals(multi.getLocalName(0), attrs.getLocalName(0));
+        assertEquals(multi.getQName(0), attrs.getQName(0));
+        assertEquals(multi.getType(0), attrs.getType(0));
+        assertEquals(multi.getValue(0), attrs.getValue(0));
+        assertEquals(multi.isDeclared(0), attrs.isDeclared(0));
+        assertEquals(multi.isSpecified(0), attrs.isSpecified(0));
+        
+        assertEquals(multi.getURI(2), attrs.getURI(1));
+        assertEquals(multi.getLocalName(2), attrs.getLocalName(1));
+        assertEquals(multi.getQName(2), attrs.getQName(1));
+        assertEquals(multi.getType(2), attrs.getType(1));
+        assertEquals(multi.getValue(2), attrs.getValue(1));
+        assertEquals(multi.isDeclared(2), attrs.isDeclared(1));
+        assertEquals(multi.isSpecified(2), attrs.isSpecified(1));
+        
+        // Out of range
+        try {
+            attrs.removeAttribute(-1);
+            fail("ArrayIndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        
+        try {
+            attrs.removeAttribute(3);
+            fail("ArrayIndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "Attributes2Impl",
+        args = {  }
+    )
+    public void testAttributes2Impl() {
+        assertEquals(0, empty.getLength());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "Attributes2Impl",
+        args = { Attributes.class }
+    )
+    public void testAttributes2ImplAttributes() {
+        // Ordinary case with Attributes2Impl
+        Attributes2Impl attrs = new Attributes2Impl(multi);
+        assertEquals(multi.getLength(), attrs.getLength());
+
+        for (int i = 0; i < multi.getLength(); i++) {
+            assertEquals(multi.getURI(i), attrs.getURI(i));
+            assertEquals(multi.getLocalName(i), attrs.getLocalName(i));
+            assertEquals(multi.getQName(i), attrs.getQName(i));
+            assertEquals(multi.getType(i), attrs.getType(i));
+            assertEquals(multi.getValue(i), attrs.getValue(i));
+            assertEquals(multi.isDeclared(i), attrs.isDeclared(i));
+            assertEquals(multi.isSpecified(i), attrs.isSpecified(i));
+        }
+        
+        attrs = new Attributes2Impl(empty);
+        assertEquals(0, attrs.getLength());
+
+        // Ordinary case with AttributesImpl
+        attrs = new Attributes2Impl(new AttributesImpl(multi));
+        assertEquals(multi.getLength(), attrs.getLength());
+        
+        for (int i = 0; i < multi.getLength(); i++) {
+            assertEquals(multi.getURI(i), attrs.getURI(i));
+            assertEquals(multi.getLocalName(i), attrs.getLocalName(i));
+            assertEquals(multi.getQName(i), attrs.getQName(i));
+            assertEquals(multi.getType(i), attrs.getType(i));
+            assertEquals(multi.getValue(i), attrs.getValue(i));
+            assertEquals(true, attrs.isDeclared(i));
+            assertEquals(true, attrs.isSpecified(i));
+        }
+
+        // Special case with CDATA
+        attrs = new Attributes2Impl(new AttributesImpl(cdata));
+        assertEquals(1, attrs.getLength());
+        assertEquals(false, attrs.isDeclared(0));
+        assertEquals(true, attrs.isSpecified(0));
+        
+        // null case
+        try {
+            attrs = new Attributes2Impl(null);
+            fail("NullPointerException expected");
+        } catch (NullPointerException e) {
+            // Expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "isDeclared",
+        args = { int.class }
+    )
+    public void testIsDeclaredInt() {
+        // Ordinary cases
+        assertEquals(false, multi.isDeclared(0));
+        assertEquals(true, multi.isDeclared(1));
+        
+        // Out of range
+        try {
+            multi.isDeclared(-1);
+            fail("ArrayIndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        
+        try {
+            multi.isDeclared(4);
+            fail("ArrayIndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "isDeclared",
+        args = { String.class, String.class }
+    )
+    public void testIsDeclaredStringString() {
+        // Ordinary cases
+        assertEquals(false, multi.isDeclared("http://some.uri", "foo"));
+        assertEquals(true, multi.isDeclared("http://some.uri", "bar"));
+
+        // Not found
+        try {
+            assertFalse(multi.isDeclared("not", "found"));
+            fail("IllegalArgumentException expected");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "isDeclared",
+        args = { String.class }
+    )
+    public void testIsDeclaredString() {
+        // Ordinary cases
+        assertEquals(false, multi.isDeclared("ns1:foo"));
+        assertEquals(true, multi.isDeclared("ns1:bar"));
+        
+        // Not found
+        try {
+            assertFalse(multi.isDeclared("notfound"));
+            fail("IllegalArgumentException expected");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "isSpecified",
+        args = { int.class }
+    )
+    public void testIsSpecifiedInt() {
+        // Ordinary cases
+        assertEquals(false, multi.isSpecified(1));
+        assertEquals(true, multi.isSpecified(2));
+        
+        // Out of range
+        try {
+            multi.isSpecified(-1);
+            fail("ArrayIndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        
+        try {
+            multi.isSpecified(4);
+            fail("ArrayIndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "isSpecified",
+        args = { String.class, String.class }
+    )
+    public void testIsSpecifiedStringString() {
+        // Ordinary cases
+        assertEquals(false, multi.isSpecified("http://some.uri", "bar"));
+        assertEquals(true, multi.isSpecified("http://some.other.uri", "answer"));
+
+        // Not found
+        try {
+            assertFalse(multi.isSpecified("not", "found"));
+            fail("IllegalArgumentException expected");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "isSpecified",
+        args = { String.class }
+    )
+    public void testIsSpecifiedString() {
+        // Ordinary cases
+        assertEquals(false, multi.isSpecified("ns1:bar"));
+        assertEquals(true, multi.isSpecified("ns2:answer"));
+
+        // Not found
+        try {
+            assertFalse(multi.isSpecified("notfound"));
+            fail("IllegalArgumentException expected");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setDeclared",
+        args = { int.class, boolean.class }
+    )
+    public void testSetDeclared() {
+        // Ordinary cases
+        multi.setSpecified(0, false);
+        assertEquals(false, multi.isSpecified(0));
+
+        multi.setSpecified(0, true);
+        assertEquals(true, multi.isSpecified(0));
+
+        multi.setSpecified(0, false);
+        assertEquals(false, multi.isSpecified(0));
+        
+        // Out of range
+        try {
+            multi.setSpecified(-1, true);
+            fail("ArrayIndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        
+        try {
+            multi.setSpecified(5, true);
+            fail("ArrayIndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setSpecified",
+        args = { int.class, boolean.class }
+    )
+    public void testSetSpecified() {
+        // Ordinary cases
+        multi.setSpecified(0, false);
+        assertEquals(false, multi.isSpecified(0));
+
+        multi.setSpecified(0, true);
+        assertEquals(true, multi.isSpecified(0));
+
+        multi.setSpecified(0, false);
+        assertEquals(false, multi.isSpecified(0));
+        
+        // Out of range
+        try {
+            multi.setSpecified(-1, true);
+            fail("ArrayIndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        
+        try {
+            multi.setSpecified(5, true);
+            fail("ArrayIndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/ext/DefaultHandler2Test.java b/xml/src/test/java/tests/api/org/xml/sax/ext/DefaultHandler2Test.java
new file mode 100644
index 0000000..52a5972
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/ext/DefaultHandler2Test.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.ext;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.ext.DefaultHandler2;
+
+import java.io.IOException;
+
+@TestTargetClass(DefaultHandler2.class)
+public class DefaultHandler2Test extends TestCase {
+
+    private DefaultHandler2 h = new DefaultHandler2();
+    
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "DefaultHandler2",
+        args = { }
+    )
+    public void testDefaultHandler2() {
+        new DefaultHandler2();
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "startCDATA",
+        args = { }
+    )
+    public void testStartCDATA() {
+        try {
+            h.startCDATA();
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "endCDATA",
+        args = { }
+    )
+    public void testEndCDATA() {
+        try {
+            h.endCDATA();
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "startDTD",
+        args = { String.class, String.class, String.class }
+    )
+    public void testStartDTD() {
+        try {
+            h.startDTD("name", "publicId", "systemId");
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "endDTD",
+        args = { }
+    )
+    public void testEndDTD() {
+        try {
+            h.endDTD();
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "startEntity",
+        args = { String.class }
+    )
+    public void testStartEntity() {
+        try {
+            h.startEntity("name");
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "endEntity",
+        args = { String.class }
+    )
+    public void testEndEntity() {
+        try {
+            h.endEntity("name");
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "comment",
+        args = { char[].class, int.class, int.class }
+    )
+    public void testComment() {
+        try {
+            h.comment("<!-- Comment -->".toCharArray(), 0, 15);
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "attributeDecl",
+        args = { String.class, String.class, String.class, String.class,
+                 String.class }
+    )
+    public void testAttributeDecl() {
+        try {
+            h.attributeDecl("eName", "aName", "type", "mode", "value");
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "elementDecl",
+        args = { String.class, String.class }
+    )
+    public void testElementDecl() {
+        try {
+            h.elementDecl("name", "model");
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "externalEntityDecl",
+        args = { String.class, String.class, String.class }
+    )
+    public void testExternalEntityDecl() {
+        try {
+            h.externalEntityDecl("name", "publicId", "systemId");
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "internalEntityDecl",
+        args = { String.class, String.class }
+    )
+    public void testInternalEntityDecl() {
+        try {
+            h.internalEntityDecl("name", "value");
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getExternalSubset",
+        args = { String.class, String.class }
+    )
+    public void testGetExternalSubset() {
+        try {
+            assertNull(h.getExternalSubset("name", "http://some.uri"));
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        } catch (IOException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "resolveEntity",
+        args = { String.class, String.class }
+    )
+    public void testResolveEntityStringString() {
+        try {
+            assertNull(h.resolveEntity("publicId", "systemId"));
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        } catch (IOException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "resolveEntity",
+        args = { String.class, String.class, String.class, String.class }
+    )
+    public void testResolveEntityStringStringStringString() {
+        try {
+            assertNull(h.resolveEntity("name", "publicId", "http://some.uri",
+                    "systemId"));
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        } catch (IOException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/ext/Locator2ImplTest.java b/xml/src/test/java/tests/api/org/xml/sax/ext/Locator2ImplTest.java
new file mode 100644
index 0000000..b018f59
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/ext/Locator2ImplTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.ext;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.Locator;
+import org.xml.sax.ext.Locator2Impl;
+import org.xml.sax.helpers.LocatorImpl;
+
+@TestTargetClass(Locator2Impl.class)
+public class Locator2ImplTest extends TestCase {
+
+    public static final String SYS = "mySystemID";
+
+    public static final String PUB = "myPublicID";
+
+    public static final int ROW = 1;
+    
+    public static final int COL = 2;
+
+    public static final String ENC = "Klingon";
+    
+    public static final String XML = "1.0";
+    
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "Locator2Impl",
+        args = { }
+    )
+    public void testLocatorImpl() {
+        Locator2Impl l = new Locator2Impl();
+        
+        assertEquals(null, l.getPublicId());
+        assertEquals(null, l.getSystemId());
+        assertEquals(0, l.getLineNumber());
+        assertEquals(0, l.getColumnNumber());
+        
+        assertEquals(null, l.getEncoding());
+        assertEquals(null, l.getXMLVersion());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "Locator2Impl",
+        args = { Locator.class }
+    )
+    public void testLocatorImplLocator() {
+        Locator2Impl inner = new Locator2Impl();
+
+        inner.setPublicId(PUB);
+        inner.setSystemId(SYS);
+        inner.setLineNumber(ROW);
+        inner.setColumnNumber(COL);
+
+        inner.setEncoding(ENC);
+        inner.setXMLVersion(XML);
+        
+        // Ordinary case
+        Locator2Impl outer = new Locator2Impl(inner);
+        
+        assertEquals(PUB, outer.getPublicId());
+        assertEquals(SYS, outer.getSystemId());
+        assertEquals(ROW, outer.getLineNumber());
+        assertEquals(COL, outer.getColumnNumber());
+
+        assertEquals(ENC, outer.getEncoding());
+        assertEquals(XML, outer.getXMLVersion());
+        
+        // Instance of old locator
+        outer = new Locator2Impl(new LocatorImpl(inner));
+        
+        assertEquals(PUB, outer.getPublicId());
+        assertEquals(SYS, outer.getSystemId());
+        assertEquals(ROW, outer.getLineNumber());
+        assertEquals(COL, outer.getColumnNumber());
+
+        assertEquals(null, outer.getEncoding());
+        assertEquals(null, outer.getXMLVersion());
+        
+        // No locator
+        try {
+            outer = new Locator2Impl(null);
+            fail("NullPointerException expected");
+        } catch (NullPointerException e) {
+            // Expected
+        }
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setXMLVersion",
+            args = { String.class }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getXMLVersion",
+            args = { }
+        )
+    })
+    public void testSetXMLVersionGetXMLVersion() {
+        Locator2Impl l = new Locator2Impl();
+        
+        l.setXMLVersion(XML);
+        assertEquals(XML, l.getXMLVersion());
+        
+        l.setXMLVersion(null);
+        assertEquals(null, l.getXMLVersion());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEncoding",
+            args = { String.class }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getEncoding",
+            args = { }
+        )
+    })
+    public void testSetEncodingGetEncoding() {
+        Locator2Impl l = new Locator2Impl();
+        
+        l.setEncoding(ENC);
+        assertEquals(ENC, l.getEncoding());
+        
+        l.setEncoding(null);
+        assertEquals(null, l.getEncoding());
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/helpers/AllTests.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/AllTests.java
new file mode 100644
index 0000000..5bf63bf
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/AllTests.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.helpers;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(AllTests.suite());
+    }
+
+    public static Test suite() {
+        TestSuite suite = tests.TestSuiteFactory.createTestSuite("Tests for org.xml.sax.helpers package");
+        // $JUnit-BEGIN$
+
+        suite.addTestSuite(AttributeListImplTest.class);
+        suite.addTestSuite(AttributesImplTest.class);
+        suite.addTestSuite(ParserFactoryTest.class);
+        suite.addTestSuite(DefaultHandlerTest.class);
+        suite.addTestSuite(LocatorImplTest.class);
+        suite.addTestSuite(NamespaceSupportTest.class);
+        suite.addTestSuite(XMLFilterImplTest.class);
+        suite.addTestSuite(XMLReaderAdapterTest.class);
+        suite.addTestSuite(XMLReaderFactoryTest.class);
+
+        // $JUnit-END$
+        return suite;
+    }
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/helpers/AttributeListImplTest.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/AttributeListImplTest.java
new file mode 100644
index 0000000..00658cb
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/AttributeListImplTest.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.helpers;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.AttributeList;
+import org.xml.sax.helpers.AttributeListImpl;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+@SuppressWarnings("deprecation")
+@TestTargetClass(AttributeListImpl.class)
+public class AttributeListImplTest extends TestCase {
+
+    private AttributeListImpl empty = new AttributeListImpl();
+
+    private AttributeListImpl multi = new AttributeListImpl();
+    
+    @Override
+    public void setUp() {
+        multi.addAttribute("foo", "string", "abc");
+        multi.addAttribute("bar", "string", "xyz");
+        multi.addAttribute("answer", "int", "42");
+    }
+    
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "AttributeListImpl",
+        args = { }
+    )
+    public void testAttributeListImpl() {
+        assertEquals(0, empty.getLength());
+        assertEquals(3, multi.getLength());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "AttributeListImpl",
+        args = { AttributeList.class }
+    )
+    public void testAttributeListImplAttributeList() {
+        // Ordinary case
+        AttributeListImpl ai = new AttributeListImpl(empty);
+        assertEquals(0, ai.getLength());
+        
+        // Another ordinary case
+        ai = new AttributeListImpl(multi);
+        assertEquals(3, ai.getLength());
+
+        // No Attributes
+        try {
+            ai = new AttributeListImpl(null);
+            assertEquals(0, ai.getLength());
+            fail("NullPointerException expected");
+        } catch (NullPointerException e) {
+            // Expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setAttributeList",
+        args = { AttributeList.class }
+    )
+    public void testSetAttributeList() {
+        // Ordinary cases
+        AttributeListImpl attrs = new AttributeListImpl();
+        attrs.addAttribute("doe", "boolean", "false");
+        
+        attrs.setAttributeList(empty);
+        assertEquals(0, attrs.getLength());
+        
+        attrs.setAttributeList(multi);
+        assertEquals(multi.getLength(), attrs.getLength());
+        
+        for (int i = 0; i < multi.getLength(); i++) {
+            assertEquals(multi.getName(i), attrs.getName(i));
+            assertEquals(multi.getType(i), attrs.getType(i));
+            assertEquals(multi.getValue(i), attrs.getValue(i));
+        }
+        
+        // null case
+        try {
+            attrs.setAttributeList(null);
+            fail("NullPointerException expected");
+        } catch (NullPointerException e) {
+            // Expected, must still have old elements
+            assertEquals(3, attrs.getLength());
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "addAttribute",
+        args = { String.class, String.class, String.class }
+    )
+    public void testAddAttribute() {
+        // Ordinary case
+        multi.addAttribute("doe", "boolean", "false");
+        
+        assertEquals("doe", multi.getName(3));
+        assertEquals("boolean", multi.getType(3));
+        assertEquals("false", multi.getValue(3));
+        
+        // Duplicate case
+        multi.addAttribute("doe", "boolean", "false");
+        
+        assertEquals("doe", multi.getName(4));
+        assertEquals("boolean", multi.getType(4));
+        assertEquals("false", multi.getValue(4));
+        
+        // null case
+        multi.addAttribute(null, null, null);
+        assertEquals(null, multi.getName(5));
+        assertEquals(null, multi.getType(5));
+        assertEquals(null, multi.getValue(5));
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "removeAttribute",
+        args = { String.class }
+    )
+    public void testRemoveAttribute() {
+        // Ordinary case
+        multi.removeAttribute("foo");
+        assertEquals("bar", multi.getName(0));
+        assertEquals("string", multi.getType(0));
+        assertEquals("xyz", multi.getValue(0));
+        
+        // Unknown attribute
+        multi.removeAttribute("john");
+        assertEquals(2, multi.getLength());
+
+        // null case
+        multi.removeAttribute(null);
+        assertEquals(2, multi.getLength());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "clear",
+        args = { }
+    )
+    public void testClear() {
+        assertEquals(3, multi.getLength());
+        multi.clear();
+        assertEquals(0, multi.getLength());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getLength",
+        args = { }
+    )
+    public void testGetLength() {
+        AttributeListImpl ai = new AttributeListImpl(empty);
+        assertEquals(0, ai.getLength());
+
+        ai = new AttributeListImpl(multi);
+        assertEquals(3, ai.getLength());
+        
+        for (int i = 2; i >= 0; i--) {
+            ai.removeAttribute(ai.getName(i));
+            assertEquals(i, ai.getLength());
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getName",
+        args = { int.class }
+    )
+    public void testGetName() {
+        // Ordinary cases
+        assertEquals("foo", multi.getName(0));
+        assertEquals("bar", multi.getName(1));
+        assertEquals("answer", multi.getName(2));
+        
+        // Out of range
+        assertEquals(null, multi.getName(-1));
+        assertEquals(null, multi.getName(3));
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getType",
+        args = { int.class }
+    )
+    public void testGetTypeInt() {
+        // Ordinary cases
+        assertEquals("string", multi.getType(0));
+        assertEquals("string", multi.getType(1));
+        assertEquals("int", multi.getType(2));
+        
+        // Out of range
+        assertEquals(null, multi.getType(-1));
+        assertEquals(null, multi.getType(3));
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getValue",
+        args = { int.class }
+    )
+    public void testGetValueInt() {
+        // Ordinary cases
+        assertEquals("abc", multi.getValue(0));
+        assertEquals("xyz", multi.getValue(1));
+        assertEquals("42", multi.getValue(2));
+        
+        // Out of range
+        assertEquals(null, multi.getValue(-1));
+        assertEquals(null, multi.getValue(5));
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getType",
+        args = { String.class }
+    )
+    public void testGetTypeString() {
+        // Ordinary cases
+        assertEquals("string", multi.getType("foo"));
+        assertEquals("string", multi.getType("bar"));
+        assertEquals("int", multi.getType("answer"));
+        
+        // Not found
+        assertEquals(null, multi.getType("john"));
+        
+        // null case
+        assertEquals(null, multi.getType(null));
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getValue",
+        args = { String.class }
+    )
+    public void testGetValueString() {
+        // Ordinary cases
+        assertEquals("abc", multi.getValue("foo"));
+        assertEquals("xyz", multi.getValue("bar"));
+        assertEquals("42", multi.getValue("answer"));
+        
+        // Not found
+        assertEquals(null, multi.getValue("john"));
+
+        // null case
+        assertEquals(null, multi.getValue(null));
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/helpers/AttributesImplTest.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/AttributesImplTest.java
new file mode 100644
index 0000000..0efe25f
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/AttributesImplTest.java
@@ -0,0 +1,608 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.helpers;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.helpers.AttributesImpl;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+@TestTargetClass(AttributesImpl.class)
+public class AttributesImplTest extends TestCase {
+
+    private AttributesImpl empty = new AttributesImpl();
+
+    private AttributesImpl multi = new AttributesImpl();
+    
+    @Override
+    public void setUp() {
+        multi.addAttribute("http://some.uri", "foo", "ns1:foo",
+                "string", "abc");
+        multi.addAttribute("http://some.uri", "bar", "ns1:bar",
+                "string", "xyz");
+        multi.addAttribute("http://some.other.uri", "answer", "ns2:answer",
+                "int", "42");
+        
+        multi.addAttribute("", "gabbaHey", "", "string", "1-2-3-4");
+        multi.addAttribute("", "", "gabba:hey", "string", "1-2-3-4");
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "AttributesImpl",
+        args = { }
+    )
+    public void testAttributesImpl() {
+        assertEquals(0, empty.getLength());
+        assertEquals(5, multi.getLength());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "AttributesImpl",
+        args = { Attributes.class }
+    )
+    public void testAttributesImplAttributes() {
+        // Ordinary case
+        AttributesImpl ai = new AttributesImpl(empty);
+        assertEquals(0, ai.getLength());
+        
+        // Another ordinary case
+        ai = new AttributesImpl(multi);
+        assertEquals(5, ai.getLength());
+
+        // No Attributes
+        try {
+            ai = new AttributesImpl(null);
+            assertEquals(0, ai.getLength());
+            fail("NullPointerException expected");
+        } catch (NullPointerException e) {
+            // Expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getLength",
+        args = { }
+    )
+    public void testGetLength() {
+        AttributesImpl ai = new AttributesImpl(empty);
+        assertEquals(0, ai.getLength());
+
+        ai = new AttributesImpl(multi);
+        assertEquals(5, ai.getLength());
+        
+        for (int i = 4; i >= 0; i--) {
+            ai.removeAttribute(i);
+            assertEquals(i, ai.getLength());
+        }
+    }
+    
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getURI",
+        args = { int.class }
+    )
+    public void testGetURI() {
+        // Ordinary cases
+        assertEquals("http://some.uri", multi.getURI(0));
+        assertEquals("http://some.uri", multi.getURI(1));
+        assertEquals("http://some.other.uri", multi.getURI(2));
+        assertEquals("", multi.getURI(3));
+        assertEquals("", multi.getURI(4));
+        
+        // Out of range
+        assertEquals(null, multi.getURI(-1));
+        assertEquals(null, multi.getURI(5));
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getLocalName",
+        args = { int.class }
+    )
+    public void testGetLocalName() {
+        // Ordinary cases
+        assertEquals("foo", multi.getLocalName(0));
+        assertEquals("bar", multi.getLocalName(1));
+        assertEquals("answer", multi.getLocalName(2));
+        assertEquals("gabbaHey", multi.getLocalName(3));
+        assertEquals("", multi.getLocalName(4));
+        
+        // Out of range
+        assertEquals(null, multi.getLocalName(-1));
+        assertEquals(null, multi.getLocalName(5));
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getQName",
+        args = { int.class }
+    )
+    public void testGetQName() {
+        // Ordinary cases
+        assertEquals("ns1:foo", multi.getQName(0));
+        assertEquals("ns1:bar", multi.getQName(1));
+        assertEquals("ns2:answer", multi.getQName(2));
+        assertEquals("", multi.getQName(3));
+        assertEquals("gabba:hey", multi.getQName(4));
+        
+        // Out of range
+        assertEquals(null, multi.getQName(-1));
+        assertEquals(null, multi.getQName(5));
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getType",
+        args = { int.class }
+    )
+    public void testGetTypeInt() {
+        // Ordinary cases
+        assertEquals("string", multi.getType(0));
+        assertEquals("string", multi.getType(1));
+        assertEquals("int", multi.getType(2));
+        assertEquals("string", multi.getType(3));
+        assertEquals("string", multi.getType(4));
+        
+        // Out of range
+        assertEquals(null, multi.getType(-1));
+        assertEquals(null, multi.getType(5));
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getValue",
+        args = { int.class }
+    )
+    public void testGetValueInt() {
+        // Ordinary cases
+        assertEquals("abc", multi.getValue(0));
+        assertEquals("xyz", multi.getValue(1));
+        assertEquals("42", multi.getValue(2));
+        assertEquals("1-2-3-4", multi.getValue(3));
+        assertEquals("1-2-3-4", multi.getValue(4));
+        
+        // Out of range
+        assertEquals(null, multi.getValue(-1));
+        assertEquals(null, multi.getValue(5));
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getIndex",
+        args = { String.class, String.class }
+    )
+    public void testGetIndexStringString() {
+        // Ordinary cases
+        assertEquals(0, multi.getIndex("http://some.uri", "foo"));
+        assertEquals(1, multi.getIndex("http://some.uri", "bar"));
+        assertEquals(2, multi.getIndex("http://some.other.uri", "answer"));
+        
+        // Not found
+        assertEquals(-1, multi.getIndex("john", "doe"));
+        
+        // null cases
+        assertEquals(-1, multi.getIndex("http://some.uri", null));
+        assertEquals(-1, multi.getIndex(null, "foo"));
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getIndex",
+        args = { String.class }
+    )
+    public void testGetIndexString() {
+        // Ordinary cases
+        assertEquals(0, multi.getIndex("ns1:foo"));
+        assertEquals(1, multi.getIndex("ns1:bar"));
+        assertEquals(2, multi.getIndex("ns2:answer"));
+        assertEquals(4, multi.getIndex("gabba:hey"));
+        
+        // Not found
+        assertEquals(-1, multi.getIndex("john:doe"));
+        
+        // null case
+        assertEquals(-1, multi.getIndex(null));
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getType",
+        args = { String.class, String.class }
+    )
+    public void testGetTypeStringString() {
+        // Ordinary cases
+        assertEquals("string", multi.getType("http://some.uri", "foo"));
+        assertEquals("string", multi.getType("http://some.uri", "bar"));
+        assertEquals("int", multi.getType("http://some.other.uri", "answer"));
+        
+        // Not found
+        assertEquals(null, multi.getType("john", "doe"));
+        
+        // null cases
+        assertEquals(null, multi.getType("http://some.uri", null));
+        assertEquals(null, multi.getType(null, "foo"));
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getType",
+        args = { String.class }
+    )
+    public void testGetTypeString() {
+        // Ordinary cases
+        assertEquals("string", multi.getType("ns1:foo"));
+        assertEquals("string", multi.getType("ns1:bar"));
+        assertEquals("int", multi.getType("ns2:answer"));
+        assertEquals("string", multi.getType("gabba:hey"));
+        
+        // Not found
+        assertEquals(null, multi.getType("john:doe"));
+        
+        // null case
+        assertEquals(null, multi.getType(null));
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getValue",
+        args = { String.class, String.class }
+    )
+    public void testGetValueStringString() {
+        // Ordinary cases
+        assertEquals("abc", multi.getValue("http://some.uri", "foo"));
+        assertEquals("xyz", multi.getValue("http://some.uri", "bar"));
+        assertEquals("42", multi.getValue("http://some.other.uri", "answer"));
+        
+        // Not found
+        assertEquals(null, multi.getValue("john", "doe"));
+        
+        // null cases
+        assertEquals(null, multi.getValue("http://some.uri", null));
+        assertEquals(null, multi.getValue(null, "foo"));
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "getValue",
+        args = { String.class }
+    )
+    public void testGetValueString() {
+        // Ordinary cases
+        assertEquals("abc", multi.getValue("ns1:foo"));
+        assertEquals("xyz", multi.getValue("ns1:bar"));
+        assertEquals("42", multi.getValue("ns2:answer"));
+        assertEquals("1-2-3-4", multi.getValue("gabba:hey"));
+        
+        // Not found
+        assertEquals(null, multi.getValue("john:doe"));
+
+        // null case
+        assertEquals(null, multi.getValue(null));
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "clear",
+        args = { }
+    )
+    public void testClear() {
+        assertEquals(5, multi.getLength());
+        multi.clear();
+        assertEquals(0, multi.getLength());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setAttributes",
+        args = { Attributes.class }
+    )
+    public void testSetAttributes() {
+        // Ordinary cases
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("http://yet.another.uri", "doe", "john:doe",
+                "boolean", "false");
+        
+        attrs.setAttributes(empty);
+        assertEquals(0, attrs.getLength());
+        
+        attrs.setAttributes(multi);
+        assertEquals(multi.getLength(), attrs.getLength());
+        
+        for (int i = 0; i < multi.getLength(); i++) {
+            assertEquals(multi.getURI(i), attrs.getURI(i));
+            assertEquals(multi.getLocalName(i), attrs.getLocalName(i));
+            assertEquals(multi.getQName(i), attrs.getQName(i));
+            assertEquals(multi.getType(i), attrs.getType(i));
+            assertEquals(multi.getValue(i), attrs.getValue(i));
+        }
+        
+        // null case
+        try {
+            attrs.setAttributes(null);
+            fail("NullPointerException expected");
+        } catch (NullPointerException e) {
+            // Expected, but must be empty now
+            assertEquals(0, attrs.getLength());
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "addAttribute",
+        args = { String.class, String.class, String.class, String.class,
+                 String.class }
+    )
+    public void testAddAttribute() {
+        // Ordinary case
+        multi.addAttribute("http://yet.another.uri", "doe", "john:doe",
+                "boolean", "false");
+        
+        assertEquals("http://yet.another.uri", multi.getURI(5));
+        assertEquals("doe", multi.getLocalName(5));
+        assertEquals("john:doe", multi.getQName(5));
+        assertEquals("boolean", multi.getType(5));
+        assertEquals("false", multi.getValue(5));
+        
+        // Duplicate case
+        multi.addAttribute("http://yet.another.uri", "doe", "john:doe",
+                "boolean", "false");
+        
+        assertEquals("http://yet.another.uri", multi.getURI(6));
+        assertEquals("doe", multi.getLocalName(6));
+        assertEquals("john:doe", multi.getQName(6));
+        assertEquals("boolean", multi.getType(6));
+        assertEquals("false", multi.getValue(6));
+        
+        // null case
+        multi.addAttribute(null, null, null, null, null);
+        assertEquals(null, multi.getURI(7));
+        assertEquals(null, multi.getLocalName(7));
+        assertEquals(null, multi.getQName(7));
+        assertEquals(null, multi.getType(7));
+        assertEquals(null, multi.getValue(7));
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setAttribute",
+        args = { int.class, String.class, String.class, String.class,
+                 String.class, String.class }
+    )
+    public void testSetAttribute() {
+        // Ordinary case
+        multi.setAttribute(0, "http://yet.another.uri", "doe", "john:doe",
+                "boolean", "false");
+        assertEquals("http://yet.another.uri", multi.getURI(0));
+        assertEquals("doe", multi.getLocalName(0));
+        assertEquals("john:doe", multi.getQName(0));
+        assertEquals("boolean", multi.getType(0));
+        assertEquals("false", multi.getValue(0));
+
+        // null case
+        multi.setAttribute(1, null, null, null, null, null);
+        assertEquals(null, multi.getURI(1));
+        assertEquals(null, multi.getLocalName(1));
+        assertEquals(null, multi.getQName(1));
+        assertEquals(null, multi.getType(1));
+        assertEquals(null, multi.getValue(1));
+        
+        // Out of range
+        try {
+            multi.setAttribute(-1, "http://yet.another.uri", "doe", "john:doe",
+                    "boolean", "false");
+            fail("ArrayIndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        
+        try {
+            multi.setAttribute(5, "http://yet.another.uri", "doe", "john:doe",
+                    "boolean", "false");
+            fail("ArrayIndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "removeAttribute",
+        args = { int.class }
+    )
+    public void testRemoveAttribute() {
+        // Ordinary case
+        multi.removeAttribute(0);
+        assertEquals("http://some.uri", multi.getURI(0));
+        assertEquals("bar", multi.getLocalName(0));
+        assertEquals("ns1:bar", multi.getQName(0));
+        assertEquals("string", multi.getType(0));
+        assertEquals("xyz", multi.getValue(0));
+        
+        // Out of range
+        try {
+            multi.removeAttribute(-1);
+            fail("ArrayIndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        
+        try {
+            multi.removeAttribute(4);
+            fail("ArrayIndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setURI",
+        args = { int.class, String.class }
+    )
+    public void testSetURI() {
+        // Ordinary case
+        multi.setURI(0, "http://yet.another.uri");
+        assertEquals("http://yet.another.uri", multi.getURI(0));
+
+        // null case
+        multi.setURI(1, null);
+        assertEquals(null, multi.getURI(1));
+        
+        // Out of range
+        try {
+            multi.setURI(-1, "http://yet.another.uri");
+            fail("ArrayIndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        
+        try {
+            multi.setURI(5, "http://yet.another.uri");
+            fail("ArrayIndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setLocalName",
+        args = { int.class, String.class }
+    )
+    public void testSetLocalName() {
+        // Ordinary case
+        multi.setLocalName(0, "john");
+        assertEquals("john", multi.getLocalName(0));
+
+        // null case
+        multi.setLocalName(1, null);
+        assertEquals(null, multi.getLocalName(1));
+        
+        // Out of range
+        try {
+            multi.setLocalName(-1, "john");
+            fail("ArrayIndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        
+        try {
+            multi.setLocalName(5, "john");
+            fail("ArrayIndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setQName",
+        args = { int.class, String.class }
+    )
+    public void testSetQName() {
+        // Ordinary case
+        multi.setQName(0, "john:doe");
+        assertEquals("john:doe", multi.getQName(0));
+
+        // null case
+        multi.setQName(1, null);
+        assertEquals(null, multi.getQName(1));
+        
+        // Out of range
+        try {
+            multi.setQName(-1, "john:doe");
+            fail("ArrayIndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        
+        try {
+            multi.setQName(5, "john:doe");
+            fail("ArrayIndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setType",
+        args = { int.class, String.class }
+    )
+    public void testSetType() {
+        // Ordinary case
+        multi.setType(0, "float");
+        assertEquals("float", multi.getType(0));
+
+        // null case
+        multi.setType(1, null);
+        assertEquals(null, multi.getType(1));
+        
+        // Out of range
+        try {
+            multi.setType(-1, "float");
+            fail("ArrayIndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        
+        try {
+            multi.setType(5, "float");
+            fail("ArrayIndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setValue",
+        args = { int.class, String.class }
+    )
+    public void testSetValue() {
+        // Ordinary case
+        multi.setValue(0, "too much");
+        assertEquals("too much", multi.getValue(0));
+
+        // null case
+        multi.setValue(1, null);
+        assertEquals(null, multi.getValue(1));
+        
+        // Out of range
+        try {
+            multi.setValue(-1, "too much");
+            fail("ArrayIndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+        
+        try {
+            multi.setValue(5, "too much");
+            fail("ArrayIndexOutOfBoundsException expected");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Expected
+        }
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/helpers/DefaultHandlerTest.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/DefaultHandlerTest.java
new file mode 100644
index 0000000..527048f
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/DefaultHandlerTest.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.helpers;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.AttributesImpl;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.helpers.LocatorImpl;
+
+import java.io.IOException;
+
+@TestTargetClass(DefaultHandler.class)
+public class DefaultHandlerTest extends TestCase {
+
+    /*
+     * Note: most of the tests have to check for an empty implementation of the
+     * respective methods and, as a result, are somewhat trivial.
+     */
+    
+    private DefaultHandler h = new DefaultHandler();
+    
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "resolveEntity",
+        args = { String.class, String.class }
+    )
+    public void testResolveEntity() {
+        try {
+            h.resolveEntity("publicID", "systemID");
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }        
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "notationDecl",
+        args = { String.class, String.class, String.class }
+    )
+    public void testNotationDecl() {
+        try {
+            h.notationDecl("name", "publicID", "systemID");
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }        
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "unparsedEntityDecl",
+        args = { String.class, String.class, String.class, String.class }
+    )
+    public void testUnparsedEntityDecl() {
+        try {
+            h.unparsedEntityDecl("name", "publicID", "systemID",
+                    "notationName");
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }        
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setDocumentLocator",
+        args = { org.xml.sax.Locator.class }
+    )
+    public void testSetDocumentLocator() {
+        h.setDocumentLocator(new LocatorImpl());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "startDocument",
+        args = { }
+    )
+    public void testStartDocument() {
+        try {
+            h.startDocument();
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "endDocument",
+        args = { }
+    )
+    public void testEndDocument() {
+        try {
+            h.endDocument();
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "startPrefixMapping",
+        args = { String.class, String.class }
+    )
+    public void testStartPrefixMapping() {
+        try {
+            h.startPrefixMapping("prefix", "uri");
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "endPrefixMapping",
+        args = { String.class }
+    )
+    public void testEndPrefixMapping() {
+        try {
+            h.endPrefixMapping("prefix");
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "startElement",
+        args = { String.class, String.class, String.class,
+                 Attributes.class }
+    )
+    public void testStartElement() {
+        try {
+            h.startElement("uri", "name", "qname", new AttributesImpl());
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "endElement",
+        args = { String.class, String.class, String.class }
+    )
+    public void testEndElement() {
+        try {
+            h.endElement("uri", "name", "qname");
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "characters",
+        args = { char[].class, int.class, int.class }
+    )
+    public void testCharacters() {
+        try {
+            h.characters("The quick brown fox".toCharArray(), 4, 11);
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "ignorableWhitespace",
+        args = { char[].class, int.class, int.class }
+    )
+    public void testIgnorableWhitespace() {
+        try {
+            h.ignorableWhitespace("                   ".toCharArray(), 4, 11);
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "processingInstruction",
+        args = { String.class, String.class }
+    )
+    public void testProcessingInstruction() {
+        try {
+            h.processingInstruction("target", "data");
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "skippedEntity",
+        args = { String.class }
+    )
+    public void testSkippedEntity() {
+        try {
+            h.skippedEntity("name");
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "warning",
+        args = { org.xml.sax.SAXParseException.class }
+    )
+    public void testWarning() {
+        try {
+            h.warning(new SAXParseException("Foo", new LocatorImpl()));
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "error",
+        args = { org.xml.sax.SAXParseException.class }
+    )
+    public void testError() {
+        try {
+            h.error(new SAXParseException("Foo", new LocatorImpl()));
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "fatalError",
+        args = { org.xml.sax.SAXParseException.class }
+    )
+    public void testFatalError() {
+        // Ordinary case
+        try {
+            h.fatalError(new SAXParseException("Foo", new LocatorImpl()));
+            fail("SAXException expected");
+        } catch (SAXException e) {
+            // Expected
+        }
+        
+        // No exception
+        try {
+            h.fatalError(null);
+            fail("NullPointerException expected");
+        } catch (SAXException e) {
+            fail("NullPointerException expected");
+        } catch (NullPointerException e) {
+            // Expected
+        }
+        
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/helpers/LocatorImplTest.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/LocatorImplTest.java
new file mode 100644
index 0000000..e6b243c
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/LocatorImplTest.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.helpers;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.Locator;
+import org.xml.sax.helpers.LocatorImpl;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+@TestTargetClass(LocatorImpl.class)
+public class LocatorImplTest extends TestCase {
+
+    public static final String SYS = "mySystemID";
+
+    public static final String PUB = "myPublicID";
+
+    public static final int ROW = 1;
+    
+    public static final int COL = 2;
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "LocatorImpl",
+        args = { }
+    )
+    public void testLocatorImpl() {
+        LocatorImpl l = new LocatorImpl();
+        
+        assertEquals(null, l.getPublicId());
+        assertEquals(null, l.getSystemId());
+        assertEquals(0, l.getLineNumber());
+        assertEquals(0, l.getColumnNumber());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "LocatorImpl",
+        args = { Locator.class }
+    )
+    public void testLocatorImplLocator() {
+        LocatorImpl inner = new LocatorImpl();
+
+        inner.setPublicId(PUB);
+        inner.setSystemId(SYS);
+        inner.setLineNumber(ROW);
+        inner.setColumnNumber(COL);
+        
+        // Ordinary case
+        LocatorImpl outer = new LocatorImpl(inner);
+        
+        assertEquals(PUB, outer.getPublicId());
+        assertEquals(SYS, outer.getSystemId());
+        assertEquals(ROW, outer.getLineNumber());
+        assertEquals(COL, outer.getColumnNumber());
+        
+        // No locator
+        try {
+            outer = new LocatorImpl(null);
+            fail("NullPointerException expected");
+        } catch (NullPointerException e) {
+            // Expected
+        }
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setPublicId",
+            args = { String.class }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getPublicId",
+            args = { }
+        )
+    })
+    public void testSetPublicIdGetPublicId() {
+        LocatorImpl l = new LocatorImpl();
+        
+        l.setPublicId(PUB);
+        assertEquals(PUB, l.getPublicId());
+        
+        l.setPublicId(null);
+        assertEquals(null, l.getPublicId());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setSystemId",
+            args = { String.class }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getSystemId",
+            args = { }
+        )
+    })
+    public void testSetSystemIdGetSystemId() {
+        LocatorImpl l = new LocatorImpl();
+        
+        l.setSystemId(SYS);
+        assertEquals(SYS, l.getSystemId());
+        
+        l.setSystemId(null);
+        assertEquals(null, l.getSystemId());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setLineNumber",
+            args = { int.class }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getLineNumber",
+            args = { }
+        )
+    })
+    public void testSetLineNumberGetLineNumber() {
+        LocatorImpl l = new LocatorImpl();
+        
+        l.setLineNumber(ROW);
+        assertEquals(ROW, l.getLineNumber());
+        
+        l.setLineNumber(0);
+        assertEquals(0, l.getLineNumber());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setColumnNumber",
+            args = { int.class }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getColumnNumber",
+            args = { }
+        )
+    })
+    public void testSetColumnNumberGetColumnNumber() {
+        LocatorImpl l = new LocatorImpl();
+        
+        l.setColumnNumber(COL);
+        assertEquals(COL, l.getColumnNumber());
+        
+        l.setColumnNumber(0);
+        assertEquals(0, l.getColumnNumber());
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/helpers/NamespaceSupportTest.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/NamespaceSupportTest.java
new file mode 100644
index 0000000..b163b54
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/NamespaceSupportTest.java
@@ -0,0 +1,434 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.helpers;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.EmptyStackException;
+import java.util.Enumeration;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.helpers.NamespaceSupport;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+@TestTargetClass(
+        value = NamespaceSupport.class,
+        untestedMethods = {
+        }
+)
+public class NamespaceSupportTest extends TestCase {
+
+    final static String defaultUri = "http://www.android.com"; 
+    final static String marketUri = "http://www.android.com/market"; 
+
+    NamespaceSupport ns;
+    ArrayList<String> expected;
+    
+    @Override
+    public void setUp() {
+        expected = new ArrayList<String>();
+        expected.add("ak");
+        expected.add("bk");
+        
+        ns = new NamespaceSupport();
+        ns.pushContext();
+        
+        ns.declarePrefix("ak", marketUri);
+        ns.declarePrefix("bk", marketUri);
+        ns.declarePrefix("", defaultUri);
+    }
+    
+    @SuppressWarnings("unchecked")
+    @TestTargets ({
+        @TestTargetNew(
+                level = TestLevel.COMPLETE,
+                notes = "Checks that a new NamespaceSupport object contains a " +
+                "default context with two predefined prefixes.",
+                method = "NamespaceSupport",
+                args = {}
+        ),
+        @TestTargetNew(
+                level = TestLevel.PARTIAL_COMPLETE,
+                method = "popContext",
+                args = {}
+        )
+    })
+    public void testConstructor() {
+        String prefix;
+        boolean xmlPrefixExists = false;
+        
+        ns = new NamespaceSupport();
+        Enumeration<String> prefixes = ns.getDeclaredPrefixes();
+        
+        while (prefixes.hasMoreElements()) {
+            prefix = prefixes.nextElement();
+            if (prefix.equals("xml")) xmlPrefixExists = true;
+        }
+
+        assertTrue("Test 1: xml prefix does not exist.", xmlPrefixExists);
+
+        // Check that only one context has been created by the constructor.
+        try {
+            ns.popContext();
+            fail("Test 2: EmptyStackException expected.");
+        } catch (EmptyStackException e) {
+            // Expected.
+        }
+    }
+    
+    @TestTargets ({
+        @TestTargetNew(
+                level = TestLevel.COMPLETE,
+                method = "pushContext",
+                args = {}
+        ),
+        @TestTargetNew(
+                level = TestLevel.PARTIAL_COMPLETE,
+                method = "popContext",
+                args = {}
+        )
+    })
+    public void testPush_PopContext() {
+        int count;
+        
+        ns = new NamespaceSupport();
+        count = countPrefixes();
+        
+        ns.pushContext();
+        ns.declarePrefix("dc", "http://www.purl.org/dc#");
+        assertEquals("Test 1: Incorrect prefix count;", 
+                count + 1, countPrefixes());
+        
+        ns.popContext();
+        assertEquals("Test 2: Incorrect prefix count;", 
+                count, countPrefixes());
+
+        // Check that only one context has been created by pushContext().
+        try {
+            ns.popContext();
+            fail("Test 3: EmptyStackException expected.");
+        } catch (EmptyStackException e) {
+            // Expected.
+        }
+    }
+    
+    @TestTargets ({
+        @TestTargetNew(
+                level = TestLevel.COMPLETE,
+                method = "reset",
+                args = {}
+        ),
+        @TestTargetNew(
+                level = TestLevel.PARTIAL_COMPLETE,
+                method = "popContext",
+                args = {}
+        )
+    })
+    public void testReset() {
+        int count;
+        
+        ns = new NamespaceSupport();
+        count = countPrefixes();
+        
+        ns.pushContext();
+        ns.declarePrefix("dc", "http://www.purl.org/dc#");
+
+        assertEquals("Test 1: Incorrect prefix count;", 
+                count + 1, countPrefixes());
+        
+        ns.reset();
+        assertEquals("Test 2: Incorrect prefix count;", 
+                count, countPrefixes());
+
+        // Check that only one context has been created by reset().
+        try {
+            ns.popContext();
+            fail("Test 3: EmptyStackException expected.");
+        } catch (EmptyStackException e) {
+            // Expected.
+        }
+    }
+    
+    @TestTargets ({
+        @TestTargetNew(
+                level = TestLevel.COMPLETE,
+                method = "declarePrefix",
+                args = {String.class, String.class}
+        ),
+        @TestTargetNew(
+                level = TestLevel.COMPLETE,
+                method = "getPrefix",
+                args = {String.class}
+        )
+    })
+    public void testDeclare_GetPrefix() {
+        ns.pushContext();
+        
+        // Part 1: Check that xml and xmlns are not accepted as prefixes.
+        assertFalse("Test 1: Invalid prefix accepted.",
+                ns.declarePrefix("xml", marketUri));
+
+        assertFalse("Test 2: Invalid prefix accepted.",
+                ns.declarePrefix("xmlns", marketUri));
+        
+        // Part 2: Check that declarePrefix and getPrefix work for valid 
+        // prefixes.
+        assertTrue("Test 3: Valid prefix not accepted.",
+                ns.declarePrefix("ak", marketUri));
+        
+        assertTrue("Test 4: Incorrect prefix returned.",
+                ns.getPrefix(marketUri).equals("ak"));
+        
+        assertTrue("Test 5: Valid prefix not accepted.",
+                ns.declarePrefix("bk", marketUri));
+
+        assertTrue("Test 6: Incorrect prefix returned.",
+                expected.contains(ns.getPrefix(marketUri)));
+        
+        assertTrue("Test 7: Valid prefix not accepted.",
+                ns.declarePrefix("", defaultUri));
+        
+        // Part 3: Negative Tests for getPrefix.
+        assertNull("Test 8: Non-null value returned for the URI that is " +
+                "assigned to the default namespace.",
+                ns.getPrefix(defaultUri));
+        
+        assertNull("Test 9: Non-null value returned for an unassigned URI.",
+                ns.getPrefix(defaultUri + "/42"));
+    }
+    
+    @SuppressWarnings("unchecked")
+    @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getPrefixes",
+            args = {String.class}
+    )
+    public void testGetPrefixesLjava_lang_String() {
+        ArrayList<String> prefixes;
+        
+        prefixes = Collections.list(ns.getPrefixes(marketUri));
+        assertTrue("Test 1: Incorrect set of prefixes returned.",
+                expected.containsAll(prefixes) && prefixes.containsAll(expected));
+
+        prefixes = Collections.list(ns.getPrefixes(defaultUri));
+        assertTrue("Test 2: Default namespace prefix should not be returned.",
+                prefixes.size() == 0);
+        
+        prefixes = Collections.list(ns.getPrefixes(NamespaceSupport.XMLNS));
+        assertTrue("Test 3: xml prefix is missing.",
+                prefixes.contains("xml") && prefixes.size() == 1);
+
+        prefixes = Collections.list(ns.getPrefixes(defaultUri + "/42"));
+        assertTrue("Test 4: Non-empty enumeration returned for an unassigned URI.",
+                prefixes.size() == 0);
+    }
+    
+    @SuppressWarnings("unchecked")
+    @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getPrefixes",
+            args = {}
+    )
+    public void testGetPrefixes() {
+        ArrayList<String> prefixes;
+        
+        expected.add("xml");
+        
+        prefixes = Collections.list(ns.getPrefixes());
+        assertTrue("Test 1: Incorrect set of prefixes returned.",
+                expected.containsAll(prefixes) && prefixes.containsAll(expected));
+    }
+
+    @SuppressWarnings("unchecked")
+    @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getDeclaredPrefixes",
+            args = {}
+    )
+    public void testGetDeclaredPrefixes() {
+        ArrayList<String> prefixes;
+        
+        expected.add("");
+        
+        prefixes = Collections.list(ns.getDeclaredPrefixes());
+        assertTrue("Test 1: Incorrect set of prefixes returned.",
+                expected.containsAll(prefixes) && prefixes.containsAll(expected));
+    }
+
+    @TestTargets ({
+        @TestTargetNew(
+                level = TestLevel.COMPLETE,
+                method = "getURI",
+                args = {String.class}
+        ),
+        @TestTargetNew(
+                level = TestLevel.PARTIAL_COMPLETE,
+                method = "popContext",
+                args = {}
+        )
+    })
+    public void testGetUri() {
+        assertEquals("Test 1: Incorrect URI returned;",
+                marketUri, ns.getURI("bk"));
+        assertEquals("Test 2: Incorrect URI returned;",
+                defaultUri, ns.getURI(""));
+        assertNull("Test 3: Null expected for not-existing prefix.", 
+                ns.getURI("ck"));
+        
+        ns.popContext();
+        assertNull("Test 4: Null expected for not-existing prefix.", 
+                ns.getURI("bk"));
+        assertEquals("Test 5: Incorrect URI returned;",
+                NamespaceSupport.XMLNS, ns.getURI("xml"));
+    }
+
+    @TestTargets ({
+        @TestTargetNew(
+                level = TestLevel.PARTIAL_COMPLETE,
+                method = "setNamespaceDeclUris",
+                args = {boolean.class}
+        ),
+        @TestTargetNew(
+                level = TestLevel.COMPLETE,
+                method = "isNamespaceDeclUris",
+                args = {}
+        )        
+    })
+    public void testNamespaceDeclUris() {
+        
+        assertFalse("Test 1: Incorrect default value returned by isNamespaceDeclUris().",
+                ns.isNamespaceDeclUris());
+        
+        try {
+            ns.setNamespaceDeclUris(true);
+            fail("Test 2: IllegalStateException expected since a context has already been pushed in setUp().");
+        } catch (IllegalStateException e) {
+            // Expected.
+        }
+        
+        ns = new NamespaceSupport();
+        ns.setNamespaceDeclUris(true);
+        assertTrue("Test 3: Incorrect value returned by isNamespaceDeclUris().",
+                ns.isNamespaceDeclUris());
+
+        ns.setNamespaceDeclUris(false);
+        assertFalse("Test 4: Incorrect value returned by isNamespaceDeclUris().",
+                ns.isNamespaceDeclUris());
+    }
+        
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            method = "processName",
+            args = {String.class, String[].class, boolean.class}
+    )
+    public void testProcessName_Element() {
+        String[] parts = new String[3];
+        
+        assertNotNull("Test 1: Non-null value expected.", 
+                ns.processName("ak:hello", parts, false));
+        assertEquals("Test 2: Incorrect namespace URI;", marketUri, parts[0]);
+        assertEquals("Test 3: Incorrect local name;", "hello", parts[1]);
+        assertEquals("Test 4: Incorrect raw name;", "ak:hello", parts[2]);
+
+        assertNotNull("Test 5: Non-null value expected.", 
+                ns.processName("bk:", parts, false));
+        assertEquals("Test 6: Incorrect namespace URI;", marketUri, parts[0]);
+        assertEquals("Test 7: Incorrect local name;", "", parts[1]);
+        assertEquals("Test 8: Incorrect raw name;", "bk:", parts[2]);
+        
+        assertNotNull("Test 9: Non-null value expected.", 
+                ns.processName("world", parts, false));
+        assertEquals("Test 10: Incorrect namespace URI;", defaultUri, parts[0]);
+        assertEquals("Test 11: Incorrect local name;", "world", parts[1]);
+        assertEquals("Test 12: Incorrect raw name;", "world", parts[2]);
+        
+        assertNull("Test 13: Null expected for undeclared prefix.",
+                ns.processName("ck:lorem", parts, false));
+        
+        assertNull("Test 14: Null expected for xmlns prefix.",
+                ns.processName("xmlns:ipsum", parts, false));
+        
+        ns = new NamespaceSupport();
+        ns.pushContext();
+        assertNotNull("Test 15: Non-null value expected.", 
+                ns.processName("world", parts, false));
+        assertEquals("Test 16: Incorrect namespace URI;", "", parts[0]);
+        assertEquals("Test 17: Incorrect local name;", "world", parts[1]);
+        assertEquals("Test 18: Incorrect raw name;", "world", parts[2]);
+    }
+
+    @TestTargets ({
+        @TestTargetNew(
+                level = TestLevel.PARTIAL_COMPLETE,
+                method = "setNamespaceDeclUris",
+                args = {boolean.class}
+        ),
+        @TestTargetNew(
+                level = TestLevel.PARTIAL_COMPLETE,
+                method = "processName",
+                args = {String.class, String[].class, boolean.class}
+        )
+    })
+    public void testProcessName_Attribute() {
+        String[] parts = new String[3];
+        
+        assertNotNull("Test 1: Non-null value expected.", 
+                ns.processName("ak:hello", parts, true));
+        assertEquals("Test 2: Incorrect namespace URI;", marketUri, parts[0]);
+        assertEquals("Test 3: Incorrect local name;", "hello", parts[1]);
+        assertEquals("Test 4: Incorrect raw name;", "ak:hello", parts[2]);
+
+        assertNotNull("Test 5: Non-null value expected.", 
+                ns.processName("bk:", parts, true));
+        assertEquals("Test 6: Incorrect namespace URI;", marketUri, parts[0]);
+        assertEquals("Test 7: Incorrect local name;", "", parts[1]);
+        assertEquals("Test 8: Incorrect raw name;", "bk:", parts[2]);
+        
+        assertNotNull("Test 9: Non-null value expected.", 
+                ns.processName("world", parts, true));
+        assertEquals("Test 10: Incorrect namespace URI;", "", parts[0]);
+        assertEquals("Test 11: Incorrect local name;", "world", parts[1]);
+        assertEquals("Test 12: Incorrect raw name;", "world", parts[2]);
+        
+        assertNull("Test 13: Null expected for undeclared prefix.",
+                ns.processName("ck:lorem", parts, true));
+        
+        assertNull("Test 14: Null expected for xmlns prefix.",
+                ns.processName("xmlns:ipsum", parts, true));
+        
+        ns = new NamespaceSupport();
+        ns.setNamespaceDeclUris(true);
+        ns.pushContext();
+        assertNotNull("Test 15: Non-null value expected.", 
+                ns.processName("xmlns", parts, true));
+        assertEquals("Test 16: Incorrect namespace URI;", NamespaceSupport.NSDECL, parts[0]);
+        assertEquals("Test 17: Incorrect local name;", "xmlns", parts[1]);
+        assertEquals("Test 18: Incorrect raw name;", "xmlns", parts[2]);
+    }
+
+    @SuppressWarnings("unchecked")
+    private int countPrefixes() 
+    {
+        ArrayList<String> prefixes = Collections.list(ns.getPrefixes());
+        return prefixes.size();
+    }
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/helpers/ParserAdapterTest.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/ParserAdapterTest.java
new file mode 100644
index 0000000..27a7e78
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/ParserAdapterTest.java
@@ -0,0 +1,468 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.helpers;
+
+import java.io.IOException;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.AttributeList;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.Parser;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.helpers.AttributeListImpl;
+import org.xml.sax.helpers.LocatorImpl;
+import org.xml.sax.helpers.ParserAdapter;
+
+import tests.api.org.xml.sax.support.MethodLogger;
+import tests.api.org.xml.sax.support.MockHandler;
+import tests.api.org.xml.sax.support.MockParser;
+import tests.api.org.xml.sax.support.MockResolver;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+@SuppressWarnings("deprecation")
+@TestTargetClass(ParserAdapter.class)
+public class ParserAdapterTest extends TestCase {
+
+    // Note: In many cases we can only test that delegation works
+    // properly. The rest is outside the scope of the specification.
+
+    private final static String FEATURES = "http://xml.org/sax/features/";
+
+    private final static String NAMESPACES = FEATURES + "namespaces";
+    
+    private final static String NAMESPACE_PREFIXES = FEATURES
+                                                        + "namespace-prefixes";
+    
+    private final static String XMLNS_URIs = FEATURES + "xmlns-uris";
+    
+    private MethodLogger logger = new MethodLogger();
+    
+    private MockHandler handler = new MockHandler(logger);
+    
+    private Parser parser = new MockParser(logger);
+    
+    private ParserAdapter adapter = new ParserAdapter(parser);
+    
+    private void assertEquals(Object[] a, Object[] b) {
+        assertEquals(a.length, b.length);
+        
+        for (int i = 0; i < a.length; i++) {
+            assertEquals("Element #" + i + " must be equal", a[i], b[i]);
+        }
+    }
+
+    @Override
+    public void setUp() {
+        adapter.setContentHandler(handler);
+        adapter.setDTDHandler(handler);
+        adapter.setErrorHandler(handler);
+    }
+    
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "ParserAdapter",
+        args = { }
+    )
+    public void testParserAdapter() {
+        System.setProperty("org.xml.sax.parser",
+                "tests.api.org.xml.sax.support.DoNothingParser");
+
+        try {
+            new ParserAdapter();
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "ParserAdapter",
+        args = { Parser.class }
+    )
+    public void testParserAdapterParser() {
+        // Ordinary case
+        @SuppressWarnings("unused")
+        ParserAdapter adapter = new ParserAdapter(parser);
+
+        // Null case
+        try {
+            adapter = new ParserAdapter(null);
+            fail("NullPointerException expected");
+        } catch (NullPointerException e) {
+            // Expected
+        }
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getFeature",
+            args = { String.class }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setFeature",
+            args = { String.class, boolean.class }
+        )
+    })
+    public void testGetSetFeature() {
+        String[] features = new String[] { NAMESPACES, NAMESPACE_PREFIXES,
+                XMLNS_URIs };
+
+        for (String s: features) {
+            try {
+                adapter.setFeature(s, true);
+                assertEquals(true, adapter.getFeature(s));
+                
+                adapter.setFeature(s, false);
+                assertEquals(false, adapter.getFeature(s));
+            } catch (SAXException e) {
+                throw new RuntimeException("Unexpected exception", e);
+            }
+        }
+        
+        try {
+            adapter.setFeature("http://argle.bargle", true);
+            fail("SAXNotRecognizedException expected");
+        } catch (SAXNotRecognizedException e) {
+            // Expected
+        } catch (SAXNotSupportedException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getProperty",
+            args = { String.class }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setProperty",
+            args = { String.class, Object.class }
+        )
+    })
+    public void testGetSetProperty() {
+        try {
+            adapter.setProperty("http://argle.bargle", ":)");
+            fail("SAXNotRecognizedException expected");
+        } catch (SAXNotRecognizedException e) {
+            // Expected
+        } catch (SAXNotSupportedException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        try {
+            adapter.getProperty("http://argle.bargle");
+            fail("SAXNotRecognizedException expected");
+        } catch (SAXNotRecognizedException e) {
+            // Expected
+        } catch (SAXNotSupportedException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getEntityResolver",
+            args = { }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEntityResolver",
+            args = { EntityResolver.class }
+        )
+    })
+    public void testGetSetEntityResolver() {
+        EntityResolver resolver = new MockResolver();
+
+        adapter.setEntityResolver(resolver);
+        assertEquals(resolver, adapter.getEntityResolver());
+        
+        adapter.setEntityResolver(null);
+        assertEquals(null, adapter.getEntityResolver());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getDTDHandler",
+            args = { }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setDTDHandler",
+            args = { DTDHandler.class }
+        )
+    })
+    public void testGetSetDTDHandler() {
+        adapter.setDTDHandler(null);
+        assertEquals(null, adapter.getDTDHandler());
+        
+        adapter.setDTDHandler(handler);
+        assertEquals(handler, adapter.getDTDHandler());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getContentHandler",
+            args = { }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setContentHandler",
+            args = { ContentHandler.class }
+        )
+    })
+    public void testGetSetContentHandler() {
+        adapter.setContentHandler(null);
+        assertEquals(null, adapter.getContentHandler());
+        
+        adapter.setContentHandler(handler);
+        assertEquals(handler, adapter.getContentHandler());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getErrorHandler",
+            args = { }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setErrorHandler",
+            args = { ErrorHandler.class }
+        )
+    })
+    public void testGetSetErrorHandler() {
+        adapter.setErrorHandler(null);
+        assertEquals(null, adapter.getErrorHandler());
+        
+        adapter.setErrorHandler(handler);
+        assertEquals(handler, adapter.getErrorHandler());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "parse",
+        args = { String.class }
+    )
+    public void testParseString() {
+        try {
+            adapter.parse("foo");
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        } catch (IOException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        // The SAX RI creates an InputSource itself and then delegates to the
+        // "other" parse method.
+        assertEquals("parse", logger.getMethod());
+        assertEquals(InputSource.class, logger.getArgs()[0].getClass());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "parse",
+        args = { InputSource.class }
+    )
+    public void testParseInputSource() {
+        InputSource source = new InputSource("foo");
+        
+        try {
+            adapter.parse(source);
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        } catch (IOException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        assertEquals("parse", logger.getMethod());
+        assertEquals(new Object[] { source }, logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setDocumentLocator",
+        args = { Locator.class }
+    )
+    public void testSetDocumentLocator() {
+        Locator l = new LocatorImpl();
+
+        adapter.setDocumentLocator(l);
+        
+        assertEquals(logger.size(), 1);
+        assertEquals("setDocumentLocator", logger.getMethod());
+        assertEquals(new Object[] { l }, logger.getArgs());
+        
+        adapter.setDocumentLocator(null);
+        
+        assertEquals(logger.size(), 2);
+        assertEquals("setDocumentLocator", logger.getMethod());
+        assertEquals(new Object[] { null }, logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "startDocument",
+        args = { }
+    )
+    public void testStartDocument() {
+        try {
+            adapter.startDocument();
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        assertEquals(logger.size(), 1);
+        assertEquals("startDocument", logger.getMethod());
+        assertEquals(new Object[] {}, logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "endDocument",
+        args = { }
+    )
+    public void testEndDocument() {
+        try {
+            adapter.endDocument();
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        assertEquals(logger.size(), 1);
+        assertEquals("endDocument", logger.getMethod());
+        assertEquals(new Object[] {}, logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "startElement",
+        args = { String.class, AttributeList.class }
+    )
+    public void testStartElement() {
+        AttributeListImpl atts = new AttributeListImpl();
+        atts.addAttribute("john:doe", "int", "42");
+
+        try {
+            adapter.startDocument();
+            adapter.startElement("foo:bar", atts);
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        assertEquals("startElement", logger.getMethod());
+        assertEquals("", logger.getArgs()[0]);
+        assertEquals("", logger.getArgs()[1]);
+        assertEquals("foo:bar", logger.getArgs()[2]);
+        assertEquals("john:doe", ((Attributes)logger.getArgs()[3]).getQName(0));
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "endElement",
+        args = { String.class }
+    )
+    public void testEndElement() {
+        AttributeListImpl atts = new AttributeListImpl();
+        atts.addAttribute("john:doe", "int", "42");
+
+        try {
+            adapter.startDocument();
+            adapter.startElement("foo:bar", atts);
+            adapter.endElement("foo:bar");
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        assertEquals("endElement", logger.getMethod());
+        assertEquals(new String[] { "", "", "foo:bar" }, logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "characters",
+        args = { char[].class, int.class, int.class }
+    )
+    public void testCharacters() {
+        char[] ch = "Android".toCharArray();
+
+        try {
+            adapter.characters(ch, 2, 5);
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        assertEquals(logger.size(), 1);
+        assertEquals("characters", logger.getMethod());
+        assertEquals(new Object[] { ch, 2, 5 }, logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "ignorableWhitespace",
+        args = { char[].class, int.class, int.class }
+    )
+    public void testIgnorableWhitespace() {
+        char[] ch = "     ".toCharArray();
+
+        try {
+            adapter.ignorableWhitespace(ch, 0, 5);
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        assertEquals(logger.size(), 1);
+        assertEquals("ignorableWhitespace", logger.getMethod());
+        assertEquals(new Object[] { ch, 0, 5 }, logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "processingInstruction",
+        args = { String.class, String.class }
+    )
+    public void testProcessingInstruction() {
+        try {
+            adapter.processingInstruction("foo", "bar");
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        assertEquals(logger.size(), 1);
+        assertEquals("processingInstruction", logger.getMethod());
+        assertEquals(new Object[] { "foo" , "bar" }, logger.getArgs());
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/helpers/ParserFactoryTest.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/ParserFactoryTest.java
new file mode 100644
index 0000000..ebf2a04
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/ParserFactoryTest.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.helpers;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.helpers.ParserFactory;
+
+@SuppressWarnings("deprecation")
+@TestTargetClass(ParserFactory.class)
+public class ParserFactoryTest extends TestCase {
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "makeParser",
+        args = { },
+        notes = "Checks everything except META-INF case"
+    )
+    public void testMakeParser() {
+        // Property not set at all
+        try {
+            ParserFactory.makeParser();
+        } catch (NullPointerException e) {
+            // Expected
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        // Unknown class
+        System.setProperty("org.xml.sax.parser", "foo.bar.SAXParser");
+        
+        try {
+            ParserFactory.makeParser();
+        } catch (ClassNotFoundException e) {
+            // Expected
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        // Non-accessible class
+        System.setProperty("org.xml.sax.parser",
+                "tests.api.org.xml.sax.support.NoAccessParser");
+        
+        try {
+            ParserFactory.makeParser();
+        } catch (IllegalAccessException e) {
+            // Expected
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        // Non-instantiable class
+        System.setProperty("org.xml.sax.parser",
+                "tests.api.org.xml.sax.support.NoInstanceParser");
+        
+        try {
+            ParserFactory.makeParser();
+        } catch (InstantiationException e) {
+            // Expected
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        // Non-Parser class
+        System.setProperty("org.xml.sax.parser",
+                "tests.api.org.xml.sax.support.NoSubclassParser");
+        
+        try {
+            ParserFactory.makeParser();
+        } catch (ClassCastException e) {
+            // Expected
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        // Good one, finally
+        System.setProperty("org.xml.sax.parser",
+                "tests.api.org.xml.sax.support.DoNothingParser");
+        
+        try {
+            ParserFactory.makeParser();
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "makeParser",
+        args = { String.class }
+    )
+    public void testMakeParserString() {
+        // No class
+        try {
+            ParserFactory.makeParser(null);
+        } catch (NullPointerException e) {
+            // Expected
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        // Unknown class
+        try {
+            ParserFactory.makeParser("foo.bar.SAXParser");
+        } catch (ClassNotFoundException e) {
+            // Expected
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        // Non-accessible class
+        try {
+            ParserFactory.makeParser(
+                    "tests.api.org.xml.sax.support.NoAccessParser");
+        } catch (IllegalAccessException e) {
+            // Expected
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        // Non-instantiable class
+        try {
+            ParserFactory.makeParser(
+                    "tests.api.org.xml.sax.support.NoInstanceParser");
+        } catch (InstantiationException e) {
+            // Expected
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        // Non-Parser class
+        try {
+            ParserFactory.makeParser(
+                    "tests.api.org.xml.sax.support.NoSubclassParser");
+        } catch (ClassCastException e) {
+            // Expected
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        // Good one, finally
+        try {
+            ParserFactory.makeParser(
+                    "tests.api.org.xml.sax.support.DoNothingParser");
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLFilterImplTest.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLFilterImplTest.java
new file mode 100644
index 0000000..6586461
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLFilterImplTest.java
@@ -0,0 +1,678 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.helpers;
+
+import java.io.IOException;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.AttributesImpl;
+import org.xml.sax.helpers.LocatorImpl;
+import org.xml.sax.helpers.XMLFilterImpl;
+
+import tests.api.org.xml.sax.support.MethodLogger;
+import tests.api.org.xml.sax.support.MockFilter;
+import tests.api.org.xml.sax.support.MockHandler;
+import tests.api.org.xml.sax.support.MockResolver;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+@TestTargetClass(XMLFilterImpl.class)
+public class XMLFilterImplTest extends TestCase {
+
+    // Note: In many cases we can only test that delegation works
+    // properly. The rest is outside the scope of the specification.
+
+    private MethodLogger logger = new MethodLogger();
+    
+    private MockHandler handler = new MockHandler(logger);
+
+    private XMLFilterImpl parent = new MockFilter(logger);
+
+    private XMLFilterImpl child = new XMLFilterImpl(parent);
+
+    private XMLFilterImpl orphan = new XMLFilterImpl();
+    
+    private void assertEquals(Object[] a, Object[] b) {
+        assertEquals(a.length, b.length);
+        
+        for (int i = 0; i < a.length; i++) {
+            assertEquals("Element #" + i + " must be equal", a[i], b[i]);
+        }
+    }
+    
+    public void setUp() {
+        parent.setContentHandler(handler);
+        parent.setDTDHandler(handler);
+        parent.setErrorHandler(handler);
+        
+        child.setContentHandler(handler);
+        child.setDTDHandler(handler);
+        child.setErrorHandler(handler);
+    }
+    
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "XMLFilterImpl",
+        args = { }
+    )
+    public void testXMLFilterImpl() {
+        assertEquals(null, parent.getParent());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "XMLFilterImpl",
+        args = { XMLReader.class }
+    )
+    public void testXMLFilterImplXMLReader() {
+        // Ordinary case
+        assertEquals(null, parent.getParent());
+        
+        // null case
+        XMLFilterImpl filter = new XMLFilterImpl(null);
+        assertEquals(null, filter.getParent());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getParent",
+            args = { }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setParent",
+            args = { XMLReader.class }
+        )
+    })
+    public void testGetSetParent() {
+        child.setParent(null);
+        assertEquals(null, child.getParent());
+
+        child.setParent(parent);
+        assertEquals(parent, child.getParent());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getFeature",
+            args = { String.class }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setFeature",
+            args = { String.class, boolean.class }
+        )
+    })
+    public void testGetSetFeature() {
+        // Ordinary case
+        try {
+            child.setFeature("foo", true);
+            assertEquals(true, child.getFeature("foo"));
+            
+            child.setFeature("foo", false);
+            assertEquals(false, child.getFeature("foo"));
+        } catch (SAXNotRecognizedException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        } catch (SAXNotSupportedException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        // No parent case
+        try {
+            orphan.setFeature("foo", false);
+            fail("SAXNotRecognizedException expected");
+        } catch (SAXNotRecognizedException e) {
+            // Expected
+        } catch (SAXNotSupportedException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getProperty",
+            args = { String.class }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setProperty",
+            args = { String.class, Object.class }
+        )
+    })
+    public void testGetSetProperty() {
+        // Ordinary case
+        try {
+            child.setProperty("foo", "bar");
+            assertEquals("bar", child.getProperty("foo"));
+            
+            child.setProperty("foo", null);
+            assertEquals(null, child.getProperty("foo"));
+        } catch (SAXNotRecognizedException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        } catch (SAXNotSupportedException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        // No parent case
+        try {
+            orphan.setProperty("foo", "bar");
+            fail("SAXNotRecognizedException expected");
+        } catch (SAXNotRecognizedException e) {
+            // Expected
+        } catch (SAXNotSupportedException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getEntityResolver",
+            args = { }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEntityResolver",
+            args = { EntityResolver.class }
+        )
+    })
+    public void testGetSetEntityResolver() {
+        EntityResolver resolver = new MockResolver();
+
+        parent.setEntityResolver(resolver);
+        assertEquals(resolver, parent.getEntityResolver());
+        
+        parent.setEntityResolver(null);
+        assertEquals(null, parent.getEntityResolver());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getDTDHandler",
+            args = { }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setDTDHandler",
+            args = { DTDHandler.class }
+        )
+    })
+    public void testGetSetDTDHandler() {
+        parent.setDTDHandler(null);
+        assertEquals(null, parent.getDTDHandler());
+        
+        parent.setDTDHandler(handler);
+        assertEquals(handler, parent.getDTDHandler());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getContentHandler",
+            args = { }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setContentHandler",
+            args = { ContentHandler.class }
+        )
+    })
+    public void testGetSetContentHandler() {
+        parent.setContentHandler(null);
+        assertEquals(null, parent.getContentHandler());
+        
+        parent.setContentHandler(handler);
+        assertEquals(handler, parent.getContentHandler());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getErrorHandler",
+            args = { }
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setErrorHandler",
+            args = { ErrorHandler.class }
+        )
+    })
+    public void testGetSetErrorHandler() {
+        parent.setErrorHandler(null);
+        assertEquals(null, parent.getErrorHandler());
+        
+        parent.setErrorHandler(handler);
+        assertEquals(handler, parent.getErrorHandler());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "parse",
+        args = { InputSource.class }
+    )
+    public void testParseInputSource() {
+        InputSource is = new InputSource();
+
+        // Ordinary case
+        try {
+            child.parse(is);
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        } catch (IOException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        assertEquals(1, logger.size());
+        assertEquals("parse", logger.getMethod());
+        
+        // No parent case
+        try {
+            orphan.parse(is);
+            fail("NullPointerException expected");
+        } catch (NullPointerException e) {
+            // Expected
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        } catch (IOException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "parse",
+        args = { String.class }
+    )
+    public void testParseString() {
+        // Ordinary case
+        try {
+            child.parse("foo");
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        } catch (IOException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        assertEquals(1, logger.size());
+        assertEquals("parse", logger.getMethod());
+        
+        // No parent case
+        try {
+            orphan.parse("foo");
+            fail("NullPointerException expected");
+        } catch (NullPointerException e) {
+            // Expected
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        } catch (IOException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "resolveEntity",
+        args = { String.class, String.class }
+    )
+    public void testResolveEntity() {
+        InputSource expected = new InputSource();
+
+        MockResolver resolver = new MockResolver();
+        resolver.addEntity("foo", "bar", expected);
+
+        InputSource result = null;
+
+        parent.setEntityResolver(resolver);
+
+        // Ordinary case
+        try {
+            result = parent.resolveEntity("foo", "bar");
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        } catch (IOException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        assertEquals(expected, result);
+
+        // No entity resolver case
+        parent.setEntityResolver(null);
+
+        try {
+            result = parent.resolveEntity("foo", "bar");
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        } catch (IOException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        assertEquals(null, result);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "notationDecl",
+        args = { String.class, String.class, String.class }
+    )
+    public void testNotationDecl() {
+        try {
+            parent.notationDecl("foo", "bar", "foobar");
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        assertEquals(logger.size(), 1);
+        assertEquals("notationDecl", logger.getMethod());
+        assertEquals(new Object[] { "foo", "bar", "foobar" },
+                logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "unparsedEntityDecl",
+        args = { String.class, String.class, String.class, String.class }
+    )
+    public void testUnparsedEntityDecl() {
+        try {
+            parent.unparsedEntityDecl("foo", "bar", "gabba", "hey");
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        assertEquals(logger.size(), 1);
+        assertEquals("unparsedEntityDecl", logger.getMethod());
+        assertEquals(new Object[] { "foo", "bar", "gabba", "hey" },
+                logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setDocumentLocator",
+        args = { Locator.class }
+    )
+    public void testSetDocumentLocator() {
+        Locator l = new LocatorImpl();
+        
+        child.setDocumentLocator(l);
+
+        assertEquals(logger.size(), 1);
+        assertEquals("setDocumentLocator", logger.getMethod());
+        assertEquals(new Object[] { l }, logger.getArgs());
+        
+        child.setDocumentLocator(null);
+        
+        assertEquals(logger.size(), 2);
+        assertEquals("setDocumentLocator", logger.getMethod());
+        assertEquals(new Object[] { null }, logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "startDocument",
+        args = { }
+    )
+    public void testStartDocument() {
+        try {
+            parent.startDocument();
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        assertEquals(logger.size(), 1);
+        assertEquals("startDocument", logger.getMethod());
+        assertEquals(new Object[] {}, logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "endDocument",
+        args = { }
+    )
+    public void testEndDocument() {
+        try {
+            parent.endDocument();
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        assertEquals(logger.size(), 1);
+        assertEquals("endDocument", logger.getMethod());
+        assertEquals(new Object[] {}, logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "startPrefixMapping",
+        args = { String.class, String.class }
+    )
+    public void testStartPrefixMapping() {
+        try {
+            parent.startPrefixMapping("foo", "http://some.uri");
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        assertEquals(logger.size(), 1);
+        assertEquals("startPrefixMapping", logger.getMethod());
+        assertEquals(new Object[] { "foo", "http://some.uri" },
+                logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "endPrefixMapping",
+        args = { String.class }
+    )
+    public void testEndPrefixMapping() {
+        try {
+            parent.endPrefixMapping("foo");
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        assertEquals(logger.size(), 1);
+        assertEquals("endPrefixMapping", logger.getMethod());
+        assertEquals(new Object[] { "foo" }, logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "startElement",
+        args = { String.class, String.class, String.class, Attributes.class }
+    )
+    public void testStartElement() {
+        Attributes atts = new AttributesImpl();
+
+        try {
+            parent.startElement("http://some.uri", "bar", "foo:bar", atts);
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        assertEquals(logger.size(), 1);
+        assertEquals("startElement", logger.getMethod());
+        assertEquals(new Object[] { "http://some.uri", "bar", "foo:bar", atts },
+                logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "endElement",
+        args = { String.class, String.class, String.class }
+    )
+    public void testEndElement() {
+        try {
+            parent.endElement("http://some.uri", "bar", "foo:bar");
+         } catch (SAXException e) {
+             throw new RuntimeException("Unexpected exception", e);
+         }
+         
+         assertEquals(logger.size(), 1);
+         assertEquals("endElement", logger.getMethod());
+         assertEquals(new Object[] { "http://some.uri", "bar", "foo:bar" },
+                 logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "characters",
+        args = { char[].class, int.class, int.class }
+    )
+    public void testCharacters() {
+        char[] ch = "Android".toCharArray();
+
+        try {
+            parent.characters(ch, 2, 5);
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        assertEquals(logger.size(), 1);
+        assertEquals("characters", logger.getMethod());
+        assertEquals(new Object[] { ch, 2, 5 }, logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "ignorableWhitespace",
+        args = { char[].class, int.class, int.class }
+    )
+    public void testIgnorableWhitespace() {
+        char[] ch = "     ".toCharArray();
+
+        try {
+            parent.ignorableWhitespace(ch, 0, 5);
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        assertEquals(logger.size(), 1);
+        assertEquals("ignorableWhitespace", logger.getMethod());
+        assertEquals(new Object[] { ch, 0, 5 }, logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "processingInstruction",
+        args = { String.class, String.class }
+    )
+    public void testProcessingInstruction() {
+        try {
+            parent.processingInstruction("foo", "bar");
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        assertEquals(logger.size(), 1);
+        assertEquals("processingInstruction", logger.getMethod());
+        assertEquals(new Object[] { "foo", "bar" }, logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "skippedEntity",
+        args = { String.class }
+    )
+    public void testSkippedEntity() {
+        try {
+            parent.skippedEntity("foo");
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        assertEquals(logger.size(), 1);
+        assertEquals("skippedEntity", logger.getMethod());
+        assertEquals(new Object[] { "foo" }, logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "warning",
+        args = { SAXParseException.class }
+    )
+    public void testWarning() {
+        SAXParseException exception = new SAXParseException("Oops!", null);
+
+        try {
+            parent.warning(exception);
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        assertEquals(logger.size(), 1);
+        assertEquals("warning", logger.getMethod());
+        assertEquals(new Object[] { exception }, logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "error",
+        args = { SAXParseException.class }
+    )
+    public void testError() {
+        SAXParseException exception = new SAXParseException("Oops!", null);
+        
+        try {
+            parent.error(exception);
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        assertEquals(logger.size(), 1);
+        assertEquals("error", logger.getMethod());
+        assertEquals(new Object[] { exception }, logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "fatalError",
+        args = { SAXParseException.class }
+    )
+    public void testFatalError() {
+        SAXParseException exception = new SAXParseException("Oops!", null);
+        
+        try {
+            parent.fatalError(exception);
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        assertEquals(logger.size(), 1);
+        assertEquals("fatalError", logger.getMethod());
+        assertEquals(new Object[] { exception }, logger.getArgs());
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLReaderAdapterTest.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLReaderAdapterTest.java
new file mode 100644
index 0000000..20488c5
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLReaderAdapterTest.java
@@ -0,0 +1,414 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.helpers;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.AttributeList;
+import org.xml.sax.Attributes;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.DocumentHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.AttributesImpl;
+import org.xml.sax.helpers.LocatorImpl;
+import org.xml.sax.helpers.XMLReaderAdapter;
+
+import tests.api.org.xml.sax.support.MethodLogger;
+import tests.api.org.xml.sax.support.MockHandler;
+import tests.api.org.xml.sax.support.MockReader;
+import tests.api.org.xml.sax.support.MockResolver;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+@SuppressWarnings("deprecation")
+@TestTargetClass(XMLReaderAdapter.class)
+public class XMLReaderAdapterTest extends TestCase {
+
+    // Note: In many cases we can only test that delegation works
+    // properly. The rest is outside the scope of the specification.
+
+    private MethodLogger logger = new MethodLogger();
+    
+    private MockHandler handler = new MockHandler(logger);
+    
+    private XMLReader reader = new MockReader(logger);
+    
+    private XMLReaderAdapter adapter = new XMLReaderAdapter(reader);
+    
+    private void assertEquals(Object[] a, Object[] b) {
+        assertEquals(a.length, b.length);
+        
+        for (int i = 0; i < a.length; i++) {
+            assertEquals("Element #" + i + " must be equal", a[i], b[i]);
+        }
+    }
+
+    @Override
+    public void setUp() {
+        adapter.setDocumentHandler(handler);
+        adapter.setDTDHandler(handler);
+        adapter.setErrorHandler(handler);
+    }
+    
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "XMLReaderAdapter",
+        args = { }
+    )
+    public void testXMLReaderAdapter() {
+        System.setProperty("org.xml.sax.driver",
+                "tests.api.org.xml.sax.support.DoNothingXMLReader");
+        
+        try {
+            new XMLReaderAdapter();
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "XMLReaderAdapter",
+        args = { XMLReader.class }
+    )
+    public void testXMLReaderAdapterXMLReader() {
+        // Ordinary case
+        @SuppressWarnings("unused")
+        XMLReaderAdapter adapter = new XMLReaderAdapter(reader);
+
+        // Null case
+        try {
+            adapter = new XMLReaderAdapter(null);
+            fail("NullPointerException expected");
+        } catch (NullPointerException e) {
+            // Expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setLocale",
+        args = { Locale.class }
+    )
+    public void testSetLocale() {
+        // SAX RI does not support this, hence always expect exception
+        try {
+            adapter.setLocale(Locale.getDefault());
+            fail("SAXException expected");
+        } catch (SAXException e) {
+            // Expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setEntityResolver",
+        args = { EntityResolver.class }
+    )
+    public void testSetEntityResolver() {
+        EntityResolver resolver = new MockResolver();
+
+        // Ordinary case
+        adapter.setEntityResolver(resolver);
+        assertEquals(resolver, reader.getEntityResolver());
+        
+        // null case
+        adapter.setEntityResolver(null);
+        assertEquals(null, reader.getEntityResolver());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setDTDHandler",
+        args = { DTDHandler.class }
+    )
+    public void testSetDTDHandler() {
+        // Ordinary case
+        assertEquals(handler, reader.getDTDHandler());
+        
+        // null case
+        adapter.setDTDHandler(null);
+        assertEquals(null, reader.getDTDHandler());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setDocumentHandler",
+        args = { DocumentHandler.class }
+    )
+    public void testSetDocumentHandler() {
+        // There is no getter for the DocumentHandler, so we can only test
+        // indirectly whether is has been set correctly.
+        try {
+            adapter.startDocument();
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        assertEquals("startDocument", logger.getMethod());
+        assertEquals(new Object[] { }, logger.getArgs());
+
+        // null case
+        adapter.setDocumentHandler(null);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setErrorHandler",
+        args = { ErrorHandler.class }
+    )
+    public void testSetErrorHandler() {
+        // Ordinary case
+        assertEquals(handler, reader.getErrorHandler());
+        
+        // null case
+        adapter.setErrorHandler(null);
+        assertEquals(null, reader.getErrorHandler());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "parse",
+        args = { String.class }
+    )
+    public void testParseString() {
+        try {
+            adapter.parse("foo");
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        } catch (IOException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        // The SAX RI creates an InputSource itself and then delegates to the
+        // "other" parse method.
+        assertEquals("parse", logger.getMethod(0));
+        assertEquals(InputSource.class, logger.getArgs(0)[0].getClass());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "parse",
+        args = { InputSource.class }
+    )
+    public void testParseInputSource() {
+        InputSource source = new InputSource("foo");
+        
+        try {
+            adapter.parse(source);
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        } catch (IOException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        assertEquals("parse", logger.getMethod());
+        assertEquals(new Object[] { source }, logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "setDocumentLocator",
+        args = { Locator.class }
+    )
+    public void testSetDocumentLocator() {
+        // Ordinary case
+        LocatorImpl locator = new LocatorImpl();
+        adapter.setDocumentLocator(locator);
+        
+        assertEquals("setDocumentLocator", logger.getMethod());
+        assertEquals(new Object[] { locator }, logger.getArgs());
+
+        // null case (for the DocumentHandler itself!)
+        adapter.setDocumentHandler(null);
+        adapter.setDocumentLocator(locator);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "startDocument",
+        args = { }
+    )
+    public void testStartDocument() {
+        try {
+            adapter.startDocument();
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        assertEquals(logger.size(), 1);
+        assertEquals("startDocument", logger.getMethod());
+        assertEquals(new Object[] {}, logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "endDocument",
+        args = { }
+    )
+    public void testEndDocument() {
+        try {
+            adapter.endDocument();
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        assertEquals(logger.size(), 1);
+        assertEquals("endDocument", logger.getMethod());
+        assertEquals(new Object[] {}, logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "startPrefixMapping",
+        args = { String.class, String.class }
+    )
+    public void testStartPrefixMapping() {
+        adapter.startPrefixMapping("foo", "http://some.uri");
+        assertEquals(logger.size(), 0);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "endPrefixMapping",
+        args = { String.class }
+    )
+    public void testEndPrefixMapping() {
+        adapter.endPrefixMapping("foo");
+        assertEquals(logger.size(), 0);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "startElement",
+        args = { String.class, String.class, String.class, Attributes.class }
+    )
+    public void testStartElement() {
+        AttributesImpl atts = new AttributesImpl();
+        atts.addAttribute("http://some.other.uri", "gabba", "gabba:hey",
+                "int", "42");
+
+        try {
+            adapter.startElement("http://some.uri", "bar", "foo:bar", atts);
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        assertEquals(logger.size(), 1);
+        assertEquals("startElement", logger.getMethod());
+        assertEquals("foo:bar", logger.getArgs()[0]);
+        assertEquals("gabba:hey",
+                ((AttributeList)logger.getArgs()[1]).getName(0));
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "endElement",
+        args = { String.class, String.class, String.class }
+    )
+    public void testEndElement() {
+        try {
+            adapter.endElement("http://some.uri", "bar", "foo:bar");
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        assertEquals(logger.size(), 1);
+        assertEquals("endElement", logger.getMethod());
+        assertEquals(new Object[] { "foo:bar" }, logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "characters",
+        args = { char[].class, int.class, int.class }
+    )
+    public void testCharacters() {
+        char[] ch = "Android".toCharArray();
+
+        try {
+            adapter.characters(ch, 2, 5);
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        assertEquals(logger.size(), 1);
+        assertEquals("characters", logger.getMethod());
+        assertEquals(new Object[] { ch, 2, 5 }, logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "ignorableWhitespace",
+        args = { char[].class, int.class, int.class }
+    )
+    public void testIgnorableWhitespace() {
+        char[] ch = "     ".toCharArray();
+
+        try {
+            adapter.ignorableWhitespace(ch, 0, 5);
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        assertEquals(logger.size(), 1);
+        assertEquals("ignorableWhitespace", logger.getMethod());
+        assertEquals(new Object[] { ch, 0, 5 }, logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "processingInstruction",
+        args = { String.class, String.class }
+    )
+    public void testProcessingInstruction() {
+        try {
+            adapter.processingInstruction("foo", "bar");
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        assertEquals(logger.size(), 1);
+        assertEquals("processingInstruction", logger.getMethod());
+        assertEquals(new Object[] { "foo" , "bar" }, logger.getArgs());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "skippedEntity",
+        args = { String.class }
+    )
+    public void testSkippedEntity() {
+        try {
+            adapter.skippedEntity("foo");
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        assertEquals(logger.size(), 0);
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLReaderFactoryTest.java b/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLReaderFactoryTest.java
new file mode 100644
index 0000000..bfb1bd1
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/helpers/XMLReaderFactoryTest.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.helpers;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+@TestTargetClass(XMLReaderFactory.class)
+public class XMLReaderFactoryTest extends TestCase {
+
+    @TestTargetNew(
+        level = TestLevel.SUFFICIENT,
+        method = "createXMLReader",
+        args = { },
+        notes = "Checks everything except META-INF case"
+    )
+    public void testCreateXMLReader() {
+        // Property not set at all
+        try {
+            XMLReaderFactory.createXMLReader();
+        } catch (SAXException e) {
+            // Expected
+        }
+
+        // Unknown class
+        System.setProperty("org.xml.sax.driver", "foo.bar.XMLReader");
+        
+        try {
+            XMLReaderFactory.createXMLReader();
+        } catch (SAXException e) {
+            // Expected
+        }
+        
+        // Non-accessible class
+        System.setProperty("org.xml.sax.driver",
+                "tests.api.org.xml.sax.support.NoAccessXMLReader");
+        
+        try {
+            XMLReaderFactory.createXMLReader();
+        } catch (SAXException e) {
+            // Expected
+        }
+        
+        // Non-instantiable class
+        System.setProperty("org.xml.sax.driver",
+                "tests.api.org.xml.sax.support.NoInstanceXMLReader");
+        
+        try {
+            XMLReaderFactory.createXMLReader();
+        } catch (SAXException e) {
+            // Expected
+        }
+        
+        // Non-XMLReader class
+        System.setProperty("org.xml.sax.driver",
+                "tests.api.org.xml.sax.support.NoSubclassXMLReader");
+        
+        try {
+            XMLReaderFactory.createXMLReader();
+        } catch (ClassCastException e) {
+            // Expected
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+        // Good one, finally
+        System.setProperty("org.xml.sax.driver",
+                "tests.api.org.xml.sax.support.DoNothingXMLReader");
+        
+        try {
+            XMLReaderFactory.createXMLReader();
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+        
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "createXMLReader",
+        args = { String.class }
+    )
+    public void testMakeParserString() {
+        // No class
+        try {
+            XMLReaderFactory.createXMLReader(null);
+        } catch (NullPointerException e) {
+            // Expected
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+        // Unknown class
+        try {
+            XMLReaderFactory.createXMLReader("foo.bar.XMLReader");
+        } catch (SAXException e) {
+            // Expected
+        }
+        
+        // Non-accessible class
+        try {
+            XMLReaderFactory.createXMLReader(
+                    "tests.api.org.xml.sax.support.NoAccessXMLReader");
+        } catch (SAXException e) {
+            // Expected
+        }
+        
+        // Non-instantiable class
+        try {
+            XMLReaderFactory.createXMLReader(
+                    "tests.api.org.xml.sax.support.NoInstanceXMLReader");
+        } catch (SAXException e) {
+            // Expected
+        }
+        
+        // Non-Parser class
+        try {
+            XMLReaderFactory.createXMLReader(
+                    "tests.api.org.xml.sax.support.NoSubclassXMLReader");
+        } catch (SAXException e) {
+            // Expected
+        }
+        
+        // Good one, finally
+        try {
+            XMLReaderFactory.createXMLReader(
+                    "tests.api.org.xml.sax.support.DoNothingXMLReader");
+        } catch (SAXException e) {
+            throw new RuntimeException("Unexpected exception", e);
+        }
+
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/BrokenInputStream.java b/xml/src/test/java/tests/api/org/xml/sax/support/BrokenInputStream.java
new file mode 100644
index 0000000..daa36f9
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/support/BrokenInputStream.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.support;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Implements an InputStream what wraps another InputStream and throws an
+ * IOException after having read a specified number of bytes. Used for
+ * injecting IOExceptions on lower levels.
+ */
+public class BrokenInputStream extends InputStream {
+
+    private InputStream stream;
+    
+    private int offset;
+    
+    public BrokenInputStream(InputStream stream, int offset) {
+        super();
+        
+        this.stream = stream;
+        this.offset = offset;
+    }
+    
+    @Override
+    public int read() throws IOException {
+        if (offset == 0) {
+            throw new IOException("Injected exception");
+        }
+
+        offset--;
+        return stream.read();
+    }
+    
+}
\ No newline at end of file
diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/DoNothingParser.java b/xml/src/test/java/tests/api/org/xml/sax/support/DoNothingParser.java
new file mode 100644
index 0000000..6049cc6
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/support/DoNothingParser.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.support;
+
+import org.xml.sax.DTDHandler;
+import org.xml.sax.DocumentHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.Parser;
+
+import java.util.Locale;
+
+/**
+ * A SAX Parser that does nothing, but can be instantiated properly.
+ */
+@SuppressWarnings("deprecation")
+public class DoNothingParser implements Parser {
+
+    public void parse(InputSource source)  {
+    }
+
+    public void parse(String systemId) {
+    }
+
+    public void setDocumentHandler(DocumentHandler handler) {
+    }
+
+    public void setDTDHandler(DTDHandler handler) {
+    }
+
+    public void setEntityResolver(EntityResolver resolver) {
+    }
+
+    public void setErrorHandler(ErrorHandler handler) {
+    }
+
+    public void setLocale(Locale locale) {
+    }
+    
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/DoNothingXMLReader.java b/xml/src/test/java/tests/api/org/xml/sax/support/DoNothingXMLReader.java
new file mode 100644
index 0000000..8687bff
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/support/DoNothingXMLReader.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.support;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
+
+/**
+ * An XMLReader that does nothing, but can be instantiated properly.
+ */
+public class DoNothingXMLReader implements XMLReader {
+
+    public ContentHandler getContentHandler() {
+        return null;
+    }
+
+    public DTDHandler getDTDHandler() {
+        return null;
+    }
+
+    public EntityResolver getEntityResolver() {
+        return null;
+    }
+
+    public ErrorHandler getErrorHandler() {
+        return null;
+    }
+
+    public boolean getFeature(String name) {
+        return false;
+    }
+
+    public Object getProperty(String name) {
+        return null;
+    }
+
+    public void parse(InputSource input) {
+    }
+
+    public void parse(String systemId) {
+    }
+
+    public void setContentHandler(ContentHandler handler) {
+    }
+
+    public void setDTDHandler(DTDHandler handler) {
+    }
+
+    public void setEntityResolver(EntityResolver resolver) {
+    }
+
+    public void setErrorHandler(ErrorHandler handler) {
+    }
+
+    public void setFeature(String name, boolean value) {
+    }
+
+    public void setProperty(String name, Object value) {
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/MethodLogger.java b/xml/src/test/java/tests/api/org/xml/sax/support/MethodLogger.java
new file mode 100644
index 0000000..198172b
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/support/MethodLogger.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.support;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A simple helper class that logs method calls by storing method names and
+ * parameter lists. Used as a foundation for various simple SAX handlers.
+ */
+public class MethodLogger {
+
+    /**
+     * The names of the invoked methods, in order.
+     */
+    private List<String> methods = new ArrayList<String>();
+
+    /**
+     * The parameter lists of the invoked methods, in order.
+     */
+    private List<Object[]> argLists = new ArrayList<Object[]>();
+
+    /**
+     * Adds a method call with a variable list of arguments.
+     */
+    public void add(String method, Object ... args) {
+        Object[] argsCopy = new Object[args.length];
+        System.arraycopy(args, 0, argsCopy, 0, args.length);
+        
+        methods.add(method);
+        argLists.add(argsCopy);
+    }
+
+    /**
+     * Returns the number of method invoked so far.
+     */
+    public int size() {
+        return methods.size();
+    }
+
+    /**
+     * Returns the method name stored at the given index.
+     */
+    public String getMethod(int index) {
+        return methods.get(index);
+    }
+
+    /**
+     * Returns the name of the last method that was invoked. Returns null if no
+     * method calls have been logged so far.
+     */
+    public String getMethod() {
+        return (size() == 0 ? null : getMethod(size() - 1));
+    }
+
+    /**
+     * Returns the argument array stored at the given index. May be empty, but
+     * not null.
+     */
+    public Object[] getArgs(int index) {
+        return argLists.get(index);
+    }
+
+    /**
+     * Returns the argument array of the last method that was invoked. Returns
+     * null if no method has been invoked so far.
+     */
+    public Object[] getArgs() {
+        return (size() == 0 ? null : getArgs(size() - 1));
+    }
+
+    /**
+     * Clears the log.
+     */
+    public void clear() {
+        methods.clear();
+        argLists.clear();
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/MockFilter.java b/xml/src/test/java/tests/api/org/xml/sax/support/MockFilter.java
new file mode 100644
index 0000000..0b54bf8
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/support/MockFilter.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.support;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.helpers.XMLFilterImpl;
+
+/**
+ * A helper class that extends XMLFilterImpl, provides dummy feature/property
+ * management, and logs some method calls.
+ */
+public class MockFilter extends XMLFilterImpl {
+
+    private MethodLogger logger;
+    
+    private Set<String> features = new HashSet<String>();
+
+    private Map<String, Object> properties = new HashMap<String, Object>();
+    
+    public MockFilter(MethodLogger logger) {
+        super();
+        this.logger = logger;
+    }
+    
+    @Override
+    public boolean getFeature(String name) throws SAXNotRecognizedException,
+            SAXNotSupportedException {
+        return features.contains(name);
+    }
+
+    @Override
+    public Object getProperty(String name) throws SAXNotRecognizedException,
+            SAXNotSupportedException {
+        return properties.get(name);
+    }
+
+    @Override
+    public void setFeature(String name, boolean value) {
+        if (value) {
+            features.add(name);
+        } else {
+            features.remove(name);
+        }
+    }
+
+    @Override
+    public void setProperty(String name, Object value) throws SAXNotRecognizedException,
+            SAXNotSupportedException {
+        if (value == null) {
+            properties.remove(name);
+        } else {
+            properties.put(name, value);
+        }
+    }
+
+    @Override
+    public void parse(InputSource input) throws SAXException, IOException {
+        logger.add("parse", input);
+    }
+
+    @Override
+    public void parse(String systemId) throws SAXException, IOException {
+        logger.add("parse", systemId);
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/MockHandler.java b/xml/src/test/java/tests/api/org/xml/sax/support/MockHandler.java
new file mode 100644
index 0000000..98b024a
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/support/MockHandler.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.support;
+
+import org.xml.sax.AttributeList;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.DocumentHandler;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.ext.LexicalHandler;
+
+/**
+ * A helper class that implements the various SAX callback interfaces and logs
+ * method calls.
+ */
+@SuppressWarnings("deprecation")
+public class MockHandler implements ContentHandler, DTDHandler, DocumentHandler,
+        ErrorHandler, LexicalHandler {
+
+    private MethodLogger logger;
+    
+    public MockHandler(MethodLogger logger) {
+        super();
+        this.logger = logger;
+    }
+    
+    public void characters(char[] ch, int start, int length) throws SAXException {
+        logger.add("characters", ch, start, length);
+    }
+
+    public void endDocument() throws SAXException {
+        logger.add("endDocument");
+    }
+
+    public void endElement(String name) throws SAXException {
+        logger.add("endElement", name);
+    }
+
+    public void endElement(String uri, String localName, String name) throws SAXException {
+        logger.add("endElement", uri, localName, name);
+    }
+
+    public void endPrefixMapping(String prefix) throws SAXException {
+        logger.add("endPrefixMapping", prefix);
+    }
+
+    public void error(SAXParseException exception) throws SAXException {
+        logger.add("error", exception);
+    }
+
+    public void fatalError(SAXParseException exception) throws SAXException {
+        logger.add("fatalError", exception);
+    }
+
+    public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
+        logger.add("ignorableWhitespace", ch, start, length);
+    }
+
+    public void notationDecl(String name, String publicId, String systemId) throws SAXException {
+        logger.add("notationDecl", name, publicId, systemId);
+    }
+
+    public void processingInstruction(String target, String data) throws SAXException {
+        logger.add("processingInstruction", target, data);
+    }
+
+    public void setDocumentLocator(Locator locator) {
+        logger.add("setDocumentLocator", locator);
+    }
+
+    public void skippedEntity(String name) throws SAXException {
+        logger.add("skippedEntity", name);
+    }
+
+    public void startDocument() throws SAXException {
+        logger.add("startDocument");
+    }
+
+    public void startElement(String name, AttributeList atts) throws SAXException {
+        logger.add("startElement", name, atts);
+    }
+
+    public void startElement(String uri, String localName, String name, Attributes atts)
+            throws SAXException {
+        logger.add("startElement", uri, localName, name, atts);
+    }
+
+    public void startPrefixMapping(String prefix, String uri) throws SAXException {
+        logger.add("startPrefixMapping", prefix, uri);
+    }
+
+    public void unparsedEntityDecl(String name, String publicId, String systemId,
+            String notationName) throws SAXException {
+        logger.add("unparsedEntityDecl", name, publicId, systemId, notationName);
+    }
+
+    public void warning(SAXParseException exception) throws SAXException {
+        logger.add("warning", exception);
+    }
+
+    public void comment(char[] ch, int start, int length) throws SAXException {
+        logger.add("comment", ch, start, length);
+    }
+
+    public void endCDATA() throws SAXException {
+        logger.add("endCDATA");
+    }
+
+    public void endDTD() throws SAXException {
+        logger.add("endDTD");
+    }
+
+    public void endEntity(String name) throws SAXException {
+        logger.add("endEntity", name);
+    }
+
+    public void startCDATA() throws SAXException {
+        logger.add("startCDATA");
+    }
+
+    public void startDTD(String name, String publicId, String systemId) throws SAXException {
+        logger.add("startDTD", name, publicId, systemId);
+    }
+
+    public void startEntity(String name) throws SAXException {
+        logger.add("startEntity", name);
+    }
+    
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/MockParser.java b/xml/src/test/java/tests/api/org/xml/sax/support/MockParser.java
new file mode 100644
index 0000000..01520f8
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/support/MockParser.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.support;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import org.xml.sax.DTDHandler;
+import org.xml.sax.DocumentHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.Parser;
+import org.xml.sax.SAXException;
+
+@SuppressWarnings("deprecation")
+public class MockParser implements Parser {
+    
+    private MethodLogger logger;
+    
+    public MockParser(MethodLogger logger) {
+        super();
+        this.logger = logger;
+    }
+
+    public void parse(InputSource source) throws SAXException, IOException {
+        logger.add("parse", source);
+    }
+
+    public void parse(String systemId) throws SAXException, IOException {
+        logger.add("parse", systemId);
+    }
+
+    public void setDTDHandler(DTDHandler handler) {
+        logger.add("setDTDHandler", handler);
+    }
+
+    public void setDocumentHandler(DocumentHandler handler) {
+        logger.add("setDocumentHandler", handler);
+    }
+
+    public void setEntityResolver(EntityResolver resolver) {
+        logger.add("setEntityResolver", resolver);
+    }
+
+    public void setErrorHandler(ErrorHandler handler) {
+        logger.add("setErrorHandler", handler);
+    }
+
+    public void setLocale(Locale locale) throws SAXException {
+        logger.add("setLocale", locale);
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/MockReader.java b/xml/src/test/java/tests/api/org/xml/sax/support/MockReader.java
new file mode 100644
index 0000000..22a6a57
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/support/MockReader.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.support;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.XMLReader;
+
+/**
+ * A helper class that implements the SAX XMLReader interface and logs method
+ * calls.
+ */
+public class MockReader implements XMLReader {
+
+    private MethodLogger logger;
+    
+    private ContentHandler contentHandler;
+    
+    private DTDHandler dtdHandler;
+
+    private EntityResolver resolver;
+    
+    private ErrorHandler errorHandler;
+    
+    private Set<String> features = new HashSet<String>();
+
+    private Map<String, Object> properties = new HashMap<String, Object>();
+    
+    public MockReader(MethodLogger logger) {
+        super();
+        this.logger = logger;
+    }
+
+    
+    public ContentHandler getContentHandler() {
+        return contentHandler;
+    }
+
+    public DTDHandler getDTDHandler() {
+        return dtdHandler;
+    }
+
+    public EntityResolver getEntityResolver() {
+        return resolver;
+    }
+
+    public ErrorHandler getErrorHandler() {
+        return errorHandler;
+    }
+
+    public boolean getFeature(String name) throws SAXNotRecognizedException,
+            SAXNotSupportedException {
+        return features.contains(name);
+    }
+
+    public Object getProperty(String name) throws SAXNotRecognizedException,
+            SAXNotSupportedException {
+        return properties.get(name);
+    }
+
+    public void parse(InputSource input) throws IOException, SAXException {
+        logger.add("parse", input);
+    }
+
+    public void parse(String systemId) throws IOException, SAXException {
+        logger.add("parse", systemId);
+    }
+
+    public void setContentHandler(ContentHandler handler) {
+        this.contentHandler = handler;
+    }
+
+    public void setDTDHandler(DTDHandler handler) {
+        this.dtdHandler = handler;
+    }
+
+    public void setEntityResolver(EntityResolver resolver) {
+        this.resolver = resolver;
+    }
+
+    public void setErrorHandler(ErrorHandler handler) {
+        this.errorHandler = handler;
+    }
+
+    public void setFeature(String name, boolean value) {
+        if (value) {
+            features.add(name);
+        } else {
+            features.remove(name);
+        }
+    }
+
+    public void setProperty(String name, Object value) throws SAXNotRecognizedException,
+            SAXNotSupportedException {
+        if (value == null) {
+            properties.remove(name);
+        } else {
+            properties.put(name, value);
+        }
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/MockResolver.java b/xml/src/test/java/tests/api/org/xml/sax/support/MockResolver.java
new file mode 100644
index 0000000..ae0066e
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/support/MockResolver.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.support;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * A helper class for resolving entities.
+ */
+public class MockResolver implements EntityResolver {
+
+    private Map<String, InputSource> entities = new HashMap<String, InputSource>();
+    
+    public void addEntity(String publicId, String systemId, InputSource source) {
+        entities.put("[" + publicId + ":" + systemId + "]", source);
+    }
+
+    public void removeEntity(String publicId, String systemId) {
+        entities.remove("[" + publicId + ":" + systemId + "]");
+    }            
+    
+    public InputSource resolveEntity(String publicId, String systemId)
+            throws SAXException, IOException {
+        return entities.get("[" + publicId + ":" + systemId + "]");            
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/NoAccessParser.java b/xml/src/test/java/tests/api/org/xml/sax/support/NoAccessParser.java
new file mode 100644
index 0000000..5aac9af
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/support/NoAccessParser.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.support;
+
+import org.xml.sax.DTDHandler;
+import org.xml.sax.DocumentHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.Parser;
+
+import java.util.Locale;
+
+/**
+ * A SAX Parser that can't be accessed.
+ */
+@SuppressWarnings("deprecation")
+class NoAccessParser implements Parser {
+
+    public void parse(InputSource source)  {
+    }
+
+    public void parse(String systemId) {
+    }
+
+    public void setDocumentHandler(DocumentHandler handler) {
+    }
+
+    public void setDTDHandler(DTDHandler handler) {
+    }
+
+    public void setEntityResolver(EntityResolver resolver) {
+    }
+
+    public void setErrorHandler(ErrorHandler handler) {
+    }
+
+    public void setLocale(Locale locale) {
+    }
+    
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/NoAccessXMLReader.java b/xml/src/test/java/tests/api/org/xml/sax/support/NoAccessXMLReader.java
new file mode 100644
index 0000000..b6a0a68
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/support/NoAccessXMLReader.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.support;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
+
+/**
+ * An XMLReader that is not accessible.
+ */
+class NoAccessXMLReader implements XMLReader {
+
+    public ContentHandler getContentHandler() {
+        return null;
+    }
+
+    public DTDHandler getDTDHandler() {
+        return null;
+    }
+
+    public EntityResolver getEntityResolver() {
+        return null;
+    }
+
+    public ErrorHandler getErrorHandler() {
+        return null;
+    }
+
+    public boolean getFeature(String name) {
+        return false;
+    }
+
+    public Object getProperty(String name) {
+        return null;
+    }
+
+    public void parse(InputSource input) {
+    }
+
+    public void parse(String systemId) {
+    }
+
+    public void setContentHandler(ContentHandler handler) {
+    }
+
+    public void setDTDHandler(DTDHandler handler) {
+    }
+
+    public void setEntityResolver(EntityResolver resolver) {
+    }
+
+    public void setErrorHandler(ErrorHandler handler) {
+    }
+
+    public void setFeature(String name, boolean value) {
+    }
+
+    public void setProperty(String name, Object value) {
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/NoInstanceParser.java b/xml/src/test/java/tests/api/org/xml/sax/support/NoInstanceParser.java
new file mode 100644
index 0000000..8f1692f
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/support/NoInstanceParser.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.support;
+
+import org.xml.sax.DTDHandler;
+import org.xml.sax.DocumentHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.Parser;
+
+import java.util.Locale;
+
+/**
+ * A SAX Parser that can be accessed, but not instantiated.
+ */
+@SuppressWarnings("deprecation")
+public class NoInstanceParser implements Parser {
+
+    public NoInstanceParser(int i) {
+    }
+    
+    public void parse(InputSource source)  {
+    }
+
+    public void parse(String systemId) {
+    }
+
+    public void setDocumentHandler(DocumentHandler handler) {
+    }
+
+    public void setDTDHandler(DTDHandler handler) {
+    }
+
+    public void setEntityResolver(EntityResolver resolver) {
+    }
+
+    public void setErrorHandler(ErrorHandler handler) {
+    }
+
+    public void setLocale(Locale locale) {
+    }
+    
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/NoInstanceXMLReader.java b/xml/src/test/java/tests/api/org/xml/sax/support/NoInstanceXMLReader.java
new file mode 100644
index 0000000..764c451
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/support/NoInstanceXMLReader.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.support;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
+
+/**
+ * An XMLReader that is accessible, but can't be instantiated.
+ */
+public class NoInstanceXMLReader implements XMLReader {
+
+    public NoInstanceXMLReader(int i) {
+    }
+    
+    public ContentHandler getContentHandler() {
+        return null;
+    }
+
+    public DTDHandler getDTDHandler() {
+        return null;
+    }
+
+    public EntityResolver getEntityResolver() {
+        return null;
+    }
+
+    public ErrorHandler getErrorHandler() {
+        return null;
+    }
+
+    public boolean getFeature(String name) {
+        return false;
+    }
+
+    public Object getProperty(String name) {
+        return null;
+    }
+
+    public void parse(InputSource input) {
+    }
+
+    public void parse(String systemId) {
+    }
+
+    public void setContentHandler(ContentHandler handler) {
+    }
+
+    public void setDTDHandler(DTDHandler handler) {
+    }
+
+    public void setEntityResolver(EntityResolver resolver) {
+    }
+
+    public void setErrorHandler(ErrorHandler handler) {
+    }
+
+    public void setFeature(String name, boolean value) {
+    }
+
+    public void setProperty(String name, Object value) {
+    }
+
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/NoSubclassParser.java b/xml/src/test/java/tests/api/org/xml/sax/support/NoSubclassParser.java
new file mode 100644
index 0000000..f178998
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/support/NoSubclassParser.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.support;
+
+import org.xml.sax.DTDHandler;
+import org.xml.sax.DocumentHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+
+import java.util.Locale;
+
+/**
+ * A SAX Parser that does not implement the Parser interface.
+ */
+@SuppressWarnings("deprecation")
+public class NoSubclassParser {
+
+    public void parse(InputSource source)  {
+    }
+
+    public void parse(String systemId) {
+    }
+
+    public void setDocumentHandler(DocumentHandler handler) {
+    }
+
+    public void setDTDHandler(DTDHandler handler) {
+    }
+
+    public void setEntityResolver(EntityResolver resolver) {
+    }
+
+    public void setErrorHandler(ErrorHandler handler) {
+    }
+
+    public void setLocale(Locale locale) {
+    }
+    
+}
diff --git a/xml/src/test/java/tests/api/org/xml/sax/support/NoSubclassXMLReader.java b/xml/src/test/java/tests/api/org/xml/sax/support/NoSubclassXMLReader.java
new file mode 100644
index 0000000..acdbd88
--- /dev/null
+++ b/xml/src/test/java/tests/api/org/xml/sax/support/NoSubclassXMLReader.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.api.org.xml.sax.support;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
+
+/**
+ * An XMLReader that does not implement the XMLReader interface.
+ */
+public class NoSubclassXMLReader implements XMLReader {
+
+    public ContentHandler getContentHandler() {
+        return null;
+    }
+
+    public DTDHandler getDTDHandler() {
+        return null;
+    }
+
+    public EntityResolver getEntityResolver() {
+        return null;
+    }
+
+    public ErrorHandler getErrorHandler() {
+        return null;
+    }
+
+    public boolean getFeature(String name) {
+        return false;
+    }
+
+    public Object getProperty(String name) {
+        return null;
+    }
+
+    public void parse(InputSource input) {
+    }
+
+    public void parse(String systemId) {
+    }
+
+    public void setContentHandler(ContentHandler handler) {
+    }
+
+    public void setDTDHandler(DTDHandler handler) {
+    }
+
+    public void setEntityResolver(EntityResolver resolver) {
+    }
+
+    public void setErrorHandler(ErrorHandler handler) {
+    }
+
+    public void setFeature(String name, boolean value) {
+    }
+
+    public void setProperty(String name, Object value) {
+    }
+
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/AllTests.java b/xml/src/test/java/tests/org/w3c/dom/AllTests.java
new file mode 100644
index 0000000..a4299a7
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/AllTests.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.org.w3c.dom;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * This is autogenerated source file. Includes tests for package org.w3c.dom;
+ */
+
+public class AllTests {
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(AllTests.suite());
+    }
+
+    public static Test suite() {
+        TestSuite suite = tests.TestSuiteFactory.createTestSuite("All tests for package org.w3c.dom;");
+        // $JUnit-BEGIN$
+
+        suite.addTestSuite(AttrGetOwnerElement.class);
+        suite.addTestSuite(CreateAttributeNS.class);
+        suite.addTestSuite(CreateDocument.class);
+        suite.addTestSuite(CreateDocumentType.class);
+        suite.addTestSuite(CreateElementNS.class);
+        suite.addTestSuite(DOMImplementationCreateDocument.class);
+        suite.addTestSuite(DOMImplementationCreateDocumentType.class);
+        suite.addTestSuite(DOMImplementationHasFeature.class);
+        suite.addTestSuite(DocumentCreateAttributeNS.class);
+        suite.addTestSuite(DocumentCreateElementNS.class);
+        suite.addTestSuite(DocumentGetElementsByTagnameNS.class);
+        suite.addTestSuite(DocumentGeteEementById.class);
+        suite.addTestSuite(DocumentImportNode.class);
+        suite.addTestSuite(DocumentTypeInternalSubset.class);
+        suite.addTestSuite(DocumentTypePublicId.class);
+        suite.addTestSuite(DocumentTypeSystemId.class);
+// Is empty. Only test assumes validation. Leave disabled.        
+//        suite.addTestSuite(ElementGetAttributeNS.class);
+        suite.addTestSuite(ElementGetAttributeNodeNS.class);
+        suite.addTestSuite(ElementGetElementsByTagNameNS.class);
+        suite.addTestSuite(ElementHasAttribute.class);
+        suite.addTestSuite(ElementHasAttributeNS.class);
+        suite.addTestSuite(ElementRemoveAttributeNS.class);
+        suite.addTestSuite(ElementSetAttributeNS.class);
+        suite.addTestSuite(ElementSetAttributeNodeNS.class);
+        suite.addTestSuite(GetAttributeNS.class);
+        suite.addTestSuite(GetAttributeNodeNS.class);
+        suite.addTestSuite(GetElementById.class);
+        suite.addTestSuite(GetElementsByTagNameNS.class);
+        suite.addTestSuite(GetNamedItemNS.class);
+// Is empty. Only test assumes validation. Leave disabled.        
+//        suite.addTestSuite(HCEntitiesRemoveNamedItemNS.class);
+// Is empty. Only test assumes validation. Leave disabled.        
+//        suite.addTestSuite(HCEntitiesSetNamedItemNS.class);
+        suite.addTestSuite(HCNamedNodeMapInvalidType.class);
+        suite.addTestSuite(HCNodeDocumentFragmentNormalize.class);
+// Is empty. Only test assumes validation. Leave disabled.        
+//        suite.addTestSuite(HCNotationsRemoveNamedItemNS.class);
+// Is empty. Only test assumes validation. Leave disabled.        
+//        suite.addTestSuite(HCNotationsSetNamedItemNS.class);
+        suite.addTestSuite(HasAttribute.class);
+        suite.addTestSuite(HasAttributeNS.class);
+        suite.addTestSuite(HasAttributes.class);
+        suite.addTestSuite(ImportNode.class);
+        suite.addTestSuite(InternalSubset.class);
+        suite.addTestSuite(IsSupported.class);
+        suite.addTestSuite(LocalName.class);
+        suite.addTestSuite(NamedNodeMapGetNamedItemNS.class);
+        suite.addTestSuite(NamedNodeMapRemoveNamedItemNS.class);
+        suite.addTestSuite(NamedNodeMapSetNamedItemNS.class);
+        suite.addTestSuite(NamespaceURI.class);
+        suite.addTestSuite(NodeGetLocalName.class);
+        suite.addTestSuite(NodeGetNamespaceURI.class);
+        suite.addTestSuite(NodeGetOwnerDocument.class);
+        suite.addTestSuite(NodeGetPrefix.class);
+        suite.addTestSuite(NodeHasAttributes.class);
+        suite.addTestSuite(NodeIsSupported.class);
+        suite.addTestSuite(NodeNormalize.class);
+        suite.addTestSuite(NodeSetPrefix.class);
+        suite.addTestSuite(Normalize.class);
+        suite.addTestSuite(OwnerDocument.class);
+        suite.addTestSuite(OwnerElement.class);
+        suite.addTestSuite(Prefix.class);
+        suite.addTestSuite(PublicId.class);
+// Is empty. Only test assumes validation. Leave disabled.        
+//        suite.addTestSuite(RemoveAttributeNS.class);
+        suite.addTestSuite(RemoveNamedItemNS.class);
+        suite.addTestSuite(SetAttributeNS.class);
+        suite.addTestSuite(SetAttributeNodeNS.class);
+        suite.addTestSuite(SetNamedItemNS.class);
+        suite.addTestSuite(SystemId.class);
+        // $JUnit-END$
+        return suite;
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/AttrGetOwnerElement.java b/xml/src/test/java/tests/org/w3c/dom/AttrGetOwnerElement.java
new file mode 100644
index 0000000..bb42121
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/AttrGetOwnerElement.java
@@ -0,0 +1,156 @@
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.NamedNodeMap;
+
+import javax.xml.parsers.DocumentBuilder;
+
+@TestTargetClass(Attr.class) 
+public final class AttrGetOwnerElement extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception " + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+// Assumes validation.    
+//    public void testGetOwnerElement1() throws Throwable {
+//        Document doc;
+//        Attr attr;
+//        Element element;
+//        Element ownerElement;
+//        String ownerElementName;
+//        NodeList elementList;
+//        NamedNodeMap attributes;
+//        String nullNS = null;
+//
+//        doc = (Document) load("staffNS", builder);
+//
+//        elementList = doc.getElementsByTagNameNS("http://www.nist.gov",
+//                "employee");
+//        element = (Element) elementList.item(1);
+//        attributes = element.getAttributes();
+//        attr = (Attr) attributes.getNamedItemNS(nullNS, "defaultAttr");
+//        ownerElement = attr.getOwnerElement();
+//        ownerElementName = ownerElement.getNodeName();
+//        assertEquals("attrgetownerelement01", "emp:employee", ownerElementName);
+//
+//    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify that getOwnerElement returns null if an attribute is not in use.",
+        method = "getOwnerElement",
+        args = {}
+    )
+    public void testGetOwnerElement2() throws Throwable {
+        Document doc;
+        Element element;
+        Element ownerElement;
+        String ownerElementName;
+        Attr attr;
+
+        doc = (Document) load("staffNS", builder);
+        element = doc.createElement("root");
+        attr = doc.createAttributeNS("http://www.w3.org/DOM/L1", "L1:att");
+        element.setAttributeNodeNS(attr);
+        ownerElement = attr.getOwnerElement();
+        ownerElementName = ownerElement.getNodeName();
+        assertEquals("attrgetownerelement02", "root", ownerElementName);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that getOwnerElement returns null if an attribute is not in use.",
+        method = "getOwnerElement",
+        args = {}
+    )
+    public void testGetOwnerElement3() throws Throwable {
+        Document doc;
+        Node ownerElement;
+        Attr attr;
+        doc = (Document) load("staffNS", builder);
+        attr = doc.createAttributeNS("http://www.w3.org/DOM", "dom:attr");
+        ownerElement = attr.getOwnerElement();
+        assertNull("attrgetownerelement03", ownerElement);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that getOwnerElement returns null if an attribute is not in use.",
+        method = "getOwnerElement",
+        args = {}
+    )
+    public void testGetOwnerElement4() throws Throwable {
+        Document doc;
+        Document docImp;
+        Node ownerElement;
+        Element element;
+        Attr attr;
+        Attr attrImp;
+        NodeList addresses;
+
+        doc = (Document) load("staffNS", builder);
+        docImp = (Document) load("staff", builder);
+
+        addresses = doc
+                .getElementsByTagNameNS("http://www.nist.gov", "address");
+        element = (Element) addresses.item(1);
+        assertNotNull("empAddressNotNull", element);
+        attr = element.getAttributeNodeNS("http://www.nist.gov", "zone");
+        attrImp = (Attr) docImp.importNode(attr, true);
+        ownerElement = attrImp.getOwnerElement();
+        assertNull("attrgetownerelement04", ownerElement);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify that getOwnerElement returns null if an attribute is not in use.",
+        method = "getOwnerElement",
+        args = {}
+    )
+    public void testGetOwnerElement5() throws Throwable {
+        Document doc;
+        Node element;
+        Element ownerElement;
+        Element parentElement;
+        NodeList elementList;
+        String ownerElementName;
+        Attr attr;
+
+        NamedNodeMap nodeMap;
+        String nullNS = null;
+
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagNameNS("*", "address");
+        element = elementList.item(1);
+        parentElement = (Element) element.getParentNode();
+        nodeMap = element.getAttributes();
+        parentElement.removeChild(element);
+        attr = (Attr) nodeMap.getNamedItemNS(nullNS, "street");
+        ownerElement = attr.getOwnerElement();
+        ownerElementName = ownerElement.getNodeName();
+        assertEquals("attrgetownerelement05", "address", ownerElementName);
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/CreateAttributeNS.java b/xml/src/test/java/tests/org/w3c/dom/CreateAttributeNS.java
new file mode 100644
index 0000000..c7e0d34
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/CreateAttributeNS.java
@@ -0,0 +1,229 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Attr;
+
+import javax.xml.parsers.DocumentBuilder;
+
+@TestTargetClass(Document.class) 
+public final class CreateAttributeNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies NAMESPACE_ERR exception code.",
+        method = "createAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateAttributeNS1() throws Throwable {
+        String namespaceURI = "http://www.ecommerce.org/";
+        String malformedName = "prefix::local";
+        Document doc;
+
+        doc = (Document) load("staffNS", builder);
+
+        {
+            boolean success = false;
+            try {
+                doc.createAttributeNS(namespaceURI, malformedName);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("throw_NAMESPACE_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies createAttributeNS method with null as the fisrt parameter.",
+        method = "createAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateAttributeNS2() throws Throwable {
+        String namespaceURI = null;
+
+        String qualifiedName = "prefix:local";
+        Document doc;
+
+        doc = (Document) load("staffNS", builder);
+
+        {
+            boolean success = false;
+            try {
+                doc.createAttributeNS(namespaceURI, qualifiedName);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("throw_NAMESPACE_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that createAttributeNS throws DOMException.",
+        method = "createAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateAttributeNS3() throws Throwable {
+        String namespaceURI = "http://www.wedding.com/";
+        String qualifiedName;
+        Document doc;
+
+        List<String> illegalQNames = new ArrayList<String>();
+        illegalQNames.add("person:{");
+        illegalQNames.add("person:}");
+        illegalQNames.add("person:~");
+        illegalQNames.add("person:'");
+        illegalQNames.add("person:!");
+        illegalQNames.add("person:@");
+        illegalQNames.add("person:#");
+        illegalQNames.add("person:$");
+        illegalQNames.add("person:%");
+        illegalQNames.add("person:^");
+        illegalQNames.add("person:&");
+        illegalQNames.add("person:*");
+        illegalQNames.add("person:(");
+        illegalQNames.add("person:)");
+        illegalQNames.add("person:+");
+        illegalQNames.add("person:=");
+        illegalQNames.add("person:[");
+        illegalQNames.add("person:]");
+        illegalQNames.add("person:\\");
+        illegalQNames.add("person:/");
+        illegalQNames.add("person:;");
+        illegalQNames.add("person:`");
+        illegalQNames.add("person:<");
+        illegalQNames.add("person:>");
+        illegalQNames.add("person:,");
+        illegalQNames.add("person:a ");
+        illegalQNames.add("person:\"");
+
+        doc = (Document) load("staffNS", builder);
+        for (int indexN10090 = 0; indexN10090 < illegalQNames.size(); indexN10090++) {
+            qualifiedName = (String) illegalQNames.get(indexN10090);
+            {
+                boolean success = false;
+                try {
+                    doc.createAttributeNS(namespaceURI, qualifiedName);
+                } catch (DOMException ex) {
+                    success = (ex.code == DOMException.INVALID_CHARACTER_ERR);
+                }
+                assertTrue("throw_INVALID_CHARACTER_ERR", success);
+            }
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify exceptions.",
+        method = "createAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateAttributeNS4() throws Throwable {
+        String namespaceURI = "http://www.w3.org/XML/1998/namespaces";
+        String qualifiedName = "xml:attr1";
+        Document doc;
+
+        doc = (Document) load("staffNS", builder);
+
+        {
+            boolean success = false;
+            try {
+                doc.createAttributeNS(namespaceURI, qualifiedName);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("throw_NAMESPACE_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify exceptions.",
+        method = "createAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateAttributeNS5() throws Throwable {
+        String namespaceURI = "http://www.ecommerce.org/";
+        String qualifiedName = "econm:local";
+        Document doc;
+        Attr newAttr;
+        String attrName;
+        doc = (Document) load("staffNS", builder);
+        newAttr = doc.createAttributeNS(namespaceURI, qualifiedName);
+        attrName = newAttr.getName();
+        assertEquals("throw_Equals", qualifiedName, attrName);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "",
+        method = "createAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateAttributeNS6() throws Throwable {
+        String namespaceURI = "http://www.example.com/";
+        Document doc;
+
+        doc = (Document) load("hc_staff", builder);
+
+        boolean success = false;
+        try {
+            doc.createAttributeNS(namespaceURI, "");
+        } catch (DOMException ex) {
+            success = (ex.code == DOMException.NAMESPACE_ERR);
+        }
+        assertTrue("throw_INVALID_CHARACTER_ERR", success);
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/CreateDocument.java b/xml/src/test/java/tests/org/w3c/dom/CreateDocument.java
new file mode 100644
index 0000000..157b394
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/CreateDocument.java
@@ -0,0 +1,317 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.DOMException;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The "createDocument(namespaceURI,qualifiedName,doctype)" method for a
+ * DOMImplementation should raise NAMESPACE_ERR DOMException if parameter
+ * qualifiedName is malformed.
+ * 
+ * Retrieve the DOMImplementation on the XMLNS Document. Invoke method
+ * createDocument(namespaceURI,qualifiedName,doctype) on the retrieved
+ * DOMImplementation with namespaceURI being the literal string
+ * "http://www.ecommerce.org/", qualifiedName as "prefix::local", and doctype as
+ * null. Method should raise NAMESPACE_ERR DOMException.
+ * 
+ * @author NIST
+ * @author Mary Brady
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='NAMESPACE_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='NAMESPACE_ERR'])</a>
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#Level-2-Core-DOM-createDocument">http://www.w3.org/TR/DOM-Level-2-Core/core#Level-2-Core-DOM-createDocument</a>
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('Level-2-Core-DOM-createDocument')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='NAMESPACE_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('Level-2-Core-DOM-createDocument')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='NAMESPACE_ERR'])</a>
+ */
+@TestTargetClass(DOMImplementation.class) 
+public final class CreateDocument extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify null as parameters.",
+        method = "createDocument",
+        args = {java.lang.String.class, java.lang.String.class, org.w3c.dom.DocumentType.class}
+    )
+    public void testCreateDocument1() throws Throwable {
+        String namespaceURI = "http://www.ecommerce.org/";
+        String malformedName = "prefix::local";
+        Document doc;
+        DocumentType docType = null;
+
+        DOMImplementation domImpl;
+
+        doc = (Document) load("staffNS", builder);
+        domImpl = doc.getImplementation();
+
+        boolean success = false;
+        try {
+            domImpl.createDocument(namespaceURI, malformedName, docType);
+        } catch (DOMException ex) {
+            success = (ex.code == DOMException.NAMESPACE_ERR);
+        }
+        assertTrue("throw_NAMESPACE_ERR", success);
+
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify null as parameters.",
+        method = "createDocument",
+        args = {java.lang.String.class, java.lang.String.class, org.w3c.dom.DocumentType.class}
+    )
+    public void testCreateDocument2() throws Throwable {
+        String namespaceURI = null;
+
+        String qualifiedName = "k:local";
+        Document doc;
+        DocumentType docType = null;
+
+        DOMImplementation domImpl;
+
+        doc = (Document) load("staffNS", builder);
+        domImpl = doc.getImplementation();
+
+        boolean success = false;
+        try {
+            domImpl.createDocument(namespaceURI, qualifiedName, docType);
+        } catch (DOMException ex) {
+            success = (ex.code == DOMException.NAMESPACE_ERR);
+        }
+        assertTrue("throw_NAMESPACE_ERR", success);
+
+    }
+
+//    public void testCreateDocument3() throws Throwable {
+//        String namespaceURI = "http://www.ecommerce.org/schema";
+//        String qualifiedName = "namespaceURI:x";
+//        Document doc;
+//        DocumentType docType;
+//        DOMImplementation domImpl;
+//
+//        doc = (Document) load("staffNS", builder);
+//        docType = doc.getDoctype();
+//        domImpl = doc.getImplementation();
+//
+//        boolean success = false;
+//        try {
+//            domImpl.createDocument(namespaceURI, qualifiedName, docType);
+//        } catch (DOMException ex) {
+//            success = (ex.code == DOMException.WRONG_DOCUMENT_ERR);
+//        }
+//        assertTrue("throw_WRONG_DOCUMENT_ERR", success);
+//
+//    }
+
+//    public void testCreateDocument4() throws Throwable {
+//        String namespaceURI = "http://www.ecommerce.org/schema";
+//        String qualifiedName = "namespaceURI:x";
+//        Document doc;
+//        DocumentType docType;
+//        DOMImplementation domImpl;
+//        Document aNewDoc;
+//        doc = (Document) load("staffNS", builder);
+//        aNewDoc = (Document) load("staffNS", builder);
+//        docType = doc.getDoctype();
+//        domImpl = aNewDoc.getImplementation();
+//
+//        boolean success = false;
+//        try {
+//            aNewDoc = domImpl.createDocument(namespaceURI, qualifiedName,
+//                    docType);
+//        } catch (DOMException ex) {
+//            success = (ex.code == DOMException.WRONG_DOCUMENT_ERR);
+//        }
+//        assertTrue("throw_WRONG_DOCUMENT_ERR", success);
+//
+//    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify null as parameters.",
+        method = "createDocument",
+        args = {java.lang.String.class, java.lang.String.class, org.w3c.dom.DocumentType.class}
+    )
+    public void testCreateDocument5() throws Throwable {
+        String namespaceURI = "http://www.ecommerce.org/schema";
+        String qualifiedName;
+        Document doc;
+        DocumentType docType = null;
+
+        DOMImplementation domImpl;
+
+        List<String> illegalQNames = new ArrayList<String>();
+        illegalQNames.add("namespaceURI:{");
+        illegalQNames.add("namespaceURI:}");
+        illegalQNames.add("namespaceURI:~");
+        illegalQNames.add("namespaceURI:'");
+        illegalQNames.add("namespaceURI:!");
+        illegalQNames.add("namespaceURI:@");
+        illegalQNames.add("namespaceURI:#");
+        illegalQNames.add("namespaceURI:$");
+        illegalQNames.add("namespaceURI:%");
+        illegalQNames.add("namespaceURI:^");
+        illegalQNames.add("namespaceURI:&");
+        illegalQNames.add("namespaceURI:*");
+        illegalQNames.add("namespaceURI:(");
+        illegalQNames.add("namespaceURI:)");
+        illegalQNames.add("namespaceURI:+");
+        illegalQNames.add("namespaceURI:=");
+        illegalQNames.add("namespaceURI:[");
+        illegalQNames.add("namespaceURI:]");
+        illegalQNames.add("namespaceURI:\\");
+        illegalQNames.add("namespaceURI:/");
+        illegalQNames.add("namespaceURI:;");
+        illegalQNames.add("namespaceURI:`");
+        illegalQNames.add("namespaceURI:<");
+        illegalQNames.add("namespaceURI:>");
+        illegalQNames.add("namespaceURI:,");
+        illegalQNames.add("namespaceURI:a ");
+        illegalQNames.add("namespaceURI:\"");
+
+        doc = (Document) load("staffNS", builder);
+        for (int indexN1009A = 0; indexN1009A < illegalQNames.size(); indexN1009A++) {
+            qualifiedName = (String) illegalQNames.get(indexN1009A);
+            domImpl = doc.getImplementation();
+
+            boolean success = false;
+            try {
+                domImpl.createDocument(namespaceURI, qualifiedName, docType);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.INVALID_CHARACTER_ERR);
+            }
+            assertTrue("throw_INVALID_CHARACTER_ERR", success);
+
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify null as parameters.",
+        method = "createDocument",
+        args = {java.lang.String.class, java.lang.String.class, org.w3c.dom.DocumentType.class}
+    )
+    public void testCreateDocument6() throws Throwable {
+        String namespaceURI = "http://ecommerce.org/schema";
+        String qualifiedName = "xml:local";
+        Document doc;
+        DocumentType docType = null;
+
+        DOMImplementation domImpl;
+
+        doc = (Document) load("staffNS", builder);
+        domImpl = doc.getImplementation();
+
+        boolean success = false;
+        try {
+            domImpl.createDocument(namespaceURI, qualifiedName, docType);
+        } catch (DOMException ex) {
+            success = (ex.code == DOMException.NAMESPACE_ERR);
+        }
+        assertTrue("throw_NAMESPACE_ERR", success);
+
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify null as parameters.",
+        method = "createDocument",
+        args = {java.lang.String.class, java.lang.String.class, org.w3c.dom.DocumentType.class}
+    )
+    public void testCreateDocument7() throws Throwable {
+        String namespaceURI = "http://www.ecommerce.org/schema";
+        String qualifiedName = "y:x";
+        Document doc;
+        DocumentType docType = null;
+
+        DOMImplementation domImpl;
+        Document aNewDoc;
+        String nodeName;
+        String nodeValue;
+        doc = (Document) load("staffNS", builder);
+        domImpl = doc.getImplementation();
+        aNewDoc = domImpl.createDocument(namespaceURI, qualifiedName, docType);
+        nodeName = aNewDoc.getNodeName();
+        nodeValue = aNewDoc.getNodeValue();
+        assertEquals("nodeName", "#document", nodeName);
+        assertNull("nodeValue", nodeValue);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify null as parameters.",
+        method = "createDocument",
+        args = {java.lang.String.class, java.lang.String.class, org.w3c.dom.DocumentType.class}
+    )
+    public void testCreateDocument8() throws Throwable {
+        String namespaceURI = "http://www.example.org/schema";
+        DocumentType docType = null;
+
+        DOMImplementation domImpl;
+
+        domImpl = builder.getDOMImplementation();
+
+        boolean success = false;
+        try {
+            domImpl.createDocument(namespaceURI, "", docType);
+        } catch (DOMException ex) {
+            success = (ex.code == DOMException.NAMESPACE_ERR);
+        }
+        assertTrue("throw_NAMESPACE_ERR", success);
+
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/CreateDocumentType.java b/xml/src/test/java/tests/org/w3c/dom/CreateDocumentType.java
new file mode 100644
index 0000000..c5061b8
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/CreateDocumentType.java
@@ -0,0 +1,222 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DocumentType;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The "createDocumentType(qualifiedName,publicId,systemId)" method for a
+ * DOMImplementation should raise NAMESPACE_ERR DOMException if qualifiedName is
+ * malformed.
+ * 
+ * Retrieve the DOMImplementation on the XMLNS Document. Invoke method
+ * createDocumentType(qualifiedName,publicId,systemId) on the retrieved
+ * DOMImplementation with qualifiedName being the literal string
+ * "prefix::local", publicId as "STAFF", and systemId as "staff". Method should
+ * raise NAMESPACE_ERR DOMException.
+ * 
+ * @author NIST
+ * @author Mary Brady
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='NAMESPACE_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='NAMESPACE_ERR'])</a>
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#Level-2-Core-DOM-createDocType">http://www.w3.org/TR/DOM-Level-2-Core/core#Level-2-Core-DOM-createDocType</a>
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('Level-2-Core-DOM-createDocType')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='NAMESPACE_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('Level-2-Core-DOM-createDocType')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='NAMESPACE_ERR'])</a>
+ */
+@TestTargetClass(DOMImplementation.class) 
+public final class CreateDocumentType extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify null as parameters.",
+        method = "createDocumentType",
+        args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateDocumentType1() throws Throwable {
+        String publicId = "STAFF";
+        String systemId = "staff.xml";
+        String malformedName = "prefix::local";
+        Document doc;
+        DOMImplementation domImpl;
+
+        doc = (Document) load("staffNS", builder);
+        domImpl = doc.getImplementation();
+
+        {
+            boolean success = false;
+            try {
+                domImpl.createDocumentType(malformedName, publicId, systemId);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("throw_NAMESPACE_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify null as parameters.",
+        method = "createDocumentType",
+        args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateDocumentType2() throws Throwable {
+        String publicId = "http://www.localhost.com/";
+        String systemId = "myDoc.dtd";
+        String qualifiedName;
+        Document doc;
+
+        DOMImplementation domImpl;
+        List<String> illegalQNames = new ArrayList<String>();
+        illegalQNames.add("edi:{");
+        illegalQNames.add("edi:}");
+        illegalQNames.add("edi:~");
+        illegalQNames.add("edi:'");
+        illegalQNames.add("edi:!");
+        illegalQNames.add("edi:@");
+        illegalQNames.add("edi:#");
+        illegalQNames.add("edi:$");
+        illegalQNames.add("edi:%");
+        illegalQNames.add("edi:^");
+        illegalQNames.add("edi:&");
+        illegalQNames.add("edi:*");
+        illegalQNames.add("edi:(");
+        illegalQNames.add("edi:)");
+        illegalQNames.add("edi:+");
+        illegalQNames.add("edi:=");
+        illegalQNames.add("edi:[");
+        illegalQNames.add("edi:]");
+        illegalQNames.add("edi:\\");
+        illegalQNames.add("edi:/");
+        illegalQNames.add("edi:;");
+        illegalQNames.add("edi:`");
+        illegalQNames.add("edi:<");
+        illegalQNames.add("edi:>");
+        illegalQNames.add("edi:,");
+        illegalQNames.add("edi:a ");
+        illegalQNames.add("edi:\"");
+
+        doc = (Document) load("staffNS", builder);
+        for (int indexN1009A = 0; indexN1009A < illegalQNames.size(); indexN1009A++) {
+            qualifiedName = (String) illegalQNames.get(indexN1009A);
+            domImpl = doc.getImplementation();
+
+            {
+                boolean success = false;
+                try {
+                    domImpl.createDocumentType(qualifiedName, publicId,
+                            systemId);
+                } catch (DOMException ex) {
+                    success = (ex.code == DOMException.INVALID_CHARACTER_ERR);
+                }
+                assertTrue("throw_INVALID_CHARACTER_ERR", success);
+            }
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify null as parameters.",
+        method = "createDocumentType",
+        args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateDocumentType3() throws Throwable {
+        
+        String qualifiedName = "prefix:myDoc";
+        String publicId = "http://www.localhost.com";
+        String systemId = "myDoc.dtd";
+        Document doc;
+        DOMImplementation domImpl;
+        DocumentType newType = null;
+
+        String nodeName;
+        String nodeValue;
+        doc = (Document) load("staffNS", builder);
+        domImpl = doc.getImplementation();
+        newType = domImpl.createDocumentType(qualifiedName, publicId, systemId);
+        nodeName = newType.getNodeName();
+        assertEquals("nodeName", "prefix:myDoc", nodeName);
+        nodeValue = newType.getNodeValue();
+        assertNull("nodeValue", nodeValue);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify null as parameters.",
+        method = "createDocumentType",
+        args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateDocumentType4() throws Throwable {
+        String publicId = "http://www.example.com/";
+        String systemId = "myDoc.dtd";
+
+        DOMImplementation domImpl;
+        domImpl = builder.getDOMImplementation();
+
+        {
+            boolean success = false;
+            try {
+                domImpl.createDocumentType("", publicId, systemId);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("throw_NAMESPACE_ERR", success);
+        }
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/CreateElementNS.java b/xml/src/test/java/tests/org/w3c/dom/CreateElementNS.java
new file mode 100644
index 0000000..8d8bb4d
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/CreateElementNS.java
@@ -0,0 +1,251 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Element;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The "createElementNS(namespaceURI,qualifiedName)" method for a Document
+ * should raise NAMESPACE_ERR DOMException if qualifiedName is malformed.
+ * 
+ * Invoke method createElementNS(namespaceURI,qualifiedName) on the XMLNS
+ * Document with namespaceURI being the literal string
+ * "http://www.ecommerce.org/", and qualifiedName as "prefix::local". Method
+ * should raise NAMESPACE_ERR DOMException.
+ * 
+ * @author NIST
+ * @author Mary Brady
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='NAMESPACE_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='NAMESPACE_ERR'])</a>
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-DocCrElNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-DocCrElNS</a>
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-DocCrElNS')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='NAMESPACE_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-DocCrElNS')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='NAMESPACE_ERR'])</a>
+ */
+@TestTargetClass(Document.class) 
+public final class CreateElementNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify null as a parameters, and other types of DOMException.",
+        method = "createElementNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateElementNS1() throws Throwable {
+        String namespaceURI = "http://www.ecommerce.org/";
+        String malformedName = "prefix::local";
+        Document doc;
+        
+        doc = (Document) load("staffNS", builder);
+
+        {
+            boolean success = false;
+            try {
+                doc.createElementNS(namespaceURI, malformedName);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("throw_NAMESPACE_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify null as a parameters, and other types of DOMException.",
+        method = "createElementNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateElementNS2() throws Throwable {
+        String namespaceURI = null;
+
+        String qualifiedName = "prefix:local";
+        Document doc;
+
+        doc = (Document) load("staffNS", builder);
+
+        {
+            boolean success = false;
+            try {
+                doc.createElementNS(namespaceURI, qualifiedName);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("throw_NAMESPACE_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify null as a parameters, and other types of DOMException.",
+        method = "createElementNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateElementNS3() throws Throwable {
+        String namespaceURI = "http://www.wedding.com/";
+        String qualifiedName;
+        Document doc;
+
+        List<String> illegalQNames = new ArrayList<String>();
+        illegalQNames.add("person:{");
+        illegalQNames.add("person:}");
+        illegalQNames.add("person:~");
+        illegalQNames.add("person:'");
+        illegalQNames.add("person:!");
+        illegalQNames.add("person:@");
+        illegalQNames.add("person:#");
+        illegalQNames.add("person:$");
+        illegalQNames.add("person:%");
+        illegalQNames.add("person:^");
+        illegalQNames.add("person:&");
+        illegalQNames.add("person:*");
+        illegalQNames.add("person:(");
+        illegalQNames.add("person:)");
+        illegalQNames.add("person:+");
+        illegalQNames.add("person:=");
+        illegalQNames.add("person:[");
+        illegalQNames.add("person:]");
+        illegalQNames.add("person:\\");
+        illegalQNames.add("person:/");
+        illegalQNames.add("person:;");
+        illegalQNames.add("person:`");
+        illegalQNames.add("person:<");
+        illegalQNames.add("person:>");
+        illegalQNames.add("person:,");
+        illegalQNames.add("person:a ");
+        illegalQNames.add("person:\"");
+
+        doc = (Document) load("staffNS", builder);
+        for (int indexN10098 = 0; indexN10098 < illegalQNames.size(); indexN10098++) {
+            qualifiedName = (String) illegalQNames.get(indexN10098);
+
+            {
+                boolean success = false;
+                try {
+                    doc.createElementNS(namespaceURI, qualifiedName);
+                } catch (DOMException ex) {
+                    success = (ex.code == DOMException.INVALID_CHARACTER_ERR);
+                }
+                assertTrue("throw_INVALID_CHARACTER_ERR", success);
+            }
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify null as a parameters, and other types of DOMException.",
+        method = "createElementNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateElementNS4() throws Throwable {
+        String namespaceURI = "http://www.w3.org/XML/1998/namespaces";
+        String qualifiedName = "xml:element1";
+        Document doc;
+
+        doc = (Document) load("staffNS", builder);
+
+        {
+            boolean success = false;
+            try {
+                doc.createElementNS(namespaceURI, qualifiedName);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("throw_NAMESPACE_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify null as a parameters, and other types of DOMException.",
+        method = "createElementNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateElementNS5() throws Throwable {
+        String namespaceURI = "http://www.nist.gov";
+        String qualifiedName = "gov:faculty";
+        Document doc;
+        Element newElement;
+        String elementName;
+        doc = (Document) load("staffNS", builder);
+        newElement = doc.createElementNS(namespaceURI, qualifiedName);
+        elementName = newElement.getTagName();
+        assertEquals("throw_Equals", qualifiedName, elementName);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify null as a parameters, and other types of DOMException.",
+        method = "createElementNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateElementNS6() throws Throwable {
+        String namespaceURI = "http://www.example.com/";
+
+        Document doc;
+
+        doc = (Document) load("hc_staff", builder);
+
+        {
+            boolean success = false;
+            try {
+                doc.createElementNS(namespaceURI, "");
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("throw_NAMESPACE_ERR", success);
+        }
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/DOMDocumentBuilderFactory.java b/xml/src/test/java/tests/org/w3c/dom/DOMDocumentBuilderFactory.java
new file mode 100644
index 0000000..d28b2d7
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/DOMDocumentBuilderFactory.java
@@ -0,0 +1,94 @@
+package tests.org.w3c.dom;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+public class DOMDocumentBuilderFactory {
+    /**
+     * Parser configuration
+     */
+    private DocumentBuilderSetting[] settings = null;
+
+    private DocumentBuilder builder = null;
+
+    private DocumentBuilderFactory factory = null;
+
+    public DOMDocumentBuilderFactory(DocumentBuilderSetting[] settings) {
+        if (settings == null) {
+            settings = new DocumentBuilderSetting[0];
+        } else {
+            settings = (DocumentBuilderSetting[]) settings.clone();
+        }
+
+        factory = DocumentBuilderFactory.newInstance();
+        
+        if (factory == null) {
+            throw new RuntimeException("DocumentBuilderFactory must not be null");
+        }
+
+        if (settings != null) {
+            for (int i = 0; i < settings.length; i++) {
+                settings[i].applySetting(factory);
+            }
+        }
+        try {
+            builder = factory.newDocumentBuilder();
+        } catch (ParserConfigurationException e) {
+            e.printStackTrace();
+        }
+        
+        if (builder == null) {
+            throw new RuntimeException("DocumentBuilder must not be null");
+        }
+        
+    }
+
+    public DocumentBuilder getBuilder() {
+        return builder;
+    }
+
+    public boolean hasFeature(String feature, String version) {
+        return builder.getDOMImplementation().hasFeature(feature, version);
+    }
+
+    public boolean isCoalescing() {
+        return factory.isCoalescing();
+    }
+
+    public boolean isExpandEntityReferences() {
+        return factory.isExpandEntityReferences();
+    }
+
+    public boolean isIgnoringElementContentWhitespace() {
+        return factory.isIgnoringElementContentWhitespace();
+    }
+
+    public boolean isNamespaceAware() {
+        return factory.isNamespaceAware();
+    }
+
+    public boolean isValidating() {
+        return factory.isValidating();
+    }
+
+    public static DocumentBuilderSetting[] getConfiguration1() {
+        return new DocumentBuilderSetting[] {
+                DocumentBuilderSetting.notCoalescing,
+                DocumentBuilderSetting.notExpandEntityReferences,
+                DocumentBuilderSetting.notIgnoringElementContentWhitespace,
+                DocumentBuilderSetting.notNamespaceAware,
+                DocumentBuilderSetting.notValidating };
+    }
+
+    public static DocumentBuilderSetting[] getConfiguration2() {
+        return new DocumentBuilderSetting[] {
+                DocumentBuilderSetting.notCoalescing,
+                DocumentBuilderSetting.notExpandEntityReferences,
+                DocumentBuilderSetting.notIgnoringElementContentWhitespace,
+                DocumentBuilderSetting.namespaceAware,
+                DocumentBuilderSetting.notValidating };
+
+    }
+
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/DOMImplementationCreateDocument.java b/xml/src/test/java/tests/org/w3c/dom/DOMImplementationCreateDocument.java
new file mode 100644
index 0000000..d2650a4
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/DOMImplementationCreateDocument.java
@@ -0,0 +1,177 @@
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.DOMException;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The createDocument method with valid arguments, should create a DOM Document
+ * of the specified type.
+ * 
+ * Call the createDocument on this DOMImplementation with createDocument
+ * ("http://www.w3.org/DOMTest/L2",see the array below for valid QNames,null).
+ * Check if the returned Document object is is empty with no Document Element.
+ * 
+ * @author IBM
+ * @author Neil Delima
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#Level-2-Core-DOM-createDocument">http://www.w3.org/TR/DOM-Level-2-Core/core#Level-2-Core-DOM-createDocument</a>
+ */
+@TestTargetClass(DOMImplementation.class) 
+public final class DOMImplementationCreateDocument extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "createDocument",
+        args = {java.lang.String.class, java.lang.String.class, org.w3c.dom.DocumentType.class}
+    )
+    public void testCreateDocument3() throws Throwable {
+        Document doc;
+        DOMImplementation domImpl;
+        Document newDoc;
+        DocumentType docType = null;
+
+        String namespaceURI = "http://www.w3.org/DOMTest/L2";
+        String qualifiedName;
+        List<String> qualifiedNames = new ArrayList<String>();
+        qualifiedNames.add("_:_");
+        qualifiedNames.add("_:h0");
+        qualifiedNames.add("_:test");
+        qualifiedNames.add("l_:_");
+        qualifiedNames.add("ns:_0");
+        qualifiedNames.add("ns:a0");
+        qualifiedNames.add("ns0:test");
+        qualifiedNames.add("a.b:c");
+        qualifiedNames.add("a-b:c");
+        qualifiedNames.add("a-b:c");
+
+        doc = (Document) load("staffNS", builder);
+        domImpl = doc.getImplementation();
+        for (int indexN1006B = 0; indexN1006B < qualifiedNames.size(); indexN1006B++) {
+            qualifiedName = (String) qualifiedNames.get(indexN1006B);
+            newDoc = domImpl.createDocument(namespaceURI, qualifiedName,
+                    docType);
+            assertNotNull("domimplementationcreatedocument03", newDoc);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies DOMException with NAMESPACE_ERR code.",
+        method = "createDocument",
+        args = {java.lang.String.class, java.lang.String.class, org.w3c.dom.DocumentType.class}
+    )
+    public void testCreateDocument4() throws Throwable {
+        Document doc;
+        DOMImplementation domImpl;
+
+        String namespaceURI = null;
+
+        String qualifiedName = "dom:root";
+        DocumentType docType = null;
+
+        doc = (Document) load("staffNS", builder);
+        domImpl = doc.getImplementation();
+
+        {
+            boolean success = false;
+            try {
+                domImpl.createDocument(namespaceURI, qualifiedName, docType);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("domimplementationcreatedocument04", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies DOMException with NAMESPACE_ERR code.",
+        method = "createDocument",
+        args = {java.lang.String.class, java.lang.String.class, org.w3c.dom.DocumentType.class}
+    )
+    public void testCreateDocument5() throws Throwable {
+        Document doc;
+        DOMImplementation domImpl;
+
+        String namespaceURI = "http://www.w3.org/xml/1998/namespace";
+        String qualifiedName = "xml:root";
+        DocumentType docType = null;
+
+        doc = (Document) load("staffNS", builder);
+        domImpl = doc.getImplementation();
+
+        {
+            boolean success = false;
+            try {
+                domImpl.createDocument(namespaceURI, qualifiedName, docType);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("domimplementationcreatedocument05", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies DOMException with NAMESPACE_ERR code.",
+        method = "createDocument",
+        args = {java.lang.String.class, java.lang.String.class, org.w3c.dom.DocumentType.class}
+    )
+    public void testCreateDocument7() throws Throwable {
+        Document doc;
+        DOMImplementation domImpl;
+
+        String namespaceURI = "http://www.w3.org/DOMTest/level2";
+        DocumentType docType = null;
+
+        doc = (Document) load("staffNS", builder);
+        domImpl = doc.getImplementation();
+
+        {
+            boolean success = false;
+            try {
+                domImpl.createDocument(namespaceURI, ":", docType);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("domimplementationcreatedocument07", success);
+        }
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/DOMImplementationCreateDocumentType.java b/xml/src/test/java/tests/org/w3c/dom/DOMImplementationCreateDocumentType.java
new file mode 100644
index 0000000..286e75d
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/DOMImplementationCreateDocumentType.java
@@ -0,0 +1,208 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The method createDocumentType with valid values for qualifiedName, publicId
+ * and systemId should create an empty DocumentType node.
+ * 
+ * Invoke createDocument on this DOMImplementation with a valid qualifiedName
+ * and different publicIds and systemIds. Check if the the DocumentType node was
+ * created with its ownerDocument attribute set to null.
+ * 
+ * @author IBM
+ * @author Neil Delima
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#Level-2-Core-DOM-createDocument">http://www.w3.org/TR/DOM-Level-2-Core/core#Level-2-Core-DOM-createDocument</a>
+ */
+@TestTargetClass(DOMImplementation.class) 
+public final class DOMImplementationCreateDocumentType extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "createDocumentType",
+        args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateDocumentType1() throws Throwable {
+        Document doc;
+        DOMImplementation domImpl;
+        DocumentType newDocType;
+        Document ownerDocument;
+        String qualifiedName = "test:root";
+        String publicId;
+        String systemId;
+        List<String> publicIds = new ArrayList<String>();
+        publicIds.add("1234");
+        publicIds.add("test");
+
+        List<String> systemIds = new ArrayList<String>();
+        systemIds.add("");
+        systemIds.add("test");
+
+        doc = (Document) load("staffNS", builder);
+        domImpl = doc.getImplementation();
+        for (int indexN1005D = 0; indexN1005D < publicIds.size(); indexN1005D++) {
+            publicId = (String) publicIds.get(indexN1005D);
+            for (int indexN10061 = 0; indexN10061 < systemIds.size(); indexN10061++) {
+                systemId = (String) systemIds.get(indexN10061);
+                newDocType = domImpl.createDocumentType(qualifiedName,
+                        publicId, systemId);
+                assertNotNull(
+                        "domimplementationcreatedocumenttype01_newDocType",
+                        newDocType);
+                ownerDocument = newDocType.getOwnerDocument();
+                assertNull(
+                        "domimplementationcreatedocumenttype01_ownerDocument",
+                        ownerDocument);
+            }
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "createDocumentType",
+        args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateDocumentType2() throws Throwable {
+        Document doc;
+        DOMImplementation domImpl;
+        DocumentType newDocType;
+        Document ownerDocument;
+        String publicId = "http://www.w3.org/DOM/Test/dom2.dtd";
+        String systemId = "dom2.dtd";
+        String qualifiedName;
+        List<String> qualifiedNames = new ArrayList<String>();
+        qualifiedNames.add("_:_");
+        qualifiedNames.add("_:h0");
+        qualifiedNames.add("_:test");
+        qualifiedNames.add("_:_.");
+        qualifiedNames.add("_:a-");
+        qualifiedNames.add("l_:_");
+        qualifiedNames.add("ns:_0");
+        qualifiedNames.add("ns:a0");
+        qualifiedNames.add("ns0:test");
+        qualifiedNames.add("ns:EEE.");
+        qualifiedNames.add("ns:_-");
+        qualifiedNames.add("a.b:c");
+        qualifiedNames.add("a-b:c.j");
+        qualifiedNames.add("a-b:c");
+
+        doc = (Document) load("staffNS", builder);
+        domImpl = doc.getImplementation();
+        for (int indexN10077 = 0; indexN10077 < qualifiedNames.size(); indexN10077++) {
+            qualifiedName = (String) qualifiedNames.get(indexN10077);
+            newDocType = domImpl.createDocumentType(qualifiedName, publicId,
+                    systemId);
+            assertNotNull("domimplementationcreatedocumenttype02_newDocType",
+                    newDocType);
+            ownerDocument = newDocType.getOwnerDocument();
+            assertNull("domimplementationcreatedocumenttype02_ownerDocument",
+                    ownerDocument);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "createDocumentType",
+        args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateDocumentType4() throws Throwable {
+        Document doc;
+        DOMImplementation domImpl;
+        DocumentType newDocType;
+        Document ownerDocument;
+        String publicId = "http://www.w3.org/DOM/Test/dom2.dtd";
+        String systemId = "dom2.dtd";
+        String qualifiedName;
+        List<String> qualifiedNames = new ArrayList<String>();
+        qualifiedNames.add("_:_");
+        qualifiedNames.add("_:h0");
+        qualifiedNames.add("_:test");
+        qualifiedNames.add("_:_.");
+        qualifiedNames.add("_:a-");
+        qualifiedNames.add("l_:_");
+        qualifiedNames.add("ns:_0");
+        qualifiedNames.add("ns:a0");
+        qualifiedNames.add("ns0:test");
+        qualifiedNames.add("ns:EEE.");
+        qualifiedNames.add("ns:_-");
+        qualifiedNames.add("a.b:c");
+        qualifiedNames.add("a-b:c.j");
+        qualifiedNames.add("a-b:c");
+
+        doc = (Document) load("staffNS", builder);
+        domImpl = doc.getImplementation();
+        for (int indexN10077 = 0; indexN10077 < qualifiedNames.size(); indexN10077++) {
+            qualifiedName = (String) qualifiedNames.get(indexN10077);
+            newDocType = domImpl.createDocumentType(qualifiedName, publicId,
+                    systemId);
+            assertNotNull("domimplementationcreatedocumenttype02_newDocType",
+                    newDocType);
+            ownerDocument = newDocType.getOwnerDocument();
+            assertNull("domimplementationcreatedocumenttype02_ownerDocument",
+                    ownerDocument);
+        }
+    }
+
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/DOMImplementationHasFeature.java b/xml/src/test/java/tests/org/w3c/dom/DOMImplementationHasFeature.java
new file mode 100644
index 0000000..257555b
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/DOMImplementationHasFeature.java
@@ -0,0 +1,147 @@
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The "feature" parameter in the "hasFeature(feature,version)" method is the
+ * package name of the feature. Legal values are XML and HTML and CORE. (Test
+ * for feature core, lower case)
+ * 
+ * Retrieve the entire DOM document and invoke its "getImplementation()" method.
+ * This should create a DOMImplementation object whose "hasFeature(feature,
+ * version)" method is invoked with feature equal to "core". The method should
+ * return a boolean "true".
+ * 
+ * @author NIST
+ * @author Mary Brady
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-5CED94D7">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-5CED94D7</a>
+ */
+@TestTargetClass(DOMImplementation.class) 
+public final class DOMImplementationHasFeature extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that hasFeature returns true value.",
+        method = "hasFeature",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testHasFeatureCore() throws Throwable {
+        Document doc;
+        DOMImplementation domImpl;
+        boolean state;
+        doc = (Document) load("staff", builder);
+        domImpl = doc.getImplementation();
+        state = domImpl.hasFeature("core", "2.0");
+        assertTrue("domimplementationFeaturecoreAssert", state);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that hasFeature returns true value.",
+        method = "hasFeature",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testHasFeatureXml() throws Throwable {
+        Document doc;
+        DOMImplementation domImpl;
+        boolean state;
+        doc = (Document) load("staff", builder);
+        domImpl = doc.getImplementation();
+        state = domImpl.hasFeature("xml", "2.0");
+        assertTrue("domimplementationFeaturexmlVersion2Assert", state);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify that hasFeature method returns false.",
+        method = "hasFeature",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testHasFeature1() throws Throwable {
+        Document doc;
+        DOMImplementation domImpl;
+        String version = "";
+        String version1 = "1.0";
+        String version2 = "2.0";
+        String featureCore;
+        String featureXML;
+        boolean success;
+        List<String> featuresXML = new ArrayList<String>();
+        featuresXML.add("XML");
+        featuresXML.add("xmL");
+
+        List<String> featuresCore = new ArrayList<String>();
+        featuresCore.add("Core");
+        featuresCore.add("CORE");
+
+        doc = (Document) load("staffNS", builder);
+        domImpl = doc.getImplementation();
+        for (int indexN10063 = 0; indexN10063 < featuresXML.size(); indexN10063++) {
+            featureXML = (String) featuresXML.get(indexN10063);
+            success = domImpl.hasFeature(featureXML, version);
+            assertTrue("domimplementationhasfeature01_XML_1", success);
+            success = domImpl.hasFeature(featureXML, version1);
+            assertTrue("domimplementationhasfeature01_XML_2", success);
+        }
+        for (int indexN1007C = 0; indexN1007C < featuresCore.size(); indexN1007C++) {
+            featureCore = (String) featuresCore.get(indexN1007C);
+            success = domImpl.hasFeature(featureCore, version);
+            assertTrue("domimplementationhasfeature01_Core_1", success);
+            success = domImpl.hasFeature(featureCore, version1);
+            success = domImpl.hasFeature(featureCore, version2);
+            assertTrue("domimplementationhasfeature01_Core_3", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that hasFeature method returns false.",
+        method = "hasFeature",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testHasFeature2() throws Throwable {
+        Document doc;
+        DOMImplementation domImpl;
+        boolean success;
+        doc = (Document) load("staffNS", builder);
+        domImpl = doc.getImplementation();
+        success = domImpl.hasFeature("Blah Blah", "");
+        assertFalse("domimplementationhasfeature02", success);
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/DOMTestCase.java b/xml/src/test/java/tests/org/w3c/dom/DOMTestCase.java
new file mode 100644
index 0000000..041b67b
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/DOMTestCase.java
@@ -0,0 +1,230 @@
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargetClass; 
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.xml.parsers.DocumentBuilder;
+
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import junit.framework.TestCase;
+
+@TestTargetClass(Document.class) 
+public class DOMTestCase extends TestCase {
+
+    public Document load(String docURI, DocumentBuilder builder) {
+        Document doc = load(resolveURI(docURI), builder);
+        return doc;
+    }
+
+    public Document load(URL url, DocumentBuilder builder) {
+        Document doc = null;
+        Exception parseException = null;
+        try {
+            LoadErrorHandler errorHandler = new LoadErrorHandler();
+            builder.setErrorHandler(errorHandler);
+            doc = builder.parse(url.openStream());
+            parseException = errorHandler.getFirstException();
+        } catch (Exception ex) {
+            parseException = ex;
+        }
+        builder.setErrorHandler(null);
+        if (parseException != null) {
+            // fail("Unexpected exception " + parseException.getMessage());
+            throw new RuntimeException("Unexpected exception " + parseException.getMessage(), parseException);
+        }
+        return doc;
+    }
+
+    public void preload(String contentType, String docURI,
+            boolean willBeModified) {
+        if ("text/html".equals(contentType)
+                || "application/xhtml+xml".equals(contentType)) {
+            if (docURI.startsWith("staff")
+                    || docURI.equals("datatype_normalization")) {
+
+            }
+        }
+    }
+
+    private URL resolveURI(String baseURI) {
+        String docURI = baseURI + ".xml";
+
+        URL resolvedURI = null;
+        try {
+            resolvedURI = new URL(docURI);
+            if (resolvedURI.getProtocol() != null) {
+                return resolvedURI;
+            }
+        } catch (MalformedURLException ex) {
+            // fail("Unexpected exception " + ex.getMessage());
+        }
+        //
+        // build a URL for a test file in the JAR
+        //
+        resolvedURI = getClass().getResource("/" + docURI);
+        if (resolvedURI == null) {
+            //
+            // see if it is an absolute URI
+            //
+            int firstSlash = docURI.indexOf('/');
+            try {
+                if (firstSlash == 0
+                        || (firstSlash >= 1 && docURI.charAt(firstSlash - 1) == ':')) {
+                    resolvedURI = new URL(docURI);
+                } else {
+                    //
+                    // try the files/level?/spec directory
+                    //
+                    String filename = getClass().getPackage().getName();
+                    filename = "tests/"
+                            + filename.substring(14).replace('.', '/')
+                            + "/files/" + docURI;
+                    resolvedURI = new java.io.File(filename).toURL();
+                }
+            } catch (MalformedURLException ex) {
+                fail("Unexpected exception " + ex.getMessage());
+            }
+        }
+
+        if (resolvedURI == null) {
+            fail("resolvedURI is null ");
+        }
+        return resolvedURI;
+    }
+
+
+    public String getContentType() {
+        return "xml";
+    }
+
+    public void assertURIEquals(String assertID, String scheme, String path,
+            String host, String file, String name, String query,
+            String fragment, Boolean isAbsolute, String actual) {
+        //
+        // URI must be non-null
+        assertNotNull(assertID, actual);
+
+        String uri = actual;
+
+        int lastPound = actual.lastIndexOf("#");
+        String actualFragment = "";
+        if (lastPound != -1) {
+            //
+            // substring before pound
+            //
+            uri = actual.substring(0, lastPound);
+            actualFragment = actual.substring(lastPound + 1);
+        }
+        if (fragment != null) {
+            assertEquals(assertID, fragment, actualFragment);
+
+        }
+        int lastQuestion = uri.lastIndexOf("?");
+        String actualQuery = "";
+        if (lastQuestion != -1) {
+            //
+            // substring before pound
+            //
+            uri = actual.substring(0, lastQuestion);
+            actualQuery = actual.substring(lastQuestion + 1);
+        }
+        if (query != null) {
+            assertEquals(assertID, query, actualQuery);
+
+        }
+        int firstColon = uri.indexOf(":");
+        int firstSlash = uri.indexOf("/");
+        String actualPath = uri;
+        String actualScheme = "";
+        if (firstColon != -1 && firstColon < firstSlash) {
+            actualScheme = uri.substring(0, firstColon);
+            actualPath = uri.substring(firstColon + 1);
+        }
+
+        if (scheme != null) {
+            assertEquals(assertID, scheme, actualScheme);
+        }
+
+        if (path != null) {
+            assertEquals(assertID, path, actualPath);
+        }
+
+        if (host != null) {
+            String actualHost = "";
+            if (actualPath.startsWith("//")) {
+                int termSlash = actualPath.indexOf("/", 2);
+                actualHost = actualPath.substring(0, termSlash);
+            }
+            assertEquals(assertID, host, actualHost);
+        }
+
+        String actualFile = actualPath;
+        if (file != null || name != null) {
+            int finalSlash = actualPath.lastIndexOf("/");
+            if (finalSlash != -1) {
+                actualFile = actualPath.substring(finalSlash + 1);
+            }
+            if (file != null) {
+                assertEquals(assertID, file, actualFile);
+            }
+        }
+
+        if (name != null) {
+            String actualName = actualFile;
+            int finalPeriod = actualFile.lastIndexOf(".");
+            if (finalPeriod != -1) {
+                actualName = actualFile.substring(0, finalPeriod);
+            }
+            assertEquals(assertID, name, actualName);
+        }
+
+        if (isAbsolute != null) {
+            //
+            // Jar URL's will have any actual path like file:/c:/somedrive...
+            assertEquals(assertID, isAbsolute.booleanValue(), actualPath
+                    .startsWith("/")
+                    || actualPath.startsWith("file:/"));
+        }
+    }
+
+    
+    private class LoadErrorHandler implements org.xml.sax.ErrorHandler {
+        private SAXException parseException;
+
+        private int errorCount;
+
+        private int warningCount;
+
+        public LoadErrorHandler() {
+            parseException = null;
+            errorCount = 0;
+            warningCount = 0;
+        }
+
+        public void error(SAXParseException ex) {
+            errorCount++;
+            if (parseException == null) {
+                parseException = ex;
+            }
+        }
+
+        public void warning(SAXParseException ex) {
+            warningCount++;
+        }
+
+        public void fatalError(SAXParseException ex) {
+            if (parseException == null) {
+                parseException = ex;
+            }
+        }
+
+        public SAXException getFirstException() {
+            return parseException;
+        }
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/DocumentBuilderSetting.java b/xml/src/test/java/tests/org/w3c/dom/DocumentBuilderSetting.java
new file mode 100644
index 0000000..bbb7190
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/DocumentBuilderSetting.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2001-2004 World Wide Web Consortium, (Massachusetts Institute
+ * of Technology, Institut National de Recherche en Informatique et en
+ * Automatique, Keio University). All Rights Reserved. This program is
+ * distributed under the W3C's Software Intellectual Property License. This
+ * program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See W3C License
+ * http://www.w3.org/Consortium/Legal/ for more details.
+ */
+
+package tests.org.w3c.dom;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+
+/**
+ * This class is an parser setting, such as non-validating or entity-expanding.
+ *
+ * @author Curt Arnold @date 2 Feb 2002
+ */
+public final class DocumentBuilderSetting {
+  /**
+   * property name.
+   */
+  private final String property;
+
+  /**
+   *   property value.
+   */
+  private final boolean value;
+
+  /**
+   * strategy used to set or get property value.
+   */
+  private final DocumentBuilderSettingStrategy strategy;
+
+  /**
+   * coalescing = true.
+   */
+  public static final DocumentBuilderSetting coalescing =
+      new DocumentBuilderSetting(
+      "coalescing",
+      true,
+      DocumentBuilderSettingStrategy.coalescing);
+
+  /**
+   * coalescing = false.
+   */
+  public static final DocumentBuilderSetting notCoalescing =
+      new DocumentBuilderSetting(
+      "coalescing",
+      false,
+      DocumentBuilderSettingStrategy.coalescing);
+
+  /**
+   * expandEntityReferences = false.
+   */
+  public static final DocumentBuilderSetting expandEntityReferences =
+      new DocumentBuilderSetting(
+      "expandEntityReferences",
+      true,
+      DocumentBuilderSettingStrategy.expandEntityReferences);
+
+  /**
+   * expandEntityReferences = true.
+   */
+  public static final DocumentBuilderSetting notExpandEntityReferences =
+      new DocumentBuilderSetting(
+      "expandEntityReferences",
+      false,
+      DocumentBuilderSettingStrategy.expandEntityReferences);
+
+  /**
+   * ignoringElementContentWhitespace = true.
+   */
+  public static final DocumentBuilderSetting ignoringElementContentWhitespace =
+      new DocumentBuilderSetting(
+      "ignoringElementContentWhitespace",
+      true,
+      DocumentBuilderSettingStrategy.ignoringElementContentWhitespace);
+
+  /**
+   * ignoringElementContentWhitespace = false.
+   */
+  public static final DocumentBuilderSetting
+      notIgnoringElementContentWhitespace =
+      new DocumentBuilderSetting(
+      "ignoringElementContentWhitespace",
+      false,
+      DocumentBuilderSettingStrategy.ignoringElementContentWhitespace);
+
+  /**
+   * namespaceAware = true.
+   */
+  public static final DocumentBuilderSetting namespaceAware =
+      new DocumentBuilderSetting(
+      "namespaceAware",
+      true,
+      DocumentBuilderSettingStrategy.namespaceAware);
+
+  /**
+   * namespaceAware = false.
+   */
+  public static final DocumentBuilderSetting notNamespaceAware =
+      new DocumentBuilderSetting(
+      "namespaceAware",
+      false,
+      DocumentBuilderSettingStrategy.namespaceAware);
+
+  /**
+   * validating = true.
+   */
+  public static final DocumentBuilderSetting validating =
+      new DocumentBuilderSetting(
+      "validating",
+      true,
+      DocumentBuilderSettingStrategy.validating);
+
+  /**
+   * validating = false.
+   */
+  public static final DocumentBuilderSetting notValidating =
+      new DocumentBuilderSetting(
+      "validating",
+      false,
+      DocumentBuilderSettingStrategy.validating);
+
+  /**
+   * signed = true.
+   */
+  public static final DocumentBuilderSetting signed =
+      new DocumentBuilderSetting(
+      "signed",
+      true,
+      DocumentBuilderSettingStrategy.signed);
+
+  /**
+   * signed = false.
+   */
+  public static final DocumentBuilderSetting notSigned =
+      new DocumentBuilderSetting(
+      "signed",
+      false,
+      DocumentBuilderSettingStrategy.signed);
+
+  /**
+   * hasNullString = true.
+   */
+  public static final DocumentBuilderSetting hasNullString =
+      new DocumentBuilderSetting(
+      "hasNullString",
+      true,
+      DocumentBuilderSettingStrategy.hasNullString);
+
+  /**
+   * hasNullString = false.
+   */
+  public static final DocumentBuilderSetting notHasNullString =
+      new DocumentBuilderSetting(
+      "hasNullString",
+      false,
+      DocumentBuilderSettingStrategy.hasNullString);
+
+  /**
+   * Schema validating enabled.
+   */
+  public static final DocumentBuilderSetting schemaValidating =
+      new DocumentBuilderSetting(
+      "schemaValidating",
+      true,
+      DocumentBuilderSettingStrategy.schemaValidating);
+
+  /**
+   * Schema validating disabled.
+   */
+  public static final DocumentBuilderSetting notSchemaValidating =
+      new DocumentBuilderSetting(
+      "schemaValidating",
+      false,
+      DocumentBuilderSettingStrategy.schemaValidating);
+
+  /**
+   * Comments ignored.
+   */
+  public static final DocumentBuilderSetting ignoringComments =
+      new DocumentBuilderSetting(
+      "ignoringComments",
+      true,
+      DocumentBuilderSettingStrategy.ignoringComments);
+
+  /**
+   * Comments preserved.
+   */
+  public static final DocumentBuilderSetting notIgnoringComments =
+      new DocumentBuilderSetting(
+      "ignoringComments",
+      false,
+      DocumentBuilderSettingStrategy.ignoringComments);
+
+  /**
+   * Protected constructor, use static members for supported settings.
+   * @param property property name, follows JAXP.
+   * @param value property value
+   * @param strategy strategy, may not be null
+   */
+  protected DocumentBuilderSetting(
+      String property,
+      boolean value,
+      DocumentBuilderSettingStrategy strategy) {
+    if (property == null) {
+      throw new NullPointerException("property");
+    }
+    this.property = property;
+    this.value = value;
+    this.strategy = strategy;
+  }
+
+  /**
+   * Returns true if the settings have a conflict or are identical.
+   *
+   * @param other
+   *            other setting, may not be null.
+   * @return true if this setting and the specified setting conflict
+   */
+  public final boolean hasConflict(DocumentBuilderSetting other) {
+    if (other == null) {
+      throw new NullPointerException("other");
+    }
+    if (other == this) {
+      return true;
+    }
+    return strategy.hasConflict(other.strategy);
+  }
+
+  /**
+   * Determines current value of setting.
+   * @param factory DOMTestDocumentBuilderFactory factory
+   * @return boolean true if property enabled.
+   */
+  public final boolean hasSetting(DOMDocumentBuilderFactory factory) {
+    return strategy.hasSetting(factory) == value;
+ }
+
+  /**
+   * Attempts to change builder to have this setting.
+   * @param factory DocumentBuilderFactory Factory for DOM builders
+   * @throws DOMTestIncompatibleException
+   *      if factory does not support the setting
+   */
+  public final void applySetting(DocumentBuilderFactory factory)  {
+    strategy.applySetting(factory, value);
+  }
+
+  /**
+   * Gets the property name.
+   * @return property name
+   */
+  public final String getProperty() {
+    return property;
+  }
+
+  /**
+   * Gets the property value.
+   * @return property value
+   */
+  public final boolean getValue() {
+    return value;
+  }
+
+  /**
+   * Gets a string representation of the setting.
+   * @return string representation
+   */
+  public final String toString() {
+    StringBuffer builder = new StringBuffer(property);
+    builder.append('=');
+    builder.append(String.valueOf(value));
+    return builder.toString();
+  }
+
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/DocumentBuilderSettingStrategy.java b/xml/src/test/java/tests/org/w3c/dom/DocumentBuilderSettingStrategy.java
new file mode 100644
index 0000000..77bbce8
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/DocumentBuilderSettingStrategy.java
@@ -0,0 +1,158 @@
+package tests.org.w3c.dom;
+
+import java.lang.reflect.Method;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+
+public abstract class DocumentBuilderSettingStrategy {
+    protected DocumentBuilderSettingStrategy() {
+    }
+
+    private static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
+
+    private static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";
+
+    public boolean hasConflict(DocumentBuilderSettingStrategy other) {
+        return (other == this);
+    }
+
+    public abstract void applySetting(DocumentBuilderFactory factory,
+            boolean value);
+
+    public abstract boolean hasSetting(DOMDocumentBuilderFactory factory);
+
+    public static final DocumentBuilderSettingStrategy coalescing = new DocumentBuilderSettingStrategy() {
+        public void applySetting(DocumentBuilderFactory factory,
+                boolean value) {
+            factory.setCoalescing(value);
+        }
+
+        public boolean hasSetting(DOMDocumentBuilderFactory factory) {
+            return factory.isCoalescing();
+        }
+
+    };
+
+    public static final DocumentBuilderSettingStrategy expandEntityReferences = new DocumentBuilderSettingStrategy() {
+        public void applySetting(DocumentBuilderFactory factory, boolean value) {
+            factory.setExpandEntityReferences(value);
+        }
+
+        public boolean hasSetting(DOMDocumentBuilderFactory factory) {
+            return factory.isExpandEntityReferences();
+        }
+    };
+
+    public static final DocumentBuilderSettingStrategy ignoringElementContentWhitespace = new DocumentBuilderSettingStrategy() {
+        public void applySetting(DocumentBuilderFactory factory, boolean value) {
+            factory.setIgnoringElementContentWhitespace(value);
+        }
+
+        public boolean hasSetting(DOMDocumentBuilderFactory factory) {
+            return factory.isIgnoringElementContentWhitespace();
+        }
+    };
+
+    public static final DocumentBuilderSettingStrategy ignoringComments = new DocumentBuilderSettingStrategy() {
+        public void applySetting(DocumentBuilderFactory factory, boolean value) {
+            if (value) {
+                System.out.println("ignoreComments=true not supported");
+            }
+        }
+
+        public boolean hasSetting(DOMDocumentBuilderFactory factory) {
+            return false;
+        }
+    };
+
+    public static final DocumentBuilderSettingStrategy namespaceAware = new DocumentBuilderSettingStrategy() {
+        public void applySetting(DocumentBuilderFactory factory, boolean value)
+                {
+            factory.setNamespaceAware(value);
+        }
+
+        public boolean hasSetting(DOMDocumentBuilderFactory factory) {
+            return factory.isNamespaceAware();
+        }
+    };
+
+    public static final DocumentBuilderSettingStrategy validating = new DocumentBuilderSettingStrategy() {
+        public void applySetting(DocumentBuilderFactory factory, boolean value)
+                {
+            factory.setValidating(value);
+        }
+
+        public boolean hasSetting(DOMDocumentBuilderFactory factory) {
+            return factory.isValidating();
+        }
+    };
+
+    public static final DocumentBuilderSettingStrategy signed = new DocumentBuilderSettingStrategy() {
+        public void applySetting(DocumentBuilderFactory factory, boolean value)
+                 {
+            if (!value) {
+                System.out.println("DocumentBuilderSetting.notSigned");
+            }
+        }
+
+        public boolean hasSetting(DOMDocumentBuilderFactory factory) {
+            return true;
+        }
+    };
+
+    public static final DocumentBuilderSettingStrategy hasNullString = new DocumentBuilderSettingStrategy() {
+        public void applySetting(DocumentBuilderFactory factory, boolean value)
+                 {
+            if (!value) {
+                System.out.println("DocumentBuilderSetting.notHasNullString");
+            }
+        }
+
+        public boolean hasSetting(DOMDocumentBuilderFactory factory) {
+            return true;
+        }
+    };
+
+    public static final DocumentBuilderSettingStrategy schemaValidating = new DocumentBuilderSettingStrategy() {
+        public void applySetting(DocumentBuilderFactory factory, boolean value)
+                 {
+            if (value) {
+                factory.setNamespaceAware(true);
+                factory.setValidating(true);
+                factory.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
+            } else {
+                factory.setAttribute(JAXP_SCHEMA_LANGUAGE,
+                        "http://www.w3.org/TR/REC-xml");
+            }
+        }
+
+        public boolean hasSetting(DOMDocumentBuilderFactory factory) {
+            try {
+                if (factory.isValidating()) {
+                    Method getAttrMethod = factory.getClass().getMethod(
+                            "getAttribute", new Class[] { String.class });
+                    String val = (String) getAttrMethod.invoke(factory,
+                            new Object[] { JAXP_SCHEMA_LANGUAGE });
+                    return W3C_XML_SCHEMA.equals(val);
+                }
+            } catch (Exception ex) {
+            }
+            return false;
+        }
+
+        //
+        // schema validating conflicts with namespaceAware
+        // and validating
+        //
+        public boolean hasConflict(DocumentBuilderSettingStrategy other) {
+            if (other == this
+                    || other == DocumentBuilderSettingStrategy.namespaceAware
+                    || other == DocumentBuilderSettingStrategy.validating) {
+                return true;
+            }
+            return false;
+        }
+
+    };
+
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/DocumentCreateAttributeNS.java b/xml/src/test/java/tests/org/w3c/dom/DocumentCreateAttributeNS.java
new file mode 100644
index 0000000..e46f3b3
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/DocumentCreateAttributeNS.java
@@ -0,0 +1,313 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.DOMImplementation;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The method createAttributeNS creates an attribute of the given qualified name
+ * and namespace URI
+ * 
+ * Invoke the createAttributeNS method on this Document object with a null
+ * namespaceURI, and a qualifiedName without a prefix. This should return a
+ * valid Attr node object.
+ * 
+ * @author IBM
+ * @author Neil Delima
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core">http://www.w3.org/TR/DOM-Level-2-Core/core</a>
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-DocCrAttrNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-DocCrAttrNS</a>
+ */
+@TestTargetClass(Document.class) 
+public final class DocumentCreateAttributeNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies positive functionality.",
+        method = "createAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateAttributeNS1() throws Throwable {
+        Document doc;
+        Attr attribute;
+        String namespaceURI = null;
+
+        String qualifiedName = "test";
+
+        String nodeName;
+        
+        doc = (Document) load("staffNS", builder);
+        attribute = doc.createAttributeNS(namespaceURI, qualifiedName);
+        nodeName = attribute.getNodeName();
+        
+        assertEquals("documentcreateattributeNS01", "test", nodeName);
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies positive functionality.",
+        method = "createAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateAttributeNS2() throws Throwable {
+        Document doc;
+        Attr attribute1;
+        Attr attribute2;
+        String name;
+        String nodeName;
+        String nodeValue;
+        String prefix;
+        String namespaceURI;
+        doc = (Document) load("staffNS", builder);
+        attribute1 = doc.createAttributeNS(
+                "http://www.w3.org/XML/1998/namespace", "xml:xml");
+        name = attribute1.getName();
+        nodeName = attribute1.getNodeName();
+        nodeValue = attribute1.getNodeValue();
+        prefix = attribute1.getPrefix();
+        namespaceURI = attribute1.getNamespaceURI();
+        assertEquals("documentcreateattributeNS02_att1_name", "xml:xml", name);
+        assertEquals("documentcreateattributeNS02_att1_nodeName", "xml:xml",
+                nodeName);
+        assertEquals("documentcreateattributeNS02_att1_nodeValue", "",
+                nodeValue);
+        assertEquals("documentcreateattributeNS02_att1_prefix", "xml", prefix);
+        assertEquals("documentcreateattributeNS02_att1_namespaceURI",
+                "http://www.w3.org/XML/1998/namespace", namespaceURI);
+        attribute2 = doc.createAttributeNS("http://www.w3.org/2000/xmlns/",
+                "xmlns");
+        name = attribute2.getName();
+        nodeName = attribute2.getNodeName();
+        nodeValue = attribute2.getNodeValue();
+        prefix = attribute2.getPrefix();
+        namespaceURI = attribute2.getNamespaceURI();
+        assertEquals("documentcreateattributeNS02_att2_name", "xmlns", name);
+        assertEquals("documentcreateattributeNS02_att2_nodeName", "xmlns",
+                nodeName);
+        assertEquals("documentcreateattributeNS02_att2_nodeValue", "",
+                nodeValue);
+        assertEquals("documentcreateattributeNS02_att2_namespaceURI",
+                "http://www.w3.org/2000/xmlns/", namespaceURI);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that createAttributeNS throws DOMException with INVALID_CHARACTER_ERR code.",
+        method = "createAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateAttributeNS3() throws Throwable {
+        Document doc;
+
+        String namespaceURI = "http://www.w3.org/DOM/Test/Level2";
+        String qualifiedName;
+        List<String> qualifiedNames = new ArrayList<String>();
+        qualifiedNames.add("/");
+        qualifiedNames.add("//");
+        qualifiedNames.add("\\");
+        qualifiedNames.add(";");
+        qualifiedNames.add("&");
+        qualifiedNames.add("*");
+        qualifiedNames.add("]]");
+        qualifiedNames.add(">");
+        qualifiedNames.add("<");
+
+        doc = (Document) load("staffNS", builder);
+        for (int indexN1005A = 0; indexN1005A < qualifiedNames.size(); indexN1005A++) {
+            qualifiedName = (String) qualifiedNames.get(indexN1005A);
+
+            {
+                boolean success = false;
+                try {
+                    doc.createAttributeNS(namespaceURI, qualifiedName);
+                } catch (DOMException ex) {
+                    success = (ex.code == DOMException.INVALID_CHARACTER_ERR);
+                }
+                assertTrue("documentcreateattributeNS03", success);
+            }
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that createAttributeNS throws DOMException with NAMESPACE_ERR code.",
+        method = "createAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateAttributeNS4() throws Throwable {
+        Document doc;
+
+        String namespaceURI = "http://www.w3.org/DOM/Test/Level2";
+        String qualifiedName;
+        List<String> qualifiedNames = new ArrayList<String>();
+        qualifiedNames.add("_:");
+        qualifiedNames.add(":0a");
+        qualifiedNames.add(":");
+        qualifiedNames.add("a:b:c");
+        qualifiedNames.add("_::a");
+
+        doc = (Document) load("staffNS", builder);
+        for (int indexN1004E = 0; indexN1004E < qualifiedNames.size(); indexN1004E++) {
+            qualifiedName = (String) qualifiedNames.get(indexN1004E);
+
+            {
+                boolean success = false;
+                try {
+                    doc.createAttributeNS(namespaceURI, qualifiedName);
+                } catch (DOMException ex) {
+                    success = (ex.code == DOMException.NAMESPACE_ERR);
+                }
+                assertTrue("documentcreateattributeNS04", success);
+            }
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that createAttributeNS throws DOMException with NAMESPACE_ERR code.",
+        method = "createAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateAttributeNS5() throws Throwable {
+        Document doc;
+        Document newDoc;
+        DocumentType docType = null;
+
+        DOMImplementation domImpl;
+
+        String namespaceURI = null;
+
+        String qualifiedName = "abc:def";
+        doc = (Document) load("staffNS", builder);
+        domImpl = doc.getImplementation();
+        newDoc = domImpl.createDocument("http://www.w3.org/DOM/Test",
+                "dom:doc", docType);
+
+        {
+            boolean success = false;
+            try {
+                newDoc.createAttributeNS(namespaceURI, qualifiedName);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("documentcreateattributeNS05", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that createAttributeNS throws DOMException with NAMESPACE_ERR code.",
+        method = "createElementNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateAttributeNS6() throws Throwable {
+        Document doc;
+        Document newDoc;
+        DocumentType docType = null;
+
+        DOMImplementation domImpl;
+
+        String namespaceURI = "http://www.w3.org/XML/1998 /namespace";
+        String qualifiedName = "xml:root";
+        doc = (Document) load("staffNS", builder);
+        domImpl = doc.getImplementation();
+        newDoc = domImpl.createDocument("http://www.w3.org/DOM/Test",
+                "dom:doc", docType);
+
+        {
+            boolean success = false;
+            try {
+                newDoc.createAttributeNS(namespaceURI, qualifiedName);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("documentcreateattributeNS06", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that createAttributeNS throws DOMException with NAMESPACE_ERR code.",
+        method = "createAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateAttributeNS7() throws Throwable {
+        Document doc;
+
+        String namespaceURI = "http://www.W3.org/2000/xmlns";
+        String qualifiedName = "xmlns";
+        doc = (Document) load("staffNS", builder);
+
+        {
+            boolean success = false;
+            try {
+                doc.createAttributeNS(namespaceURI, qualifiedName);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("documentcreateattributeNS07", success);
+        }
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/DocumentCreateElementNS.java b/xml/src/test/java/tests/org/w3c/dom/DocumentCreateElementNS.java
new file mode 100644
index 0000000..85f2fff
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/DocumentCreateElementNS.java
@@ -0,0 +1,169 @@
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.DOMImplementation;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The method createElementNS creates an element of the given valid
+ * qualifiedName and NamespaceURI.
+ * 
+ * Invoke the createElementNS method on this Document object with a valid
+ * namespaceURI and qualifiedName. Check if a valid Element object is returned
+ * with the same node attributes.
+ * 
+ * @author IBM
+ * @author Neil Delima
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core">http://www.w3.org/TR/DOM-Level-2-Core/core</a>
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-DocCrElNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-DocCrElNS</a>
+ */
+@TestTargetClass(Document.class) 
+public final class DocumentCreateElementNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies positive functionality.",
+        method = "createElementNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateElementNS1() throws Throwable {
+        Document doc;
+        Element element;
+        String namespaceURI = "http://www.w3.org/DOM/Test/level2";
+        String qualifiedName = "XML:XML";
+        String nodeName;
+        String nsURI;
+        String localName;
+        String prefix;
+        String tagName;
+        doc = (Document) load("staffNS", builder);
+        element = doc.createElementNS(namespaceURI, qualifiedName);
+        nodeName = element.getNodeName();
+        nsURI = element.getNamespaceURI();
+        localName = element.getLocalName();
+        prefix = element.getPrefix();
+        tagName = element.getTagName();
+        assertEquals("documentcreateelementNS01_nodeName", "XML:XML", nodeName);
+        assertEquals("documentcreateelementNS01_namespaceURI",
+                "http://www.w3.org/DOM/Test/level2", nsURI);
+        assertEquals("documentcreateelementNS01_localName", "XML", localName);
+        assertEquals("documentcreateelementNS01_prefix", "XML", prefix);
+        assertEquals("documentcreateelementNS01_tagName", "XML:XML", tagName);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that createElementNS throws DOMException with INVALID_CHARACTER_ERR code.",
+        method = "createElementNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateElementNS2() throws Throwable {
+        Document doc;
+        
+        String namespaceURI = null;
+
+        String qualifiedName = "^^";
+        doc = (Document) load("staffNS", builder);
+
+        {
+            boolean success = false;
+            try {
+                doc.createElementNS(namespaceURI, qualifiedName);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.INVALID_CHARACTER_ERR);
+            }
+            assertTrue("documentcreateelementNS02", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that createElementNS throws DOMException with NAMESPACE_ERR code.",
+        method = "createElementNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateElementNS5() throws Throwable {
+        Document doc;
+        
+        String namespaceURI = null;
+
+        String qualifiedName = "null:xml";
+        doc = (Document) load("staffNS", builder);
+
+        {
+            boolean success = false;
+            try {
+                doc.createElementNS(namespaceURI, qualifiedName);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("documentcreateelementNS05", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that createElementNS throws DOMException with NAMESPACE_ERR code.",
+        method = "createElementNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testCreateElementNS6() throws Throwable {
+        Document doc;
+        Document newDoc;
+        DocumentType docType = null;
+
+        DOMImplementation domImpl;
+        
+        String namespaceURI = "http://www.w3.org/xml/1998/namespace ";
+        String qualifiedName = "xml:root";
+        doc = (Document) load("staffNS", builder);
+        domImpl = doc.getImplementation();
+        newDoc = domImpl.createDocument("http://www.w3.org/DOM/Test",
+                "dom:doc", docType);
+
+        {
+            boolean success = false;
+            try {
+                newDoc.createElementNS(namespaceURI, qualifiedName);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("documentcreateelementNS06", success);
+        }
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/DocumentGetElementsByTagnameNS.java b/xml/src/test/java/tests/org/w3c/dom/DocumentGetElementsByTagnameNS.java
new file mode 100644
index 0000000..390bf11
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/DocumentGetElementsByTagnameNS.java
@@ -0,0 +1,150 @@
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Element;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The method getElementsByTagNameNS returns a NodeList of all the Elements with
+ * a given local name and namespace URI in the order in which they are
+ * encountered in a preorder traversal of the Document tree.
+ * 
+ * Invoke the getElementsByTagNameNS method on a new Document object with the
+ * values of namespaceURI=* and localName=*. This should return a nodeList of 1
+ * item.
+ * 
+ * @author IBM
+ * @author Neil Delima
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core">http://www.w3.org/TR/DOM-Level-2-Core/core</a>
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-getElBTNNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-getElBTNNS</a>
+ * @see <a
+ *      href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=259">http://www.w3.org/Bugs/Public/show_bug.cgi?id=259</a>
+ */
+@TestTargetClass(Document.class) 
+public final class DocumentGetElementsByTagnameNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies '*' as parameters.",
+        method = "getElementsByTagNameNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetElementsByTagNameNS1() throws Throwable {
+        Document doc;
+        Document newDoc;
+        DocumentType docType = null;
+
+        DOMImplementation domImpl;
+        NodeList childList;
+        String nullNS = null;
+
+        doc = (Document) load("staffNS", builder);
+        domImpl = doc.getImplementation();
+        newDoc = domImpl.createDocument(nullNS, "root", docType);
+        childList = newDoc.getElementsByTagNameNS("*", "*");
+        assertEquals("documentgetelementsbytagnameNS01", 1, childList
+                .getLength());
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies '*' as the first parameter.",
+        method = "getElementsByTagNameNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetElementsByTagNameNS2() throws Throwable {
+        Document doc;
+        Element docElem;
+        Element element;
+        NodeList childList;
+        
+        doc = (Document) load("staffNS", builder);
+        docElem = doc.getDocumentElement();
+        element = doc.createElementNS("test", "employeeId");
+        docElem.appendChild(element);
+        childList = doc.getElementsByTagNameNS("*", "employeeId");
+        assertEquals("documentgetelementsbytagnameNS02", 6, childList
+                .getLength());
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies wrong namespaceURI as a parameter.",
+        method = "getElementsByTagNameNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetElementsByTagNameNS3() throws Throwable {
+        Document doc;
+        NodeList childList;
+        doc = (Document) load("staffNS", builder);
+        childList = doc.getElementsByTagNameNS("**", "*");
+        assertEquals("documentgetelementsbytagnameNS03", 0, childList
+                .getLength());
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies positive functionality.",
+        method = "getElementsByTagNameNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetElementsByTagNameNS4() throws Throwable {
+        Document doc;
+        NodeList childList;
+        String nullNS = null;
+
+        doc = (Document) load("staffNS", builder);
+        childList = doc.getElementsByTagNameNS(nullNS, "0");
+        assertEquals("documentgetelementsbytagnameNS04", 0, childList
+                .getLength());
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies positive functionality.",
+        method = "getElementsByTagNameNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetElementsByTagNameNS5() throws Throwable {
+        Document doc;
+        NodeList childList;
+        doc = (Document) load("staffNS", builder);
+        childList = doc.getElementsByTagNameNS("null", "elementId");
+        assertEquals("documentgetelementsbytagnameNS05", 0, childList
+                .getLength());
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/DocumentGeteEementById.java b/xml/src/test/java/tests/org/w3c/dom/DocumentGeteEementById.java
new file mode 100644
index 0000000..7c82ac7
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/DocumentGeteEementById.java
@@ -0,0 +1,72 @@
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The method getElementById returns the element whose ID is given by elementId.
+ * If not such element exists, returns null.
+ * 
+ * Invoke the getElementById method on this Document object with an invalid
+ * elementId. This should return a null element.
+ * 
+ * @author IBM
+ * @author Neil Delima
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core">http://www.w3.org/TR/DOM-Level-2-Core/core</a>
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-getElBId">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-getElBId</a>
+ */
+@TestTargetClass(Document.class) 
+public final class DocumentGeteEementById extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify getElementById method for existent element.",
+        method = "getElementById",
+        args = {java.lang.String.class}
+    )
+    public void testGetElementById() throws Throwable {
+        Document doc;
+        Element element;
+        String elementId = "---";
+        doc = (Document) load("staffNS", builder);
+        element = doc.getElementById(elementId);
+        assertNull("documentgetelementbyid01", element);
+    }
+
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/DocumentImportNode.java b/xml/src/test/java/tests/org/w3c/dom/DocumentImportNode.java
new file mode 100644
index 0000000..426a0ad
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/DocumentImportNode.java
@@ -0,0 +1,699 @@
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Attr;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.ProcessingInstruction;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The importNode method imports a node from another document to this document.
+ * The returned node has no parent; (parentNode is null). The source node is not
+ * altered or removed from the original document but a new copy of the source
+ * node is created.
+ * 
+ * Using the method importNode with deep=true, import the attribute, "street" of
+ * the second element node, from a list of nodes whose local names are "address"
+ * and namespaceURI "http://www.nist.gov" into the same document. Check the
+ * parentNode, nodeName, nodeType and nodeValue of the imported node to verify
+ * if it has been imported correctly.
+ * 
+ * @author IBM
+ * @author Neil Delima
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core">http://www.w3.org/TR/DOM-Level-2-Core/core</a>
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#Core-Document-importNode">http://www.w3.org/TR/DOM-Level-2-Core/core#Core-Document-importNode</a>
+ */
+@TestTargetClass(Document.class) 
+public final class DocumentImportNode extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+// Assumes validation.
+//    public void testImportNode1() throws Throwable {
+//        Document doc;
+//        Element element;
+//        Attr attr;
+//        NodeList childList;
+//        Node importedAttr;
+//        String nodeName;
+//        int nodeType;
+//        String nodeValue;
+//        doc = (Document) load("staffNS", builder);
+//        childList = doc
+//                .getElementsByTagNameNS("http://www.nist.gov", "address");
+//        element = (Element) childList.item(1);
+//        attr = element.getAttributeNode("street");
+//        importedAttr = doc.importNode(attr, false);
+//        nodeName = importedAttr.getNodeName();
+//        nodeValue = importedAttr.getNodeValue();
+//        nodeType = (int) importedAttr.getNodeType();
+//        assertEquals("documentimportnode01_nodeName", "street", nodeName);
+//        assertEquals("documentimportnode01_nodeType", 2, nodeType);
+//        assertEquals("documentimportnode01_nodeValue", "Yes", nodeValue);
+//    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException exception.",
+        method = "importNode",
+        args = {org.w3c.dom.Node.class, boolean.class}
+    )
+    public void testImportNode2() throws Throwable {
+        Document doc;
+        Document docImported;
+        Element element;
+        Attr attr;
+        Node importedAttr;
+        String nodeName;
+        int nodeType;
+        String nodeValue;
+        NodeList addresses;
+        Node attrsParent;
+        doc = (Document) load("staffNS", builder);
+        docImported = (Document) load("staff", builder);
+        addresses = doc
+                .getElementsByTagNameNS("http://www.nist.gov", "address");
+        element = (Element) addresses.item(1);
+        attr = element.getAttributeNodeNS("http://www.nist.gov", "zone");
+        importedAttr = docImported.importNode(attr, false);
+        nodeName = importedAttr.getNodeName();
+        nodeType = (int) importedAttr.getNodeType();
+        nodeValue = importedAttr.getNodeValue();
+        attrsParent = importedAttr.getParentNode();
+        assertNull("documentimportnode02_parentNull", attrsParent);
+        assertEquals("documentimportnode02_nodeName", "emp:zone", nodeName);
+        assertEquals("documentimportnode02_nodeType", 2, nodeType);
+        assertEquals("documentimportnode02_nodeValue", "CANADA", nodeValue);
+    }
+
+// Assumes validation.
+//    public void testImportNode3() throws Throwable {
+//        Document doc;
+//        Element element;
+//        Attr attr;
+//        NodeList childList;
+//        Node importedAttr;
+//        String nodeName;
+//        int nodeType;
+//        String nodeValue;
+//        doc = (Document) load("staffNS", builder);
+//        childList = doc.getElementsByTagNameNS("http://www.nist.gov",
+//                "employee");
+//        element = (Element) childList.item(1);
+//        attr = element.getAttributeNode("defaultAttr");
+//        importedAttr = doc.importNode(attr, false);
+//        nodeName = importedAttr.getNodeName();
+//        nodeValue = importedAttr.getNodeValue();
+//        nodeType = (int) importedAttr.getNodeType();
+//        assertEquals("documentimportnode03_nodeName", "defaultAttr", nodeName);
+//        assertEquals("documentimportnode03_nodeType", 2, nodeType);
+//        assertEquals("documentimportnode03_nodeValue", "defaultVal", nodeValue);
+//    }
+
+// Assumes validation.
+//    public void testImportNode4() throws Throwable {
+//        Document doc;
+//        Document newDoc;
+//        DocumentType docType = null;
+//
+//        DOMImplementation domImpl;
+//        Element element;
+//        Attr attr;
+//        NodeList childList;
+//        Node importedAttr;
+//        String nodeName;
+//        int nodeType;
+//        String nodeValue;
+//        doc = (Document) load("staffNS", builder);
+//        domImpl = doc.getImplementation();
+//        newDoc = domImpl.createDocument("http://www.w3.org/DOM/Test",
+//                "l2:root", docType);
+//        childList = doc.getElementsByTagNameNS("http://www.nist.gov",
+//                "employee");
+//        element = (Element) childList.item(1);
+//        attr = element.getAttributeNode("defaultAttr");
+//        importedAttr = newDoc.importNode(attr, true);
+//        nodeName = importedAttr.getNodeName();
+//        nodeValue = importedAttr.getNodeValue();
+//        nodeType = (int) importedAttr.getNodeType();
+//        assertEquals("documentimportnode04_nodeName", "defaultAttr", nodeName);
+//        assertEquals("documentimportnode04_nodeType", 2, nodeType);
+//        assertEquals("documentimportnode04_nodeValue", "defaultVal", nodeValue);
+//    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException exception.",
+        method = "importNode",
+        args = {org.w3c.dom.Node.class, boolean.class}
+    )
+    public void testImportNode5() throws Throwable {
+        Document doc;
+        Document docImported;
+        Attr attr;
+        Node importedAttr;
+        String nodeName;
+        int nodeType;
+        String nodeValue;
+        String namespaceURI;
+        doc = (Document) load("staffNS", builder);
+        docImported = (Document) load("staff", builder);
+        attr = doc.createAttributeNS("http://www.w3.org/DOM/Test", "a_:b0");
+        importedAttr = docImported.importNode(attr, false);
+        nodeName = importedAttr.getNodeName();
+        nodeValue = importedAttr.getNodeValue();
+        nodeType = (int) importedAttr.getNodeType();
+        namespaceURI = importedAttr.getNamespaceURI();
+        assertEquals("documentimportnode05_nodeName", "a_:b0", nodeName);
+        assertEquals("documentimportnode05_nodeType", 2, nodeType);
+        assertEquals("documentimportnode05_nodeValue", "", nodeValue);
+        assertEquals("documentimportnode05_namespaceURI",
+                "http://www.w3.org/DOM/Test", namespaceURI);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that importNode method throws DOMException with NOT_SUPPORTED_ERR code.",
+        method = "importNode",
+        args = {org.w3c.dom.Node.class, boolean.class}
+    )
+    public void testImportNode6() throws Throwable {
+        Document doc;
+        
+        doc = (Document) load("staffNS", builder);
+
+        {
+            boolean success = false;
+            try {
+                doc.importNode(doc, false);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NOT_SUPPORTED_ERR);
+            }
+            assertTrue("throw_NOT_SUPPORTED_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that importNode method throws DOMException with NOT_SUPPORTED_ERR code.",
+        method = "importNode",
+        args = {org.w3c.dom.Node.class, boolean.class}
+    )
+    public void testImportNode7() throws Throwable {
+        Document doc;
+        
+        DocumentType docType;
+        doc = (Document) load("staffNS", builder);
+        docType = doc.getDoctype();
+
+        {
+            boolean success = false;
+            try {
+                doc.importNode(docType, true);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NOT_SUPPORTED_ERR);
+            }
+            assertTrue("throw_NOT_SUPPORTED_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that importNode method throws DOMException with NOT_SUPPORTED_ERR code.",
+        method = "importNode",
+        args = {org.w3c.dom.Node.class, boolean.class}
+    )
+    public void testImportNode8() throws Throwable {
+        Document doc;
+        
+        DocumentType docType;
+        DOMImplementation domImpl;
+        String nullNS = null;
+
+        doc = (Document) load("staffNS", builder);
+        domImpl = doc.getImplementation();
+        docType = domImpl.createDocumentType("test:root", nullNS, nullNS);
+
+        {
+            boolean success = false;
+            try {
+                doc.importNode(docType, true);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NOT_SUPPORTED_ERR);
+            }
+            assertTrue("throw_NOT_SUPPORTED_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException exception.",
+        method = "importNode",
+        args = {org.w3c.dom.Node.class, boolean.class}
+    )
+    public void testImportNode9() throws Throwable {
+        Document doc;
+        DocumentFragment docFragment;
+        NodeList childList;
+        boolean success;
+        Node addressNode;
+        
+        Node importedDocFrag;
+        doc = (Document) load("staffNS", builder);
+        docFragment = doc.createDocumentFragment();
+        childList = doc.getElementsByTagNameNS("*", "address");
+        addressNode = childList.item(0);
+        docFragment.appendChild(addressNode);
+        importedDocFrag = doc.importNode(docFragment, false);
+        success = importedDocFrag.hasChildNodes();
+        assertFalse("documentimportnode09", success);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies positive functionality; doesn't verify DOMException exceptions.",
+        method = "importNode",
+        args = {org.w3c.dom.Node.class, boolean.class}
+    )
+    public void testImportNode10() throws Throwable {
+        Document doc;
+        DocumentFragment docFragment;
+        NodeList childList;
+        boolean success;
+        Node addressNode;
+        
+        Node importedDocFrag;
+        doc = (Document) load("staffNS", builder);
+        docFragment = doc.createDocumentFragment();
+        childList = doc.getElementsByTagNameNS("*", "address");
+        addressNode = childList.item(0);
+        docFragment.appendChild(addressNode);
+        importedDocFrag = doc.importNode(docFragment, true);
+        success = importedDocFrag.hasChildNodes();
+        assertTrue("documentimportnode10", success);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException exception.",
+        method = "importNode",
+        args = {org.w3c.dom.Node.class, boolean.class}
+    )
+    public void testImportNode11() throws Throwable {
+        Document doc;
+        Element docElement;
+        Node imported;
+        boolean success;
+        String nodeNameOrig;
+        String nodeNameImported;
+        doc = (Document) load("staffNS", builder);
+        docElement = doc.getDocumentElement();
+        imported = doc.importNode(docElement, false);
+        success = imported.hasChildNodes();
+        assertFalse("documentimportnode11", success);
+        nodeNameImported = imported.getNodeName();
+        nodeNameOrig = docElement.getNodeName();
+        assertEquals("documentimportnode11_NodeName", nodeNameImported,
+                nodeNameOrig);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException exception.",
+        method = "importNode",
+        args = {org.w3c.dom.Node.class, boolean.class}
+    )
+    public void testImportNode12() throws Throwable {
+        Document doc;
+        NodeList childList;
+        Node imported;
+        Node addressElem;
+        NodeList addressElemChildren;
+        NodeList importedChildren;
+        int addressElemLen;
+        int importedLen;
+        doc = (Document) load("staffNS", builder);
+        childList = doc.getElementsByTagNameNS("*", "address");
+        addressElem = childList.item(0);
+        imported = doc.importNode(addressElem, true);
+        addressElemChildren = addressElem.getChildNodes();
+        importedChildren = imported.getChildNodes();
+        addressElemLen = (int) addressElemChildren.getLength();
+        importedLen = (int) importedChildren.getLength();
+        assertEquals("documentimportnode12", importedLen, addressElemLen);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException exception.",
+        method = "importNode",
+        args = {org.w3c.dom.Node.class, boolean.class}
+    )
+    public void testImportNode13() throws Throwable {
+        Document doc;
+        NodeList childList;
+        Node imported;
+        NodeList importedList;
+        Node employeeElem;
+        int importedLen;
+        doc = (Document) load("staffNS", builder);
+        childList = doc.getElementsByTagNameNS("*", "employee");
+        employeeElem = childList.item(0);
+        imported = doc.importNode(employeeElem, false);
+        importedList = imported.getChildNodes();
+        importedLen = (int) importedList.getLength();
+        assertEquals("documentimportnode13", 0, importedLen);
+    }
+
+// Assumes validation.
+//    public void testImportNode14() throws Throwable {
+//        Document doc;
+//        Document newDoc;
+//        DOMImplementation domImpl;
+//        DocumentType nullDocType = null;
+//
+//        NodeList childList;
+//        Node imported;
+//        Node employeeElem;
+//        Attr attrNode;
+//        String attrValue;
+//        String nullNS = null;
+//
+//        doc = (Document) load("staffNS", builder);
+//        childList = doc.getElementsByTagNameNS("*", "employee");
+//        employeeElem = childList.item(3);
+//        domImpl = builder.getDOMImplementation();
+//        newDoc = domImpl.createDocument(nullNS, "staff", nullDocType);
+//        imported = newDoc.importNode(employeeElem, true);
+//        attrNode = ((Element) /* Node */imported).getAttributeNodeNS(nullNS,
+//                "defaultAttr");
+//        assertNull("defaultAttrNotImported", attrNode);
+//        attrValue = ((Element) /* Node */imported).getAttributeNS(
+//                "http://www.w3.org/2000/xmlns/", "emp");
+//        assertEquals("explicitAttrImported", "http://www.nist.gov", attrValue);
+//    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies import of TEXT_NODE.",
+        method = "importNode",
+        args = {org.w3c.dom.Node.class, boolean.class}
+    )
+    public void testImportNode15() throws Throwable {
+        Document doc;
+        
+        Node textImport;
+        Node textToImport;
+        String nodeValue;
+        doc = (Document) load("staffNS", builder);
+        
+        textToImport = doc
+                .createTextNode("Document.importNode test for a TEXT_NODE");
+        textImport = doc.importNode(textToImport, true);
+        nodeValue = textImport.getNodeValue();
+        assertEquals("documentimportnode15",
+                "Document.importNode test for a TEXT_NODE", nodeValue);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies import of COMMENT_NODE",
+        method = "importNode",
+        args = {org.w3c.dom.Node.class, boolean.class}
+    )
+    public void testImportNode17() throws Throwable {
+        Document doc;
+        
+        Node commentImport;
+        Node commentToImport;
+        String nodeValue;
+        doc = (Document) load("staffNS", builder);
+        
+        commentToImport = doc
+                .createComment("Document.importNode test for a COMMENT_NODE");
+        commentImport = doc.importNode(commentToImport, true);
+        nodeValue = commentImport.getNodeValue();
+        assertEquals("documentimportnode17",
+                "Document.importNode test for a COMMENT_NODE", nodeValue);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException exception.",
+        method = "importNode",
+        args = {org.w3c.dom.Node.class, boolean.class}
+    )
+    public void testImportNode18() throws Throwable {
+        Document doc;
+        
+        ProcessingInstruction piImport;
+        ProcessingInstruction piToImport;
+        String piData;
+        String piTarget;
+        doc = (Document) load("staffNS", builder);
+        
+        piToImport = doc.createProcessingInstruction("Target", "Data");
+        piImport = (ProcessingInstruction) doc.importNode(piToImport, false);
+        piTarget = piImport.getTarget();
+        piData = piImport.getData();
+        assertEquals("documentimportnode18_Target", "Target", piTarget);
+        assertEquals("documentimportnode18_Data", "Data", piData);
+    }
+
+// Assumes validation.
+//    public void testImportNode19() throws Throwable {
+//        Document doc;
+//        DocumentType docTypeNull = null;
+//
+//        Document docImp;
+//        DOMImplementation domImpl;
+//        DocumentType docType;
+//        NamedNodeMap nodeMap;
+//        Entity entity2;
+//        Entity entity6;
+//        Entity entityImp2;
+//        Entity entityImp6;
+//        String nodeName;
+//        String systemId;
+//        String notationName;
+//        String nodeNameImp;
+//        String systemIdImp;
+//        String notationNameImp;
+//        doc = (Document) load("staffNS", builder);
+//        domImpl = doc.getImplementation();
+//        docType = doc.getDoctype();
+//        docImp = domImpl.createDocument("http://www.w3.org/DOM/Test", "a:b",
+//                docTypeNull);
+//        nodeMap = docType.getEntities();
+//        assertNotNull("entitiesNotNull", nodeMap);
+//        entity2 = (Entity) nodeMap.getNamedItem("ent2");
+//        entity6 = (Entity) nodeMap.getNamedItem("ent6");
+//        entityImp2 = (Entity) docImp.importNode(entity2, false);
+//        entityImp6 = (Entity) docImp.importNode(entity6, true);
+//        nodeName = entity2.getNodeName();
+//        nodeNameImp = entityImp2.getNodeName();
+//        assertEquals("documentimportnode19_Ent2NodeName", nodeName, nodeNameImp);
+//        nodeName = entity6.getNodeName();
+//        nodeNameImp = entityImp6.getNodeName();
+//        assertEquals("documentimportnode19_Ent6NodeName", nodeName, nodeNameImp);
+//        systemId = entity2.getSystemId();
+//        systemIdImp = entityImp2.getSystemId();
+//        assertEquals("documentimportnode19_Ent2SystemId", systemId, systemIdImp);
+//        systemId = entity6.getSystemId();
+//        systemIdImp = entityImp6.getSystemId();
+//        assertEquals("documentimportnode19_Ent6SystemId", systemId, systemIdImp);
+//        notationName = entity2.getNotationName();
+//        notationNameImp = entityImp2.getNotationName();
+//        assertEquals("documentimportnode19_Ent2NotationName", notationName,
+//                notationNameImp);
+//        notationName = entity6.getNotationName();
+//        notationNameImp = entityImp6.getNotationName();
+//        assertEquals("documentimportnode19_Ent6NotationName", notationName,
+//                notationNameImp);
+//    }
+
+// Assumes validation.
+//    public void testImportNode20() throws Throwable {
+//        Document doc;
+//        Document docImp;
+//        DOMImplementation domImpl;
+//        DocumentType docType;
+//        DocumentType docTypeNull = null;
+//
+//        NamedNodeMap nodeMap;
+//        Entity entity4;
+//        Entity entityImp4;
+//        Element element;
+//        CharacterData cdata;
+//        ProcessingInstruction pi;
+//        NodeList childList;
+//        NodeList elemchildList;
+//        String ent4Name;
+//        String ent4ImpName;
+//        String cdataVal;
+//        String piTargetVal;
+//        String piDataVal;
+//        doc = (Document) load("staffNS", builder);
+//        domImpl = doc.getImplementation();
+//        docType = doc.getDoctype();
+//        docImp = domImpl.createDocument("http://www.w3.org/DOM/Test", "a:b",
+//                docTypeNull);
+//        nodeMap = docType.getEntities();
+//        entity4 = (Entity) nodeMap.getNamedItem("ent4");
+//        entityImp4 = (Entity) docImp.importNode(entity4, true);
+//        childList = entityImp4.getChildNodes();
+//        element = (Element) childList.item(0);
+//        elemchildList = element.getChildNodes();
+//        cdata = (CharacterData) elemchildList.item(0);
+//        pi = (ProcessingInstruction) childList.item(1);
+//        ent4Name = entity4.getNodeName();
+//        ent4ImpName = entityImp4.getNodeName();
+//        cdataVal = cdata.getData();
+//        piTargetVal = pi.getTarget();
+//        piDataVal = pi.getData();
+//        assertEquals("documentimportnode20_Ent4NodeName", ent4Name, ent4ImpName);
+//        assertEquals("documentimportnode20_Cdata", "Element data", cdataVal);
+//        assertEquals("documentimportnode20_PITarget", "PItarget", piTargetVal);
+//        assertEquals("documentimportnode20_PIData", "PIdata", piDataVal);
+//    }
+
+// TODO Fails on JDK. Why?
+//    public void testImportNode21() throws Throwable {
+//        
+//        
+//        Document doc;
+//        DocumentType docTypeNull = null;
+//
+//        Document docImp;
+//        DOMImplementation domImpl;
+//        NodeList addressList;
+//        NodeList addressChildList;
+//        Element element;
+//        EntityReference entRef2;
+//        EntityReference entRefImp2;
+//        EntityReference entRef3;
+//        EntityReference entRefImp3;
+//        String nodeName2;
+//        String nodeName3;
+//        String nodeNameImp2;
+//        String nodeNameImp3;
+//        NodeList nodes;
+//        Node nodeImp3;
+//        Node nodeImp2;
+//        String nodeValueImp2;
+//        String nodeValueImp3;
+//        doc = (Document) load("staffNS", builder);
+//        domImpl = doc.getImplementation();
+//        docImp = domImpl.createDocument("http://www.w3.org/DOM/Test", "a:b",
+//                docTypeNull);
+//        addressList = doc.getElementsByTagName("address");
+//        element = (Element) addressList.item(1);
+//        addressChildList = element.getChildNodes();
+//        entRef2 = (EntityReference) addressChildList.item(0);
+//        entRef3 = (EntityReference) addressChildList.item(2);
+//        entRefImp2 = (EntityReference) docImp.importNode(entRef2, true);
+//        entRefImp3 = (EntityReference) docImp.importNode(entRef3, false);
+//        nodeName2 = entRef2.getNodeName();
+//        nodeName3 = entRef3.getNodeName();
+//        nodeNameImp2 = entRefImp2.getNodeName();
+//        nodeNameImp3 = entRefImp3.getNodeName();
+//        assertEquals("documentimportnode21_Ent2NodeName", nodeName2,
+//                nodeNameImp2);
+//        assertEquals("documentimportnode21_Ent3NodeName", nodeName3,
+//                nodeNameImp3);
+//        entRefImp2 = (EntityReference) doc.importNode(entRef2, true);
+//        entRefImp3 = (EntityReference) doc.importNode(entRef3, false);
+//        nodes = entRefImp2.getChildNodes();
+//        nodeImp2 = nodes.item(0);
+//        nodeValueImp2 = nodeImp2.getNodeValue();
+//        nodes = entRefImp3.getChildNodes();
+//        nodeImp3 = nodes.item(0);
+//        nodeValueImp3 = nodeImp3.getNodeValue();
+//        assertEquals("documentimportnode21_Ent2NodeValue", "1900 Dallas Road",
+//                nodeValueImp2);
+//        assertEquals("documentimportnode21_Ent3Nodevalue", "Texas",
+//                nodeValueImp3);
+//        
+//    }
+
+// Assumes validation.
+//    public void testImportNode22() throws Throwable {
+//        Document doc;
+//        DocumentType docTypeNull = null;
+//
+//        Document docImp;
+//        DOMImplementation domImpl;
+//        DocumentType docType;
+//        NamedNodeMap nodeMap;
+//        Notation notation1;
+//        Notation notation2;
+//        
+//        String publicId1;
+//        String publicId1Imp;
+//        String publicId1NewImp;
+//        String publicId2Imp;
+//        
+//        String systemId1Imp;
+//        String systemId1NewImp;
+//        String systemId2;
+//        String systemId2Imp;
+//        String systemId2NewImp;
+//        doc = (Document) load("staffNS", builder);
+//        domImpl = doc.getImplementation();
+//        docType = doc.getDoctype();
+//        docImp = domImpl.createDocument("http://www.w3.org/DOM/Test", "a:b",
+//                docTypeNull);
+//        nodeMap = docType.getNotations();
+//        assertNotNull("notationsNotNull", nodeMap);
+//        notation1 = (Notation) nodeMap.getNamedItem("notation1");
+//        notation2 = (Notation) nodeMap.getNamedItem("notation2");
+//        doc.importNode(notation1, true);
+//        doc.importNode(notation2, false);
+//        docImp.importNode(notation1, false);
+//        docImp.importNode(notation2, true);
+//        publicId1 = notation1.getPublicId();
+//        publicId1Imp = notation1.getPublicId();
+//        publicId1NewImp = notation1.getPublicId();
+//        systemId1Imp = notation1.getSystemId();
+//        systemId1NewImp = notation1.getSystemId();
+//        publicId2Imp = notation2.getPublicId();
+//        notation2.getPublicId();
+//        systemId2 = notation2.getSystemId();
+//        systemId2Imp = notation2.getSystemId();
+//        systemId2NewImp = notation2.getSystemId();
+//        assertEquals("documentimportnode22_N1PID", publicId1, publicId1Imp);
+//        assertEquals("documentimportnode22_N1NPID", publicId1, publicId1NewImp);
+//        assertNull("documentimportnode22_N1SID", systemId1Imp);
+//        assertNull("documentimportnode22_N1NSID", systemId1NewImp);
+//        assertEquals("documentimportnode22_N2SID", systemId2, systemId2Imp);
+//        assertEquals("documentimportnode22_N2NSID", systemId2, systemId2NewImp);
+//        assertNull("documentimportnode22_N2PID", publicId2Imp);
+//        assertNull("documentimportnode22_N2NPID", publicId2Imp);
+//    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/DocumentTypeInternalSubset.java b/xml/src/test/java/tests/org/w3c/dom/DocumentTypeInternalSubset.java
new file mode 100644
index 0000000..9e79788
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/DocumentTypeInternalSubset.java
@@ -0,0 +1,76 @@
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Document;
+import org.w3c.dom.DOMImplementation;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The method getInternalSubset() returns the internal subset as a string.
+ * 
+ * Create a new DocumentType node with null values for publicId and systemId.
+ * Verify that its internal subset is null.
+ * 
+ * @author IBM
+ * @author Neil Delima
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-Core-DocType-internalSubset">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-Core-DocType-internalSubset</a>
+ * @see <a
+ *      href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=259">http://www.w3.org/Bugs/Public/show_bug.cgi?id=259</a>
+ */
+@TestTargetClass(DocumentType.class) 
+public final class DocumentTypeInternalSubset extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't check positive case.",
+        method = "getInternalSubset",
+        args = {}
+    )
+    public void testGetInternalSubset() throws Throwable {
+        Document doc;
+        DocumentType docType;
+        DOMImplementation domImpl;
+        String internal;
+        String nullNS = null;
+
+        doc = (Document) load("staffNS", builder);
+        domImpl = doc.getImplementation();
+        docType = domImpl.createDocumentType("l2:root", nullNS, nullNS);
+        internal = docType.getInternalSubset();
+        assertNull("internalSubsetNull", internal);
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/DocumentTypePublicId.java b/xml/src/test/java/tests/org/w3c/dom/DocumentTypePublicId.java
new file mode 100644
index 0000000..26e9a5f
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/DocumentTypePublicId.java
@@ -0,0 +1,97 @@
+
+/*
+This Java source file was generated by test-to-java.xsl
+and is a derived work from the source document.
+The source document contained the following notice:
+
+
+
+Copyright (c) 2001-2003 World Wide Web Consortium, 
+(Massachusetts Institute of Technology, Institut National de
+Recherche en Informatique et en Automatique, Keio University).  All 
+Rights Reserved.  This program is distributed under the W3C's Software
+Intellectual Property License.  This program is distributed in the 
+hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+PURPOSE.  
+
+See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+*/
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.DOMImplementation;
+
+import javax.xml.parsers.DocumentBuilder;
+
+
+
+/**
+ *     The method getInternalSubset() returns the public identifier of the external subset.
+ *   
+ *     Create a new DocumentType node with the value "PUB" for its publicId.
+ *     Check the value of the publicId attribute using getPublicId().
+* @author IBM
+* @author Neil Delima
+* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-Core-DocType-publicId">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-Core-DocType-publicId</a>
+* @see <a href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=259">http://www.w3.org/Bugs/Public/show_bug.cgi?id=259</a>
+*/
+@TestTargetClass(DocumentType.class) 
+public final class DocumentTypePublicId extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+   /**
+    * Runs the test case.
+    * @throws Throwable Any uncaught exception causes test to fail
+    */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "getPublicId",
+        args = {}
+    )
+   public void testGetPublicId() throws Throwable {
+      Document doc;
+      DocumentType docType;
+      DOMImplementation domImpl;
+      String publicId;
+      String nullNS = null;
+
+      doc = (Document) load("staffNS", builder);
+      domImpl = doc.getImplementation();
+      docType = domImpl.createDocumentType("l2:root", "PUB", nullNS);
+      publicId = docType.getPublicId();
+      assertEquals("documenttypepublicid01", "PUB", publicId);
+      }
+   
+}
+
diff --git a/xml/src/test/java/tests/org/w3c/dom/DocumentTypeSystemId.java b/xml/src/test/java/tests/org/w3c/dom/DocumentTypeSystemId.java
new file mode 100644
index 0000000..fcad024
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/DocumentTypeSystemId.java
@@ -0,0 +1,95 @@
+
+/*
+This Java source file was generated by test-to-java.xsl
+and is a derived work from the source document.
+The source document contained the following notice:
+
+
+
+Copyright (c) 2001 World Wide Web Consortium, 
+(Massachusetts Institute of Technology, Institut National de
+Recherche en Informatique et en Automatique, Keio University).  All 
+Rights Reserved.  This program is distributed under the W3C's Software
+Intellectual Property License.  This program is distributed in the 
+hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+PURPOSE.  
+
+See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+*/
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Document;
+import org.w3c.dom.DOMImplementation;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ *     The method getInternalSubset() returns the public identifier of the external subset.
+ *   
+ *     Create a new DocumentType node with the value "SYS" for its systemId and PUB for
+ *     its publicId.  Check the value of the systemId and pbulicId attributes.
+* @author IBM
+* @author Neil Delima
+* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-Core-DocType-systemId">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-Core-DocType-systemId</a>
+*/
+@TestTargetClass(DocumentType.class) 
+public final class DocumentTypeSystemId extends DOMTestCase {
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+
+   /**
+    * Runs the test case.
+    * @throws Throwable Any uncaught exception causes test to fail
+    */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "getSystemId",
+        args = {}
+    )
+   public void testGetSystemId() throws Throwable {
+      Document doc;
+      DocumentType docType;
+      DOMImplementation domImpl;
+      String publicId;
+      String systemId;
+      doc = (Document) load("staffNS", builder);
+      domImpl = doc.getImplementation();
+      docType = domImpl.createDocumentType("l2:root", "PUB", "SYS");
+      publicId = docType.getPublicId();
+      systemId = docType.getSystemId();
+      assertEquals("documenttypepublicid01", "PUB", publicId);
+      assertEquals("documenttypesystemid01", "SYS", systemId);
+      }
+   
+}
+
diff --git a/xml/src/test/java/tests/org/w3c/dom/ElementGetAttributeNS.java b/xml/src/test/java/tests/org/w3c/dom/ElementGetAttributeNS.java
new file mode 100644
index 0000000..8505459
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/ElementGetAttributeNS.java
@@ -0,0 +1,89 @@
+
+/*
+This Java source file was generated by test-to-java.xsl
+and is a derived work from the source document.
+The source document contained the following notice:
+
+
+
+Copyright (c) 2001-2004 World Wide Web Consortium, 
+(Massachusetts Institute of Technology, Institut National de
+Recherche en Informatique et en Automatique, Keio University).  All 
+Rights Reserved.  This program is distributed under the W3C's Software
+Intellectual Property License.  This program is distributed in the 
+hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+PURPOSE.  
+
+See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+*/
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargetClass; 
+
+import javax.xml.parsers.DocumentBuilder;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+
+/**
+ *       The method getAttributeNS retrieves an attribute value by local name and namespace URI.  
+ *       Using the getAttributeNodeNS, retreive and verify the value of the default 
+ *       attribute node.
+ *     
+* @author IBM
+* @author Neil Delima
+* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElGetAttrNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElGetAttrNS</a>
+* @see <a href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=259">http://www.w3.org/Bugs/Public/show_bug.cgi?id=259</a>
+*/
+@TestTargetClass(Element.class) 
+public final class ElementGetAttributeNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+   /**
+    * Runs the test case.
+    * @throws Throwable Any uncaught exception causes test to fail
+    */
+// Assumes validation.
+//    public void testGetAttributeNS() throws Throwable {
+//        Document doc;
+//        Element element;
+//        String attrValue;
+//        NodeList childList;
+//        String nullNS = null;
+//
+//        doc = (Document) load("staffNS", builder);
+//        childList = doc.getElementsByTagNameNS("http://www.nist.gov",
+//                "employee");
+//        element = (Element) childList.item(1);
+//        attrValue = element.getAttributeNS(nullNS, "defaultAttr");
+//        assertEquals("elementgetattributens02", "defaultVal", attrValue);
+//    }
+   
+}
+
diff --git a/xml/src/test/java/tests/org/w3c/dom/ElementGetAttributeNodeNS.java b/xml/src/test/java/tests/org/w3c/dom/ElementGetAttributeNodeNS.java
new file mode 100644
index 0000000..7760ba8
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/ElementGetAttributeNodeNS.java
@@ -0,0 +1,139 @@
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+import org.w3c.dom.Attr;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The method getAttributeNodeNS retrieves an Attr node by local name and
+ * namespace URI. Create a new element node and add 2 new attribute nodes to it
+ * that have the same local name but different namespaceURIs and prefixes.
+ * Retrieve an attribute using namespace and localname and check its value, name
+ * and namespaceURI.
+ * 
+ * @author IBM
+ * @author Neil Delima
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElGetAtNodeNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElGetAtNodeNS</a>
+ */
+@TestTargetClass(Element.class) 
+public final class ElementGetAttributeNodeNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "getAttributeNodeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetAttributeNodeNS1() throws Throwable {
+        Document doc;
+        Element element;
+        Attr attribute1;
+        Attr attribute2;
+        
+        
+        Attr attribute;
+        String attrValue;
+        String attrName;
+        String attNodeName;
+        String attrLocalName;
+        String attrNS;
+        doc = (Document) load("staffNS", builder);
+        element = doc.createElementNS("namespaceURI", "root");
+        attribute1 = doc.createAttributeNS("http://www.w3.org/DOM/Level2",
+                "l2:att");
+        element.setAttributeNodeNS(attribute1);
+        attribute2 = doc.createAttributeNS("http://www.w3.org/DOM/Level1",
+                "att");
+        element.setAttributeNodeNS(attribute2);
+        attribute = element.getAttributeNodeNS("http://www.w3.org/DOM/Level2",
+                "att");
+        attrValue = attribute.getNodeValue();
+        attrName = attribute.getName();
+        attNodeName = attribute.getNodeName();
+        attrLocalName = attribute.getLocalName();
+        attrNS = attribute.getNamespaceURI();
+        assertEquals("elementgetattributenodens01_attrValue", "", attrValue);
+        assertEquals("elementgetattributenodens01_attrName", "l2:att", attrName);
+        assertEquals("elementgetattributenodens01_attrNodeName", "l2:att",
+                attNodeName);
+        assertEquals("elementgetattributenodens01_attrLocalName", "att",
+                attrLocalName);
+        assertEquals("elementgetattributenodens01_attrNs",
+                "http://www.w3.org/DOM/Level2", attrNS);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "getAttributeNodeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetAttributeNodeNS2() throws Throwable {
+        Document doc;
+        Element element;
+        Attr attribute;
+        
+        String attrValue;
+        doc = (Document) load("staffNS", builder);
+        element = doc.createElementNS("namespaceURI", "root");
+        attribute = doc.createAttributeNS("http://www.w3.org/DOM/Level2",
+                "l2:att");
+        element.setAttributeNodeNS(attribute);
+        attribute = element.getAttributeNodeNS("http://www.w3.org/DOM/Level2",
+                "att");
+        attrValue = attribute.getNodeValue();
+        assertEquals("elementgetattributenodens02", "", attrValue);
+    }
+
+// Assumes validation.
+//    public void testGetAttributeNodeNS3() throws Throwable {
+//        Document doc;
+//        Element element;
+//        Attr attribute;
+//        String attrValue;
+//        NodeList childList;
+//        String nullNS = null;
+//
+//        doc = (Document) load("staffNS", builder);
+//        childList = doc.getElementsByTagNameNS("http://www.nist.gov",
+//                "employee");
+//        element = (Element) childList.item(1);
+//        attribute = element.getAttributeNodeNS(nullNS, "defaultAttr");
+//        attrValue = attribute.getNodeValue();
+//        assertEquals("elementgetattributenodens03", "defaultVal", attrValue);
+//    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/ElementGetElementsByTagNameNS.java b/xml/src/test/java/tests/org/w3c/dom/ElementGetElementsByTagNameNS.java
new file mode 100644
index 0000000..f03007a
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/ElementGetElementsByTagNameNS.java
@@ -0,0 +1,122 @@
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The method getElementsByTagNameNS returns a NodeList of all the Elements with
+ * a given local name and namespace URI in the order in which they are
+ * encountered in a preorder traversal of the Document tree. Invoke
+ * getElementsByTagNameNS on the documentElement with values for namespaceURI
+ * '*' and localName '*'. Verify if this returns a nodeList of 0 elements.
+ * 
+ * @author IBM
+ * @author Neil Delima
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-getElBTNNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-getElBTNNS</a>
+ */
+@TestTargetClass(Element.class) 
+public final class ElementGetElementsByTagNameNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "getElementsByTagNameNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetElementsByTagNameNS1() throws Throwable {
+        Document doc;
+        Element element;
+        NodeList elementList;
+        doc = (Document) load("staffNS", builder);
+        element = doc.getDocumentElement();
+        elementList = element.getElementsByTagNameNS("**", "*");
+        assertEquals("elementgetelementsbytagnamens02", 0, elementList
+                .getLength());
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "getElementsByTagNameNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetElementsByTagNameNS4() throws Throwable {
+        Document doc;
+        Element element;
+        Element child1;
+        Element child2;
+        Element child3;
+        
+        NodeList elementList;
+        String nullNS = null;
+
+        doc = (Document) load("staffNS", builder);
+        element = doc.createElementNS("http://www.w3.org/DOM", "root");
+        child1 = doc.createElementNS("http://www.w3.org/DOM/Level1",
+                "dom:child");
+        child2 = doc.createElementNS(nullNS, "child");
+        child3 = doc.createElementNS("http://www.w3.org/DOM/Level2",
+                "dom:child");
+        element.appendChild(child1);
+        element.appendChild(child2);
+        element.appendChild(child3);
+        elementList = element.getElementsByTagNameNS(nullNS, "child");
+        assertEquals("elementgetelementsbytagnamens04_1", 1, elementList
+                .getLength());
+        elementList = element.getElementsByTagNameNS("*", "child");
+        assertEquals("elementgetelementsbytagnamens04_2", 3, elementList
+                .getLength());
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "getElementsByTagNameNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetElementsByTagNameNS5() throws Throwable {
+        Document doc;
+        Element element;
+        NodeList elementList;
+        doc = (Document) load("staffNS", builder);
+        element = doc.getDocumentElement();
+        elementList = element.getElementsByTagNameNS(
+                "http://www.altavista.com", "*");
+        assertEquals("elementgetelementsbytagnamens05", 1, elementList
+                .getLength());
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/ElementHasAttribute.java b/xml/src/test/java/tests/org/w3c/dom/ElementHasAttribute.java
new file mode 100644
index 0000000..711a1ab
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/ElementHasAttribute.java
@@ -0,0 +1,123 @@
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+import org.w3c.dom.Attr;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The method hasAttribute returns true when an attribute with a given name is
+ * specified on this element or has a default value, false otherwise Invoke the
+ * hasAttribute method to check if the documentElement has attributres.
+ * 
+ * @author IBM
+ * @author Neil Delima
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeHasAttrs">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeHasAttrs</a>
+ */
+@TestTargetClass(Element.class) 
+public final class ElementHasAttribute extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies hasAttribute method with empty string as a parameter.",
+        method = "hasAttribute",
+        args = {java.lang.String.class}
+    )
+    public void testHasAttribute1() throws Throwable {
+        Document doc;
+        Element element;
+        boolean state;
+        doc = (Document) load("staff", builder);
+        element = doc.getDocumentElement();
+        state = element.hasAttribute("");
+        assertFalse("elementhasattribute01", state);
+    }
+
+// Assumes validation.
+//    public void testHasAttribute2() throws Throwable {
+//        Document doc;
+//        Element element;
+//        boolean state;
+//        NodeList elementList;
+//        doc = (Document) load("staffNS", builder);
+//        elementList = doc.getElementsByTagName("emp:employee");
+//        element = (Element) elementList.item(0);
+//        assertNotNull("empEmployeeNotNull", element);
+//        state = element.hasAttribute("defaultAttr");
+//        assertTrue("elementhasattribute02", state);
+//    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies positive functionality.",
+        method = "hasAttribute",
+        args = {java.lang.String.class}
+    )
+    public void testHasAttribute3() throws Throwable {
+        Document doc;
+        Element element;
+        boolean state;
+        Attr attribute;
+        
+        doc = (Document) load("staff", builder);
+        element = doc.createElement("address");
+        attribute = doc.createAttribute("domestic");
+        state = element.hasAttribute("domestic");
+        assertFalse("elementhasattribute03_False", state);
+        element.setAttributeNode(attribute);
+        state = element.hasAttribute("domestic");
+        assertTrue("elementhasattribute03_True", state);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies positive functionality.",
+        method = "hasAttribute",
+        args = {java.lang.String.class}
+    )
+    public void testHasAttribute4() throws Throwable {
+        Document doc;
+        Element element;
+        boolean state;
+        Attr attribute;
+        
+        doc = (Document) load("staff", builder);
+        element = doc.createElement("address");
+        attribute = doc.createAttribute("domestic");
+        element.setAttributeNode(attribute);
+        state = element.hasAttribute("domestic");
+        assertTrue("elementhasattribute04", state);
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/ElementHasAttributeNS.java b/xml/src/test/java/tests/org/w3c/dom/ElementHasAttributeNS.java
new file mode 100644
index 0000000..e0c9fd9
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/ElementHasAttributeNS.java
@@ -0,0 +1,139 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Attr;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The method hasAttributeNS returns true when an attribute with a given local
+ * name and namespace URI is specified on this element or has a default value,
+ * false otherwise.
+ * 
+ * Retreive the first employee element node. Invoke the hasAttributeNS method to
+ * check if it has the xmlns attribute that belongs to the namespace
+ * http://www.w3.org/2000/xmlns/.
+ * 
+ * @author IBM
+ * @author Neil Delima
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElHasAttrNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElHasAttrNS</a>
+ */
+@TestTargetClass(Element.class) 
+public final class ElementHasAttributeNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "hasAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void _testHasAttributeNS1() throws Throwable {
+        Document doc;
+        Element element;
+        boolean state;
+        NodeList elementList;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagNameNS("*", "employee");
+        element = (Element) elementList.item(0);
+        state = element
+                .hasAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns");
+        assertTrue("elementhasattributens01", state);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "hasAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testHasAttributeNS2() throws Throwable {
+        Document doc;
+        Element element;
+        boolean state;
+        Attr attribute;
+        
+        doc = (Document) load("staff", builder);
+        element = doc.createElementNS("http://www.w3.org/DOM", "address");
+        attribute = doc.createAttributeNS("http://www.w3.org/DOM", "domestic");
+        element.setAttributeNode(attribute);
+        state = element.hasAttributeNS("http://www.w3.org/DOM", "domestic");
+        assertTrue("hasDomesticAttr", state);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "hasAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testHasAttributeNS3() throws Throwable {
+        Document doc;
+        Element element;
+        boolean state;
+        Attr attribute;
+        
+        String nullNS = null;
+
+        doc = (Document) load("staff", builder);
+        element = doc.createElementNS("http://www.w3.org/DOM", "address");
+        assertNotNull("createElementNotNull", element);
+        attribute = doc.createAttributeNS(nullNS, "domestic");
+        element.setAttributeNode(attribute);
+        state = element.hasAttributeNS(nullNS, "domestic");
+        assertTrue("elementhasattributens03", state);
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/ElementRemoveAttributeNS.java b/xml/src/test/java/tests/org/w3c/dom/ElementRemoveAttributeNS.java
new file mode 100644
index 0000000..72c56e9
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/ElementRemoveAttributeNS.java
@@ -0,0 +1,80 @@
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The method removeAttributeNS removes an attribute by local name and namespace
+ * URI. Create a new element and add a new attribute node to it. Remove the
+ * attribute node using the removeAttributeNodeNS method. Check if the attribute
+ * was remove by invoking the hasAttributeNS method on the element and check if
+ * it returns false.
+ * 
+ * @author IBM
+ * @author Neil Delima
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElRemAtNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElRemAtNS</a>
+ */
+@TestTargetClass(Element.class) 
+public final class ElementRemoveAttributeNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "removeAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testRemoveAttributeNS() throws Throwable {
+        Document doc;
+        Element element;
+        boolean state;
+        Attr attribute;
+
+        doc = (Document) load("staff", builder);
+        element = doc.createElementNS("http://www.w3.org/DOM", "elem");
+        attribute = doc.createAttributeNS(
+                "http://www.w3.org/DOM/Test/createAttributeNS", "attr");
+        element.setAttributeNodeNS(attribute);
+        element.removeAttributeNS(
+                "http://www.w3.org/DOM/Test/createAttributeNS", "attr");
+        state = element.hasAttributeNS(
+                "http://www.w3.org/DOM/Test/createAttributeNS", "attr");
+        assertFalse("elementremoveattributens01", state);
+    }
+
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/ElementSetAttributeNS.java b/xml/src/test/java/tests/org/w3c/dom/ElementSetAttributeNS.java
new file mode 100644
index 0000000..babd6f1
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/ElementSetAttributeNS.java
@@ -0,0 +1,266 @@
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The method setAttributeNS adds a new attribute. Create a new element and add
+ * a new attribute node to it using the setAttributeNS method. Check if the
+ * attribute was correctly set by invoking the getAttributeNodeNS method and
+ * checking the nodeName and nodeValue of the returned nodes.
+ * 
+ * @author IBM
+ * @author Neil Delima
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElSetAttrNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElSetAttrNS</a>
+ */
+@TestTargetClass(Element.class) 
+public final class ElementSetAttributeNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException.",
+        method = "setAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+    )
+    public void testSetAttributeNS1() throws Throwable {
+        Document doc;
+        Element element;
+        Attr attribute;
+        String attrName;
+        String attrValue;
+        doc = (Document) load("staff", builder);
+        element = doc.createElementNS("http://www.w3.org/DOM", "dom:elem");
+        element.setAttributeNS("http://www.w3.org/DOM/Test/setAttributeNS",
+                "attr", "value");
+        attribute = element.getAttributeNodeNS(
+                "http://www.w3.org/DOM/Test/setAttributeNS", "attr");
+        attrName = attribute.getNodeName();
+        attrValue = attribute.getNodeValue();
+        assertEquals("elementsetattributens01_attrName", "attr", attrName);
+        assertEquals("elementsetattributens01_attrValue", "value", attrValue);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException.",
+        method = "setAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+    )
+    public void testSetAttributeNS2() throws Throwable {
+        Document doc;
+        Element element;
+        Attr attribute;
+        NodeList elementList;
+        String attrName;
+        String attrValue;
+        doc = (Document) load("staff", builder);
+        elementList = doc.getElementsByTagNameNS("*", "address");
+        element = (Element) elementList.item(0);
+        element.setAttributeNS("http://www.w3.org/DOM/Test/setAttributeNS",
+                "this:street", "Silver Street");
+        attribute = element.getAttributeNodeNS(
+                "http://www.w3.org/DOM/Test/setAttributeNS", "street");
+        attrName = attribute.getNodeName();
+        attrValue = attribute.getNodeValue();
+        assertEquals("elementsetattributens02_attrName", "this:street",
+                attrName);
+        assertEquals("elementsetattributens02_attrValue", "Silver Street",
+                attrValue);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException.",
+        method = "setAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+    )
+    public void testSetAttributeNS3() throws Throwable {
+        Document doc;
+        Element element;
+        Attr attribute;
+        NodeList elementList;
+        String attrName;
+        String attrValue;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("emp:employee");
+        element = (Element) elementList.item(0);
+        assertNotNull("empEmployeeNotNull", element);
+        element.setAttributeNS("http://www.w3.org/DOM/Test/1", "defaultAttr",
+                "default1");
+        element.setAttributeNS("http://www.w3.org/DOM/Test/2", "defaultAttr",
+                "default2");
+        attribute = element.getAttributeNodeNS("http://www.w3.org/DOM/Test/1",
+                "defaultAttr");
+        attrName = attribute.getNodeName();
+        attrValue = attribute.getNodeValue();
+        assertEquals("elementsetattributens03_attrName", "defaultAttr",
+                attrName);
+        assertEquals("elementsetattributens03_attrValue", "default1", attrValue);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies DOMException with INVALID_CHARACTER_ERR.",
+        method = "setAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+    )
+    public void testSetAttributeNS4() throws Throwable {
+        Document doc;
+        Element element;
+        String qualifiedName;
+        List<String> qualifiedNames = new ArrayList<String>();
+        qualifiedNames.add("/");
+        qualifiedNames.add("//");
+        qualifiedNames.add("\\");
+        qualifiedNames.add(";");
+        qualifiedNames.add("&");
+        qualifiedNames.add("*");
+        qualifiedNames.add("]]");
+        qualifiedNames.add(">");
+        qualifiedNames.add("<");
+
+        doc = (Document) load("staffNS", builder);
+        element = doc.createElementNS("http://www.w3.org/DOM/Test/L2",
+                "dom:elem");
+        for (int indexN10058 = 0; indexN10058 < qualifiedNames.size(); indexN10058++) {
+            qualifiedName = (String) qualifiedNames.get(indexN10058);
+
+            {
+                boolean success = false;
+                try {
+                    element.setAttributeNS("http://www.w3.org/DOM/Test/L2",
+                            qualifiedName, "test");
+                } catch (DOMException ex) {
+                    success = (ex.code == DOMException.INVALID_CHARACTER_ERR);
+                }
+                assertTrue("elementsetattributens04", success);
+            }
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies DOMException with NAMESPACE_ERR code.",
+        method = "setAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+    )
+    public void testSetAttributeNS5() throws Throwable {
+        Document doc;
+        Element element;
+        String nullNS = null;
+
+        doc = (Document) load("staffNS", builder);
+        element = doc.createElementNS("http://www.w3.org/DOM/Test/L2",
+                "dom:elem");
+
+        {
+            boolean success = false;
+            try {
+                element.setAttributeNS(nullNS, "dom:root", "test");
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("elementsetattributens05", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies DOMException with NAMESPACE_ERR code.",
+        method = "setAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+    )
+    public void testSetAttributeNS8() throws Throwable {
+        Document doc;
+        Element element;
+        doc = (Document) load("staffNS", builder);
+        element = doc.createElementNS("http://www.w3.org/DOMTest/level2",
+                "dom:elem");
+
+        {
+            boolean success = false;
+            try {
+                element.setAttributeNS("http://www.w3.org/DOMTest/level2",
+                        "xmlns", "test");
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("elementsetattributens08_Err1", success);
+        }
+
+        {
+            boolean success = false;
+            try {
+                element.setAttributeNS("http://www.w3.org/DOMTest/level2",
+                        "xmlns:root", "test");
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("elementsetattributens08_Err2", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies DOMException with NAMESPACE_ERR code.",
+        method = "setAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+    )
+    public void testSetAttributeNSURINull() throws Throwable {
+          String namespaceURI = null;
+
+          String qualifiedName = "emp:qualifiedName";
+          Document doc;
+          NodeList elementList;
+          Node testAddr;
+          doc = (Document) load("staff", builder);
+          elementList = doc.getElementsByTagName("employee");
+          testAddr = elementList.item(0);
+          
+          {
+             boolean success = false;
+             try {
+                ((Element) /*Node */testAddr).setAttributeNS(namespaceURI, qualifiedName, "newValue");
+              } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+             }
+             assertTrue("throw_NAMESPACE_ERR", success);
+          }
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/ElementSetAttributeNodeNS.java b/xml/src/test/java/tests/org/w3c/dom/ElementSetAttributeNodeNS.java
new file mode 100644
index 0000000..2a115e0
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/ElementSetAttributeNodeNS.java
@@ -0,0 +1,276 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+import org.w3c.dom.Attr;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.EntityReference;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * Testing Element.setAttributeNodeNS: If an attribute with that local name and
+ * that namespace URI is already present in the element, it is replaced by the
+ * new one. Create a new element and two new attribute nodes (in the same
+ * namespace and same localNames). Add the two new attribute nodes to the
+ * element node using the setAttributeNodeNS method. Check that only one
+ * attribute is added, check the value of this attribute.
+ * 
+ * @author IBM
+ * @author Neil Delima
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElSetAtNodeNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElSetAtNodeNS</a>
+ */
+@TestTargetClass(Element.class) 
+public final class ElementSetAttributeNodeNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException.",
+        method = "setAttributeNodeNS",
+        args = {org.w3c.dom.Attr.class}
+    )
+    public void testSetAttributeNodeNS1() throws Throwable {
+        Document doc;
+        Element element;
+        Attr attribute1;
+        Attr attribute2;
+        Attr attrNode;
+        String attrName;
+        String attrNS;
+        
+        NamedNodeMap attributes;
+        
+        int length;
+        doc = (Document) load("staff", builder);
+        element = doc.createElementNS("http://www.w3.org/DOM/Test/Level2",
+                "new:element");
+        attribute1 = doc.createAttributeNS("http://www.w3.org/DOM/Test/att1",
+                "p1:att");
+        attribute2 = doc.createAttributeNS("http://www.w3.org/DOM/Test/att1",
+                "p2:att");
+        attribute2.setValue("value2");
+        element.setAttributeNodeNS(attribute1);
+        element.setAttributeNodeNS(attribute2);
+        attrNode = element.getAttributeNodeNS(
+                "http://www.w3.org/DOM/Test/att1", "att");
+        attrName = attrNode.getNodeName();
+        attrNS = attrNode.getNamespaceURI();
+        assertEquals("elementsetattributenodens01_attrName", "p2:att", attrName);
+        assertEquals("elementsetattributenodens01_attrNS",
+                "http://www.w3.org/DOM/Test/att1", attrNS);
+        attributes = element.getAttributes();
+        length = (int) attributes.getLength();
+        assertEquals("length", 1, length);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException.",
+        method = "setAttributeNodeNS",
+        args = {org.w3c.dom.Attr.class}
+    )
+    public void testSetAttributeNodeNS2() throws Throwable {
+        Document doc;
+        Element element;
+        Element element2;
+        Attr attribute;
+        Attr attributeCloned;
+        Attr newAttr;
+        NodeList elementList;
+        String attrName;
+        String attrValue;
+        String nullNS = null;
+
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagNameNS("http://www.nist.gov",
+                "address");
+        element = (Element) elementList.item(1);
+        attribute = element.getAttributeNodeNS(nullNS, "street");
+        attributeCloned = (Attr) attribute.cloneNode(true);
+        element2 = (Element) elementList.item(2);
+        newAttr = element2.setAttributeNodeNS(attributeCloned);
+        attrName = newAttr.getNodeName();
+        attrValue = newAttr.getNodeValue();
+        assertEquals("elementsetattributenodens02_attrName", "street", attrName);
+        assertEquals("elementsetattributenodens02_attrValue", "Yes", attrValue);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies DOMException with INUSE_ATTRIBUTE_ERR code.",
+        method = "setAttributeNodeNS",
+        args = {org.w3c.dom.Attr.class}
+    )
+    public void testSetAttributeNodeNS3() throws Throwable {
+        Document doc;
+        Element element1;
+        Element element2;
+        Attr attribute;
+
+        NodeList elementList;
+        String nullNS = null;
+
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagNameNS("http://www.nist.gov",
+                "address");
+        element1 = (Element) elementList.item(1);
+        attribute = element1.getAttributeNodeNS(nullNS, "street");
+        element2 = (Element) elementList.item(2);
+
+        {
+            boolean success = false;
+            try {
+                element2.setAttributeNodeNS(attribute);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.INUSE_ATTRIBUTE_ERR);
+            }
+            assertTrue("elementsetattributenodens03", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies DOMException with INUSE_ATTRIBUTE_ERR code.",
+        method = "setAttributeNodeNS",
+        args = {org.w3c.dom.Attr.class}
+    )
+    public void testSetAttributeNodeNS4() throws Throwable {
+        Document doc;
+        Element element1;
+        Element element2;
+        Attr attribute;
+
+        doc = (Document) load("staffNS", builder);
+        element1 = doc.createElementNS("http://www.w3.org/DOM/Test", "elem1");
+        element2 = doc.createElementNS("http://www.w3.org/DOM/Test", "elem2");
+        attribute = doc.createAttributeNS("http://www.w3.org/DOM/Test", "attr");
+        element1.setAttributeNodeNS(attribute);
+
+        {
+            boolean success = false;
+            try {
+                element2.setAttributeNodeNS(attribute);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.INUSE_ATTRIBUTE_ERR);
+            }
+            assertTrue("elementsetattributenodens04", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies DOMException with WRONG_DOCUMENT_ERR code.",
+        method = "setAttributeNodeNS",
+        args = {org.w3c.dom.Attr.class}
+    )
+    public void testSetAttributeNodeNS5() throws Throwable {
+        Document doc;
+        Document docAlt;
+        Element element;
+        Attr attribute;
+
+        doc = (Document) load("staffNS", builder);
+        docAlt = (Document) load("staffNS", builder);
+        element = doc.createElementNS("http://www.w3.org/DOM/Test", "elem1");
+        attribute = docAlt.createAttributeNS("http://www.w3.org/DOM/Test",
+                "attr");
+
+        {
+            boolean success = false;
+            try {
+                element.setAttributeNodeNS(attribute);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.WRONG_DOCUMENT_ERR);
+            }
+            assertTrue("throw_WRONG_DOCUMENT_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies DOMException with NO_MODIFICATION_ALLOWED_ERR code.",
+        method = "setAttributeNodeNS",
+        args = {org.w3c.dom.Attr.class}
+    )
+    public void _testSetAttributeNodeNS6() throws Throwable {
+        Document doc;
+        Element element;
+        Attr attribute;
+        Attr attribute2;
+        EntityReference entRef;
+        NodeList elementList;
+
+        doc = (Document) load("staffNS", builder);
+        element = doc.createElementNS("http://www.w3.org/DOM/Test", "elem1");
+        attribute = doc.createAttributeNS("http://www.w3.org/DOM/Test", "attr");
+        entRef = doc.createEntityReference("ent4");
+        attribute.appendChild(entRef);
+        element.setAttributeNodeNS(attribute);
+        elementList = entRef.getChildNodes();
+        element = (Element) elementList.item(0);
+        attribute2 = doc.createAttributeNS("http://www.w3.org/DOM/Test",
+                "attr2");
+
+        {
+            boolean success = false;
+            try {
+                element.setAttributeNodeNS(attribute2);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NO_MODIFICATION_ALLOWED_ERR);
+            }
+            assertTrue("elementsetattributenodens06", success);
+        }
+    }
+
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/GetAttributeNS.java b/xml/src/test/java/tests/org/w3c/dom/GetAttributeNS.java
new file mode 100644
index 0000000..ae5936c
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/GetAttributeNS.java
@@ -0,0 +1,187 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001-2003 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The "getAttributeNS(namespaceURI,localName)" method retrieves an attribute
+ * value by local name and NamespaceURI.
+ * 
+ * Retrieve the first "emp:address" element. The value returned by the
+ * "getAttributeNS()" method should be the value "DISTRICT" since the attribute
+ * has a default value.
+ * 
+ * @author NIST
+ * @author Mary Brady
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElGetAttrNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElGetAttrNS</a>
+ * @see <a
+ *      href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=238">http://www.w3.org/Bugs/Public/show_bug.cgi?id=238</a>
+ */
+@TestTargetClass(Element.class) 
+public final class GetAttributeNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+// Assumes validation.
+//    public void testGetAttributeNS1() throws Throwable {
+//        String namespaceURI = "http://www.nist.gov";
+//        String localName = "district";
+//
+//        Document doc;
+//        NodeList elementList;
+//        Element testAddr;
+//        String attrValue;
+//        doc = (Document) load("staffNS", builder);
+//        elementList = doc.getElementsByTagName("emp:address");
+//        testAddr = (Element) elementList.item(0);
+//        attrValue = testAddr.getAttributeNS(namespaceURI, localName);
+//        assertEquals("attrValue", "DISTRICT", attrValue);
+//    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "getAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetAttributeNS2() throws Throwable {
+        String namespaceURI = "http://www.nist.gov";
+        String localName = "district";
+        String qualifiedName = "emp:district";
+        Document doc;
+        Attr newAttribute;
+        NodeList elementList;
+        Element testAddr;
+
+        String attrValue;
+        doc = (Document) load("staffNS", builder);
+        newAttribute = doc.createAttributeNS(namespaceURI, qualifiedName);
+        elementList = doc.getElementsByTagName("emp:address");
+        testAddr = (Element) elementList.item(0);
+        assertNotNull("empAddrNotNull", testAddr);
+        testAddr.setAttributeNodeNS(newAttribute);
+        elementList = doc.getElementsByTagName("emp:address");
+        testAddr = (Element) elementList.item(0);
+        attrValue = testAddr.getAttributeNS(namespaceURI, localName);
+        assertEquals("throw_Equals", "", attrValue);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "getAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetAttributeNS3() throws Throwable {
+        String namespaceURI = "http://www.nist.gov";
+        String localName = "domestic";
+        Document doc;
+        NodeList elementList;
+        Element testAddr;
+        String attrValue;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("emp:address");
+        testAddr = (Element) elementList.item(0);
+        assertNotNull("empAddrNotNull", testAddr);
+        testAddr.removeAttributeNS(namespaceURI, localName);
+        attrValue = testAddr.getAttributeNS(namespaceURI, localName);
+        assertEquals("throw_Equals", "", attrValue);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "getAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetAttributeNS4() throws Throwable {
+        String namespaceURI = "http://www.nist.gov";
+        String localName = "blank";
+        String qualifiedName = "emp:blank";
+        Document doc;
+
+        NodeList elementList;
+        Element testAddr;
+
+        String attrValue;
+        doc = (Document) load("staffNS", builder);
+        doc.createAttributeNS(namespaceURI, qualifiedName);
+        elementList = doc.getElementsByTagName("emp:address");
+        testAddr = (Element) elementList.item(0);
+        assertNotNull("empAddrNotNull", testAddr);
+        testAddr.setAttributeNS(namespaceURI, qualifiedName, "NewValue");
+        attrValue = testAddr.getAttributeNS(namespaceURI, localName);
+        assertEquals("throw_Equals", "NewValue", attrValue);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "getAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetAttributeNS5() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Element testAddr;
+        String attrValue;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("emp:address");
+        testAddr = (Element) elementList.item(0);
+        assertNotNull("empAddrNotNull", testAddr);
+        attrValue = testAddr.getAttributeNS("http://www.nist.gov", "domestic");
+        assertEquals("attrValue", "Yes", attrValue);
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/GetAttributeNodeNS.java b/xml/src/test/java/tests/org/w3c/dom/GetAttributeNodeNS.java
new file mode 100644
index 0000000..7c72fe5
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/GetAttributeNodeNS.java
@@ -0,0 +1,121 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001-2004 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Attr;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The "getAttributeNodeNS(namespaceURI,localName)" method retrieves an
+ * attribute node by local name and NamespaceURI.
+ * 
+ * Retrieve the first emp:address element node. The getAttributeNodeNS method
+ * returns an Attr node, the "value" can be examined to ensure the proper
+ * attribute node was retrieved. This attribute value should be null since there
+ * is no such attribute.
+ * 
+ * @author NIST
+ * @author Mary Brady
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElGetAtNodeNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElGetAtNodeNS</a>
+ */
+@TestTargetClass(Element.class) 
+public final class GetAttributeNodeNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "getAttributeNodeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetAttributeNodeNS1() throws Throwable {
+        String namespaceURI = "http://www.nist.gov";
+        String localName = "invalidlocalname";
+        Document doc;
+        NodeList elementList;
+        Element testAddr;
+        Attr attribute;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("emp:address");
+        testAddr = (Element) elementList.item(0);
+        assertNotNull("empAddrNotNull", testAddr);
+        attribute = testAddr.getAttributeNodeNS(namespaceURI, localName);
+        assertNull("throw_Null", attribute);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "getAttributeNodeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetAttributeNodeNS2() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Element testAddr;
+        Attr attribute;
+        String attrName;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("emp:address");
+        testAddr = (Element) elementList.item(0);
+        assertNotNull("empAddrNotNull", testAddr);
+        attribute = testAddr.getAttributeNodeNS("http://www.nist.gov",
+                "domestic");
+        attrName = attribute.getNodeName();
+        assertEquals("attrName", "emp:domestic", attrName);
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/GetElementById.java b/xml/src/test/java/tests/org/w3c/dom/GetElementById.java
new file mode 100644
index 0000000..073df2f
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/GetElementById.java
@@ -0,0 +1,102 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001-2003 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The "getElementById(elementId)" method for a Document should return an
+ * element whose ID matches elementId.
+ * 
+ * Invoke method getElementById(elementId) on this document with elementId
+ * equals "CANADA". Method should return an element whose tag name is
+ * "emp:address".
+ * 
+ * @author NIST
+ * @author Mary Brady
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-104682815">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-104682815</a>
+ * @see <a
+ *      href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=383">http://www.w3.org/Bugs/Public/show_bug.cgi?id=383</a>
+ */
+@TestTargetClass(Document.class) 
+public final class GetElementById extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+// Assumes validation.
+//    public void testGetElementById1() throws Throwable {
+//        Document doc;
+//        Element element;
+//        String tagname;
+//        doc = (Document) load("staffNS", builder);
+//        element = doc.getElementById("CANADA");
+//        tagname = element.getTagName();
+//        assertEquals("throw_Equals", "emp:address", tagname);
+//    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify getElementById method for existent element.",
+        method = "getElementById",
+        args = {java.lang.String.class}
+    )
+    public void testGetElementById2() throws Throwable {
+        Document doc;
+        Element element;
+        doc = (Document) load("staffNS", builder);
+        element = doc.getElementById("Cancun");
+        assertNull("throw_Null", element);
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/GetElementsByTagNameNS.java b/xml/src/test/java/tests/org/w3c/dom/GetElementsByTagNameNS.java
new file mode 100644
index 0000000..d5fa0bf
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/GetElementsByTagNameNS.java
@@ -0,0 +1,381 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The "getElementsByTagNameNS(namespaceURI,localName)" method for a Document
+ * should return a new NodeList of all Elements that have a namespace when local
+ * name is specified as ' '.
+ * 
+ * Invoke method getElementsByTagNameNS(namespaceURI,localName) on this document
+ * with namespaceURI and localName as " ". Method should return a new NodeList
+ * of 37 elements.
+ * 
+ * @author NIST
+ * @author Mary Brady
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-getElBTNNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-getElBTNNS</a>
+ */
+@TestTargetClass(Document.class) 
+public final class GetElementsByTagNameNS extends DOMTestCase {
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies getElementsByTagNameNS method with * as parameters.",
+        method = "getElementsByTagNameNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetElementsByTagNameNS1() throws Throwable {
+        String namespaceURI = "*";
+        String localName = "*";
+        Document doc;
+        NodeList newList;
+        doc = (Document) load("staffNS", builder);
+        newList = doc.getElementsByTagNameNS(namespaceURI, localName);
+        // BEGIN android-changed: Was 37, but that assumed validation.
+        assertEquals("throw_Size", 36, newList.getLength());
+        // END android-changed
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies getElementsByTagNameNS with '*' as the first parameter.",
+        method = "getElementsByTagNameNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetElementsByTagNameNS2() throws Throwable {
+        Document doc;
+        NodeList newList;
+        Element newElement;
+        String prefix;
+        String lname;
+        doc = (Document) load("staffNS", builder);
+        newList = doc.getElementsByTagNameNS("*", "employee");
+        assertEquals("employeeCount", 5, newList.getLength());
+        newElement = (Element) newList.item(3);
+        prefix = newElement.getPrefix();
+        assertEquals("prefix", "emp", prefix);
+        lname = newElement.getLocalName();
+        assertEquals("lname", "employee", lname);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies getElementsByTagNameNS with '*' as the second parameter.",
+        method = "getElementsByTagNameNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetElementsByTagNameNS3() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Node child;
+        String childName;
+        List<String> result = new ArrayList<String>();
+
+        List<String> expectedResult = new ArrayList<String>();
+        expectedResult.add("employee");
+        expectedResult.add("employeeId");
+        expectedResult.add("name");
+        expectedResult.add("position");
+        expectedResult.add("salary");
+        expectedResult.add("gender");
+        expectedResult.add("address");
+        expectedResult.add("emp:employee");
+        expectedResult.add("emp:employeeId");
+        expectedResult.add("emp:position");
+        expectedResult.add("emp:salary");
+        expectedResult.add("emp:gender");
+        expectedResult.add("emp:address");
+        expectedResult.add("address");
+
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagNameNS("http://www.nist.gov", "*");
+        for (int indexN10076 = 0; indexN10076 < elementList.getLength(); indexN10076++) {
+            child = (Node) elementList.item(indexN10076);
+            childName = child.getNodeName();
+            result.add(childName);
+        }
+        assertEquals("nodeNames", expectedResult, result);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies getElementsByTagNameNS with '*' as the first parameter.",
+        method = "getElementsByTagNameNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetElementsByTagNameNS4() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Node child;
+        String childName;
+        List<String> result = new ArrayList<String>();
+
+        List<String> expectedResult = new ArrayList<String>();
+        expectedResult.add("address");
+        expectedResult.add("address");
+        expectedResult.add("address");
+        expectedResult.add("emp:address");
+        expectedResult.add("address");
+
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagNameNS("*", "address");
+        for (int indexN10059 = 0; indexN10059 < elementList.getLength(); indexN10059++) {
+            child = (Node) elementList.item(indexN10059);
+            childName = child.getNodeName();
+            result.add(childName);
+        }
+        assertEquals("nodeNames", expectedResult, result);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies negative case of getElementsByTagNameNS method.",
+        method = "getElementsByTagNameNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetElementsByTagNameNS5() throws Throwable {
+        String namespaceURI = "http://www.nist.gov";
+        String localName = "nomatch";
+        Document doc;
+        NodeList elementList;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagNameNS(namespaceURI, localName);
+        assertEquals("throw_Size", 0, elementList.getLength());
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies negative case of getElementsByTagNameNS method.",
+        method = "getElementsByTagNameNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetElementsByTagNameNS6() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagNameNS("http://www.nomatch.com",
+                "address");
+        assertEquals("matchSize", 0, elementList.getLength());
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies positive case of getElementsByTagNameNS method.",
+        method = "getElementsByTagNameNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetElementsByTagNameNS7() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagNameNS("http://www.nist.gov",
+                "address");
+        assertEquals("addresses", 3, elementList.getLength());
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies getElementsByTagNameNS method with '*' as parameters; positive case.",
+        method = "getElementsByTagNameNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetElementsByTagNameNS8() throws Throwable {
+        Document doc;
+        Element docElem;
+        NodeList newList;
+        doc = (Document) load("staffNS", builder);
+        docElem = doc.getDocumentElement();
+        newList = docElem.getElementsByTagNameNS("*", "*");
+        assertEquals("listSize", 36, newList.getLength());
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies getElementsByTagNameNS method with '*' as the first parameter.",
+        method = "getElementsByTagNameNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetElementsByTagNameNS9() throws Throwable {
+        Document doc;
+        NodeList newList;
+        Element newElement;
+        String prefix;
+        String lname;
+        Element docElem;
+        doc = (Document) load("staffNS", builder);
+        docElem = doc.getDocumentElement();
+        newList = docElem.getElementsByTagNameNS("*", "employee");
+        assertEquals("employeeCount", 5, newList.getLength());
+        newElement = (Element) newList.item(3);
+        prefix = newElement.getPrefix();
+        assertEquals("prefix", "emp", prefix);
+        lname = newElement.getLocalName();
+        assertEquals("lname", "employee", lname);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies getElementsByTagNameNS method with '*' as the second parameter.",
+        method = "getElementsByTagNameNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetElementsByTagNameNS10() throws Throwable {
+        Document doc;
+        Element docElem;
+        NodeList elementList;
+        Node child;
+        String childName;
+        List<String> result = new ArrayList<String>();
+
+        List<String> expectedResult = new ArrayList<String>();
+        expectedResult.add("employee");
+        expectedResult.add("employeeId");
+        expectedResult.add("name");
+        expectedResult.add("position");
+        expectedResult.add("salary");
+        expectedResult.add("gender");
+        expectedResult.add("address");
+        expectedResult.add("emp:employee");
+        expectedResult.add("emp:employeeId");
+        expectedResult.add("emp:position");
+        expectedResult.add("emp:salary");
+        expectedResult.add("emp:gender");
+        expectedResult.add("emp:address");
+        expectedResult.add("address");
+
+        doc = (Document) load("staffNS", builder);
+        docElem = doc.getDocumentElement();
+        elementList = docElem
+                .getElementsByTagNameNS("http://www.nist.gov", "*");
+        for (int indexN1007E = 0; indexN1007E < elementList.getLength(); indexN1007E++) {
+            child = (Node) elementList.item(indexN1007E);
+            childName = child.getNodeName();
+            result.add(childName);
+        }
+        assertEquals("nodeNames", expectedResult, result);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies getElementsByTagNameNS method with '*' as the first parameter.",
+        method = "getElementsByTagNameNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetElementsByTagNameNS11() throws Throwable {
+        Document doc;
+        Element docElem;
+        NodeList elementList;
+        Node child;
+        String childName;
+        List<String> result = new ArrayList<String>();
+
+        List<String> expectedResult = new ArrayList<String>();
+        expectedResult.add("address");
+        expectedResult.add("address");
+        expectedResult.add("address");
+        expectedResult.add("emp:address");
+        expectedResult.add("address");
+
+        doc = (Document) load("staffNS", builder);
+        docElem = doc.getDocumentElement();
+        elementList = docElem.getElementsByTagNameNS("*", "address");
+        for (int indexN1005E = 0; indexN1005E < elementList.getLength(); indexN1005E++) {
+            child = (Node) elementList.item(indexN1005E);
+            childName = child.getNodeName();
+            result.add(childName);
+        }
+        assertEquals("nodeNames", expectedResult, result);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies negative case for getElementsByTagNameNS method.",
+        method = "getElementsByTagNameNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetElementsByTagNameNS12() throws Throwable {
+        Document doc;
+        Element docElem;
+        NodeList elementList;
+        doc = (Document) load("staffNS", builder);
+        docElem = doc.getDocumentElement();
+        elementList = docElem.getElementsByTagNameNS("http://www.nist.gov",
+                "nomatch");
+        assertEquals("size", 0, elementList.getLength());
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies negative case for getElementsByTagNameNS method.",
+        method = "getElementsByTagNameNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetElementsByTagNameNS13() throws Throwable {
+        Document doc;
+        Element docElem;
+        NodeList elementList;
+        doc = (Document) load("staffNS", builder);
+        docElem = doc.getDocumentElement();
+        elementList = docElem.getElementsByTagNameNS("http://www.nomatch.com",
+                "address");
+        assertEquals("matchSize", 0, elementList.getLength());
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies positive case for getElementsByTagNameNS method.",
+        method = "getElementsByTagNameNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetElementsByTagNameNS14() throws Throwable {
+        Document doc;
+        Element docElem;
+        NodeList elementList;
+        doc = (Document) load("staffNS", builder);
+        docElem = doc.getDocumentElement();
+        elementList = docElem.getElementsByTagNameNS("http://www.nist.gov",
+                "address");
+        assertEquals("addresses", 3, elementList.getLength());
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/GetNamedItemNS.java b/xml/src/test/java/tests/org/w3c/dom/GetNamedItemNS.java
new file mode 100644
index 0000000..270fe04
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/GetNamedItemNS.java
@@ -0,0 +1,135 @@
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Document;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The "getNamedItemNS(namespaceURI,localName)" method for a NamedNodeMap should
+ * return a node specified by localName and namespaceURI
+ * 
+ * Retrieve a list of elements with tag name "address". Access the second
+ * element from the list and get its attributes. Try to retrieve the attribute
+ * node with local name "domestic" and namespace uri "http://www.usa.com" with
+ * method getNamedItemNS(namespaceURI,localName).
+ * 
+ * @author NIST
+ * @author Mary Brady
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-F68D095">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-F68D095</a>
+ */
+@TestTargetClass(NamedNodeMap.class) 
+public final class GetNamedItemNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "getNamedItem",
+        args = {java.lang.String.class}
+    )
+    public void testGetNamedItemNS1() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Node testEmployee;
+        NamedNodeMap attributes;
+        Attr domesticAttr;
+        String attrName;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("address");
+        testEmployee = elementList.item(1);
+        attributes = testEmployee.getAttributes();
+        domesticAttr = (Attr) attributes.getNamedItemNS("http://www.usa.com",
+                "domestic");
+        attrName = domesticAttr.getNodeName();
+        assertEquals("attrName", "dmstc:domestic", attrName);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "getNamedItemNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetNamedItemNS2() throws Throwable {
+        String namespaceURI = "http://www.usa.com";
+        String localName = "domest";
+        Document doc;
+        NodeList elementList;
+        Node testEmployee;
+        NamedNodeMap attributes;
+        Attr newAttr;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("address");
+        testEmployee = elementList.item(1);
+        attributes = testEmployee.getAttributes();
+        newAttr = (Attr) attributes.getNamedItemNS(namespaceURI, localName);
+        assertNull("throw_Null", newAttr);
+    }
+
+// Assumes validation.
+//    public void testGetNamedItemNS3() throws Throwable {
+//        Document doc;
+//        DocumentType docType;
+//        NamedNodeMap entities;
+//        Entity entity;
+//        String nullNS = null;
+//
+//        doc = (Document) load("staffNS", builder);
+//        docType = doc.getDoctype();
+//        entities = docType.getEntities();
+//        assertNotNull("entitiesNotNull", entities);
+//        entity = (Entity) entities.getNamedItemNS(nullNS, "ent1");
+//        assertNotNull("entityNull", entity);
+//    }
+
+// Assumes validation.
+//    public void testGetNamedItemNS4() throws Throwable {
+//        Document doc;
+//        DocumentType docType;
+//        NamedNodeMap notations;
+//        Notation notation;
+//        String nullNS = null;
+//
+//        doc = (Document) load("staffNS", builder);
+//        docType = doc.getDoctype();
+//        notations = docType.getNotations();
+//        assertNotNull("notationsNotNull", notations);
+//        notation = (Notation) notations.getNamedItemNS(nullNS, "notation1");
+//        assertNotNull("notationNull", notation);
+//    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/HCEntitiesRemoveNamedItemNS.java b/xml/src/test/java/tests/org/w3c/dom/HCEntitiesRemoveNamedItemNS.java
new file mode 100644
index 0000000..1cdd20f
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/HCEntitiesRemoveNamedItemNS.java
@@ -0,0 +1,102 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+ Copyright (c) 2004 World Wide Web Consortium,
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University). All
+ Rights Reserved. This program is distributed under the W3C's Software
+ Intellectual Property License. This program is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE.
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargetClass; 
+
+import javax.xml.parsers.DocumentBuilder;
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.NamedNodeMap;
+
+/**
+ * An attempt to add remove an entity using removeNamedItemNS should result in a
+ * NO_MODIFICATION_ERR or a NOT_FOUND_ERR.
+ * 
+ * @author Curt Arnold
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-1788794630">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-1788794630</a>
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-removeNamedItemNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-removeNamedItemNS</a>
+ */
+@TestTargetClass(NamedNodeMap.class) 
+public final class HCEntitiesRemoveNamedItemNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+// Assumes validation.
+//    public void testRemoveNamedItemNS() throws Throwable {
+//        Document doc;
+//        NamedNodeMap entities;
+//        DocumentType docType;
+//        
+//        doc = (Document) load("hc_staff", builder);
+//        docType = doc.getDoctype();
+//
+//        if (!(("text/html".equals(getContentType())))) {
+//            assertNotNull("docTypeNotNull", docType);
+//            entities = docType.getEntities();
+//            assertNotNull("entitiesNotNull", entities);
+//
+//            try {
+//                entities.removeNamedItemNS(
+//                        "http://www.w3.org/1999/xhtml", "alpha");
+//                fail("throw_NO_MOD_OR_NOT_FOUND_ERR");
+//
+//            } catch (DOMException ex) {
+//                switch (ex.code) {
+//                case 7:
+//                    break;
+//                case 8:
+//                    break;
+//                default:
+//                    throw ex;
+//                }
+//            }
+//        }
+//    }
+
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/HCEntitiesSetNamedItemNS.java b/xml/src/test/java/tests/org/w3c/dom/HCEntitiesSetNamedItemNS.java
new file mode 100644
index 0000000..7e2917a
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/HCEntitiesSetNamedItemNS.java
@@ -0,0 +1,86 @@
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargetClass; 
+
+import javax.xml.parsers.DocumentBuilder;
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+
+/**
+ * An attempt to add an element to the named node map returned by entities
+ * should result in a NO_MODIFICATION_ERR or HIERARCHY_REQUEST_ERR.
+ * 
+ * @author Curt Arnold
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-1788794630">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-1788794630</a>
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-setNamedItemNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-setNamedItemNS</a>
+ */
+@TestTargetClass(NamedNodeMap.class) 
+public final class HCEntitiesSetNamedItemNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+// Assumes validation.
+//    public void testSetNamedItemNS() throws Throwable {
+//        Document doc;
+//        NamedNodeMap entities;
+//        DocumentType docType;
+//
+//        Element elem;
+//        doc = (Document) load("hc_staff", builder);
+//        docType = doc.getDoctype();
+//
+//        if (!(("text/html".equals(getContentType())))) {
+//            assertNotNull("docTypeNotNull", docType);
+//            entities = docType.getEntities();
+//            assertNotNull("entitiesNotNull", entities);
+//            elem = doc.createElementNS("http://www.w3.org/1999/xhtml", "br");
+//
+//            try {
+//                entities.setNamedItemNS(elem);
+//                fail("throw_HIER_OR_NO_MOD_ERR");
+//
+//            } catch (DOMException ex) {
+//                switch (ex.code) {
+//                case 3:
+//                    break;
+//                case 7:
+//                    break;
+//                default:
+//                    throw ex;
+//                }
+//            }
+//        }
+//    }
+
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/HCNamedNodeMapInvalidType.java b/xml/src/test/java/tests/org/w3c/dom/HCNamedNodeMapInvalidType.java
new file mode 100644
index 0000000..d968bc4
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/HCNamedNodeMapInvalidType.java
@@ -0,0 +1,103 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+ Copyright (c) 2001-2004 World Wide Web Consortium,
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University). All
+ Rights Reserved. This program is distributed under the W3C's Software
+ Intellectual Property License. This program is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE.
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.DOMException;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * Attempt to insert an element into an attribute list, should raise a
+ * HIERARCHY_REQUEST_ERR.
+ * 
+ * @author Curt Arnold
+ * @see <a
+ *      href="http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core#xpointer(id('ID-258A00AF')/constant[@name='HIERARCHY_REQUEST_ERR'])">http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core#xpointer(id('ID-258A00AF')/constant[@name='HIERARCHY_REQUEST_ERR'])</a>
+ * @see <a
+ *      href="http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core#ID-1025163788">http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core#ID-1025163788</a>
+ * @see <a
+ *      href="http://www.w3.org/2000/11/DOM-Level-2-errata#core-4">http://www.w3.org/2000/11/DOM-Level-2-errata#core-4</a>
+ */
+@TestTargetClass(NamedNodeMap.class) 
+public final class HCNamedNodeMapInvalidType extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that setNamedItem method throws DOMException with HIERARCHY_REQUEST_ERR code.",
+        method = "setNamedItem",
+        args = {org.w3c.dom.Node.class}
+    )
+    public void testNamedNodeMapInvalidType() throws Throwable {
+        Document doc;
+        NamedNodeMap attributes;
+        Element docElem;
+        Element newElem;
+
+        doc = (Document) load("hc_staff", builder);
+        docElem = doc.getDocumentElement();
+        attributes = docElem.getAttributes();
+        newElem = doc.createElement("html");
+
+        {
+            boolean success = false;
+            try {
+                attributes.setNamedItem(newElem);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.HIERARCHY_REQUEST_ERR);
+            }
+            assertTrue("throw_HIERARCHY_REQUEST_ERR", success);
+        }
+    }
+
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/HCNodeDocumentFragmentNormalize.java b/xml/src/test/java/tests/org/w3c/dom/HCNodeDocumentFragmentNormalize.java
new file mode 100644
index 0000000..53317b3
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/HCNodeDocumentFragmentNormalize.java
@@ -0,0 +1,108 @@
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.Text;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * Create a document fragment with two adjacent text nodes, normalize and see if
+ * the text nodes were combined.
+ * 
+ * @author Curt Arnold
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-F68D095">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-F68D095</a>
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-B63ED1A3">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-B63ED1A3</a>
+ */
+@TestTargetClass(Node.class) 
+public final class HCNodeDocumentFragmentNormalize extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.PARTIAL,
+            notes = "Verifies positive functionality of getNodeValue method, and that getNextSibling method returns null.",
+            method = "getNodeValue",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.PARTIAL,
+            notes = "Verifies positive functionality of getNodeValue method, and that getNextSibling method returns null.",
+            method = "getNextSibling",
+            args = {}
+        )
+    })
+    public void testNodeDocumentFragmentNormalize1() throws Throwable {
+        Document doc;
+        DocumentFragment docFragment;
+        String nodeValue;
+        Text txtNode;
+        Node retval;
+        
+        doc = (Document) load("hc_staff", builder);
+        docFragment = doc.createDocumentFragment();
+        txtNode = doc.createTextNode("foo");
+        retval = docFragment.appendChild(txtNode);
+        txtNode = doc.createTextNode("bar");
+        retval = docFragment.appendChild(txtNode);
+        docFragment.normalize();
+        txtNode = (Text) docFragment.getFirstChild();
+        nodeValue = txtNode.getNodeValue();
+        assertEquals("normalizedNodeValue", "foobar", nodeValue);
+        retval = txtNode.getNextSibling();
+        assertNull("singleChild", retval);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that getFirstChild method returns null.",
+        method = "getFirstChild",
+        args = {}
+    )
+    public void testNodeDocumentFragmentNormalize2() throws Throwable {
+        Document doc;
+        DocumentFragment docFragment;
+        Text txtNode;
+        
+        doc = (Document) load("hc_staff", builder);
+        docFragment = doc.createDocumentFragment();
+        txtNode = doc.createTextNode("");
+        docFragment.appendChild(txtNode);
+        docFragment.normalize();
+        txtNode = (Text) docFragment.getFirstChild();
+        assertNull("noChild", txtNode);
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/HCNotationsRemoveNamedItemNS.java b/xml/src/test/java/tests/org/w3c/dom/HCNotationsRemoveNamedItemNS.java
new file mode 100644
index 0000000..3eab5fc
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/HCNotationsRemoveNamedItemNS.java
@@ -0,0 +1,110 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+ Copyright (c) 2004 World Wide Web Consortium,
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University). All
+ Rights Reserved. This program is distributed under the W3C's Software
+ Intellectual Property License. This program is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE.
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.DOMException;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * An attempt to add remove an notation using removeNamedItemNS should result in
+ * a NO_MODIFICATION_ERR or a NOT_FOUND_ERR.
+ * 
+ * @author Curt Arnold
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-D46829EF">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-D46829EF</a>
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-removeNamedItemNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-removeNamedItemNS</a>
+ */
+@TestTargetClass(NamedNodeMap.class) 
+public final class HCNotationsRemoveNamedItemNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that removeNamedItemNS method throws DOMException.",
+        method = "removeNamedItemNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testRemoveNamedItemNS() throws Throwable {
+        Document doc;
+        NamedNodeMap notations;
+        DocumentType docType;
+
+        doc = (Document) load("hc_staff", builder);
+        docType = doc.getDoctype();
+
+        if (!(("text/html".equals(getContentType())))) {
+            assertNotNull("docTypeNotNull", docType);
+            notations = docType.getNotations();
+            assertNotNull("notationsNotNull", notations);
+
+            try {
+                notations.removeNamedItemNS("http://www.w3.org/1999/xhtml",
+                        "alpha");
+                fail("throw_NO_MOD_OR_NOT_FOUND_ERR");
+
+            } catch (DOMException ex) {
+                switch (ex.code) {
+                case 7:
+                    break;
+                case 8:
+                    break;
+                default:
+                    throw ex;
+                }
+            }
+        }
+    }
+
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/HCNotationsSetNamedItemNS.java b/xml/src/test/java/tests/org/w3c/dom/HCNotationsSetNamedItemNS.java
new file mode 100644
index 0000000..d5daee4
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/HCNotationsSetNamedItemNS.java
@@ -0,0 +1,112 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+ Copyright (c) 2004 World Wide Web Consortium,
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University). All
+ Rights Reserved. This program is distributed under the W3C's Software
+ Intellectual Property License. This program is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE.
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.DOMException;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * An attempt to add an element to the named node map returned by notations
+ * should result in a NO_MODIFICATION_ERR or HIERARCHY_REQUEST_ERR.
+ * 
+ * @author Curt Arnold
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-D46829EF">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-D46829EF</a>
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-setNamedItemNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-setNamedItemNS</a>
+ */
+@TestTargetClass(NamedNodeMap.class) 
+public final class HCNotationsSetNamedItemNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that setNamedItemNS throws DOMException.",
+        method = "setNamedItemNS",
+        args = {org.w3c.dom.Node.class}
+    )
+    public void testNotationsSetNamedItemNS() throws Throwable {
+        Document doc;
+        NamedNodeMap notations;
+        DocumentType docType;
+
+        Element elem;
+        doc = (Document) load("hc_staff", builder);
+        docType = doc.getDoctype();
+
+        if (!(("text/html".equals(getContentType())))) {
+            assertNotNull("docTypeNotNull", docType);
+            notations = docType.getNotations();
+            assertNotNull("notationsNotNull", notations);
+            elem = doc.createElementNS("http://www.w3.org/1999/xhtml", "br");
+
+            try {
+                notations.setNamedItemNS(elem);
+                fail("throw_HIER_OR_NO_MOD_ERR");
+
+            } catch (DOMException ex) {
+                switch (ex.code) {
+                case 3:
+                    break;
+                case 7:
+                    break;
+                default:
+                    throw ex;
+                }
+            }
+        }
+    }
+
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/HasAttribute.java b/xml/src/test/java/tests/org/w3c/dom/HasAttribute.java
new file mode 100644
index 0000000..89eef88
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/HasAttribute.java
@@ -0,0 +1,119 @@
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The "hasAttribute()" method for an Element should return true if the element
+ * has an attribute with the given name. Retrieve the first "address" element
+ * and the "hasAttribute()" method should return false since the element does
+ * not have a default value.
+ * 
+ * @author NIST
+ * @author Mary Brady
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElHasAttr">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElHasAttr</a>
+ */
+@TestTargetClass(Element.class) 
+public final class HasAttribute extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that hasAttribute method returns false.",
+        method = "hasAttribute",
+        args = {java.lang.String.class}
+    )
+    public void testHasAttribute1() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Element testNode;
+        boolean state;
+        doc = (Document) load("staff", builder);
+        elementList = doc.getElementsByTagName("address");
+        testNode = (Element) elementList.item(4);
+        state = testNode.hasAttribute("domestic");
+        assertFalse("throw_False", state);
+    }
+
+// Assumes validation.
+//    public void testHasAttribute2() throws Throwable {
+//        Document doc;
+//        NodeList elementList;
+//        Element testNode;
+//        boolean state;
+//        doc = (Document) load("staff", builder);
+//        elementList = doc.getElementsByTagName("address");
+//        testNode = (Element) elementList.item(0);
+//        state = testNode.hasAttribute("street");
+//        assertTrue("throw_True", state);
+//    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that hasAttribute method returns false.",
+        method = "hasAttribute",
+        args = {java.lang.String.class}
+    )
+    public void testHasAttribute3() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Element testNode;
+        boolean state;
+        doc = (Document) load("staff", builder);
+        elementList = doc.getElementsByTagName("address");
+        testNode = (Element) elementList.item(0);
+        state = testNode.hasAttribute("nomatch");
+        assertFalse("throw_False", state);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that hasAttribute method returns true.",
+        method = "hasAttribute",
+        args = {java.lang.String.class}
+    )
+    public void testHasAttribute4() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Element testNode;
+        boolean state;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("address");
+        testNode = (Element) elementList.item(0);
+        state = testNode.hasAttribute("dmstc:domestic");
+        assertTrue("hasDomesticAttr", state);
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/HasAttributeNS.java b/xml/src/test/java/tests/org/w3c/dom/HasAttributeNS.java
new file mode 100644
index 0000000..cf1b90e
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/HasAttributeNS.java
@@ -0,0 +1,172 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * 
+ * The "hasAttributeNS()" method for an Element should return false if the
+ * element does not have an attribute with the given local name and/or a
+ * namespace URI specified on this element or does not have a default value.
+ * Retrieve the first "address" element and the "hasAttributeNS()" method should
+ * return false since the element has "nomatch" as the local name and
+ * "http://www.usa.com" as the namespace URI.
+ * 
+ * @author NIST
+ * @author Mary Brady
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElHasAttrNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElHasAttrNS</a>
+ */
+@TestTargetClass(Element.class) 
+public final class HasAttributeNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "hasAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testHasAttributeNS1() throws Throwable {
+        String localName = "nomatch";
+        String namespaceURI = "http://www.usa.com";
+        Document doc;
+        NodeList elementList;
+        Element testNode;
+        boolean state;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("address");
+        testNode = (Element) elementList.item(0);
+        state = testNode.hasAttributeNS(namespaceURI, localName);
+        assertFalse("throw_False", state);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "hasAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testHasAttributeNS2() throws Throwable {
+        String localName = "domestic";
+        String namespaceURI = "http://www.nomatch.com";
+        Document doc;
+        NodeList elementList;
+        Element testNode;
+        boolean state;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("address");
+        testNode = (Element) elementList.item(0);
+        state = testNode.hasAttributeNS(namespaceURI, localName);
+        assertFalse("throw_False", state);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "hasAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testHasAttributeNS3() throws Throwable {
+        String localName = "blank";
+        String namespaceURI = "http://www.nist.gov";
+        Document doc;
+        NodeList elementList;
+        Element testNode;
+        boolean state;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("emp:address");
+        testNode = (Element) elementList.item(0);
+        assertNotNull("empAddrNotNull", testNode);
+        state = testNode.hasAttributeNS(namespaceURI, localName);
+        assertFalse("throw_False", state);
+    }
+
+// Assumes validation.
+//    public void testHasAttributeNS4() throws Throwable {
+//        String localName = "district";
+//        String namespaceURI = "http://www.nist.gov";
+//        Document doc;
+//        NodeList elementList;
+//        Element testNode;
+//        boolean state;
+//        doc = (Document) load("staffNS", builder);
+//        elementList = doc.getElementsByTagName("emp:address");
+//        testNode = (Element) elementList.item(0);
+//        assertNotNull("empAddressNotNull", testNode);
+//        state = testNode.hasAttributeNS(namespaceURI, localName);
+//        assertTrue("hasAttribute", state);
+//    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "hasAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testHasAttributeNS5() throws Throwable {
+        String localName = "domestic";
+        String namespaceURI = "http://www.usa.com";
+        Document doc;
+        NodeList elementList;
+        Element testNode;
+        boolean state;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("address");
+        testNode = (Element) elementList.item(0);
+        state = testNode.hasAttributeNS(namespaceURI, localName);
+        assertTrue("hasAttribute", state);
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/HasAttributes.java b/xml/src/test/java/tests/org/w3c/dom/HasAttributes.java
new file mode 100644
index 0000000..5d3954d
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/HasAttributes.java
@@ -0,0 +1,111 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The "hasAttributes()" method for a node should return false if the node does
+ * not have an attribute. Retrieve the first "name" node and invoke the
+ * "hasAttributes()" method. The method should return false since the node does
+ * not have an attribute.
+ * 
+ * @author NIST
+ * @author Mary Brady
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeHasAttrs">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeHasAttrs</a>
+ */
+@TestTargetClass(Node.class) 
+public final class HasAttributes extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that hasAttributes method returns false value.",
+        method = "hasAttributes",
+        args = {}
+    )
+    public void testHasAttributes1() throws Throwable {
+        Document doc;
+        NodeList addrList;
+        Node addrNode;
+        boolean state;
+        doc = (Document) load("staff", builder);
+        addrList = doc.getElementsByTagName("name");
+        addrNode = addrList.item(0);
+        state = addrNode.hasAttributes();
+        assertFalse("throw_False", state);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that hasAttributes method returns true value.",
+        method = "hasAttributes",
+        args = {}
+    )
+    public void testHasAttributes2() throws Throwable {
+        Document doc;
+        NodeList addrList;
+        Node addrNode;
+        boolean state;
+        doc = (Document) load("staff", builder);
+        addrList = doc.getElementsByTagName("address");
+        addrNode = addrList.item(0);
+        state = addrNode.hasAttributes();
+        assertTrue("throw_True", state);
+    }
+
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/ImportNode.java b/xml/src/test/java/tests/org/w3c/dom/ImportNode.java
new file mode 100644
index 0000000..de39392
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/ImportNode.java
@@ -0,0 +1,604 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Text;
+import org.w3c.dom.Node;
+import org.w3c.dom.Element;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.Comment;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.DOMException;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The "importNode(importedNode,deep)" method for a Document should import the
+ * given importedNode into that Document. The importedNode is of type Attr. The
+ * ownerElement is set to null. Specified flag is set to true. Children is
+ * imported.
+ * 
+ * Create a new attribute whose name is "elem:attr1" in a different document.
+ * Create a child Text node with value "importedText" for the attribute node
+ * above. Invoke method importNode(importedNode,deep) on this document with
+ * importedNode being the newly created attribute. Method should return a node
+ * whose name matches "elem:attr1" and a child node whose value equals
+ * "importedText". The returned node should belong to this document whose
+ * systemId is "staff.dtd"
+ * 
+ * @author NIST
+ * @author Mary Brady
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#Core-Document-importNode">http://www.w3.org/TR/DOM-Level-2-Core/core#Core-Document-importNode</a>
+ */
+@TestTargetClass(Document.class) 
+public final class ImportNode extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException.",
+        method = "importNode",
+        args = {org.w3c.dom.Node.class, boolean.class}
+    )
+    public void _testImportNode1() throws Throwable {
+        Document doc;
+        Document aNewDoc;
+        Attr newAttr;
+        Text importedChild;
+        Node aNode;
+        Document ownerDocument;
+        Element attrOwnerElement;
+        DocumentType docType;
+        String system;
+        boolean specified;
+        NodeList childList;
+        String nodeName;
+        Node child;
+        String childValue;
+        List<String> expectedResult = new ArrayList<String>();
+        expectedResult.add("elem:attr1");
+        expectedResult.add("importedText");
+
+        doc = (Document) load("staffNS", builder);
+        aNewDoc = (Document) load("staffNS", builder);
+        newAttr = aNewDoc.createAttribute("elem:attr1");
+        importedChild = aNewDoc.createTextNode("importedText");
+        aNode = newAttr.appendChild(importedChild);
+        aNode = doc.importNode(newAttr, false);
+        ownerDocument = aNode.getOwnerDocument();
+        docType = ownerDocument.getDoctype();
+        system = docType.getSystemId();
+        assertNotNull("aNode", aNode);
+        assertURIEquals("systemId", null, null, null, "staffNS.dtd", null,
+                null, null, null, system);
+        attrOwnerElement = ((Attr) /* Node */aNode).getOwnerElement();
+        assertNull("ownerElement", attrOwnerElement);
+        specified = ((Attr) /* Node */aNode).getSpecified();
+        assertTrue("specified", specified);
+        childList = aNode.getChildNodes();
+        assertEquals("childList", 1, childList.getLength());
+        nodeName = aNode.getNodeName();
+        assertEquals("nodeName", "elem:attr1", nodeName);
+        child = aNode.getFirstChild();
+        childValue = child.getNodeValue();
+        assertEquals("childValue", "importedText", childValue);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException.",
+        method = "importNode",
+        args = {org.w3c.dom.Node.class, boolean.class}
+    )
+    public void testImportNode2() throws Throwable {
+        Document doc;
+        Document aNewDoc;
+        CDATASection cDataSec;
+        Node aNode;
+        Document ownerDocument;
+        DocumentType docType;
+        String system;
+        String value;
+        doc = (Document) load("staffNS", builder);
+        aNewDoc = (Document) load("staffNS", builder);
+        cDataSec = aNewDoc.createCDATASection("this is CDATASection data");
+        aNode = doc.importNode(cDataSec, false);
+        ownerDocument = aNode.getOwnerDocument();
+        assertNotNull("ownerDocumentNotNull", ownerDocument);
+        docType = ownerDocument.getDoctype();
+        system = docType.getSystemId();
+        assertURIEquals("dtdSystemId", null, null, null, "staffNS.dtd", null,
+                null, null, null, system);
+        value = aNode.getNodeValue();
+        assertEquals("nodeValue", "this is CDATASection data", value);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException.",
+        method = "importNode",
+        args = {org.w3c.dom.Node.class, boolean.class}
+    )
+    public void testImportNode3() throws Throwable {
+        Document doc;
+        Document aNewDoc;
+        Comment comment;
+        Node aNode;
+        Document ownerDocument;
+        DocumentType docType;
+        String system;
+        String value;
+        doc = (Document) load("staffNS", builder);
+        aNewDoc = (Document) load("staffNS", builder);
+        comment = aNewDoc.createComment("this is a comment");
+        aNode = doc.importNode(comment, false);
+        ownerDocument = aNode.getOwnerDocument();
+        assertNotNull("ownerDocumentNotNull", ownerDocument);
+        docType = ownerDocument.getDoctype();
+        system = docType.getSystemId();
+        assertURIEquals("systemId", null, null, null, "staffNS.dtd", null,
+                null, null, null, system);
+        value = aNode.getNodeValue();
+        assertEquals("nodeValue", "this is a comment", value);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException.",
+        method = "importNode",
+        args = {org.w3c.dom.Node.class, boolean.class}
+    )
+    public void testImportNode4() throws Throwable {
+        Document doc;
+        Document aNewDoc;
+        DocumentFragment docFrag;
+        Comment comment;
+        Node aNode;
+        NodeList children;
+        Node child;
+        String childValue;
+        doc = (Document) load("staff", builder);
+        aNewDoc = (Document) load("staff", builder);
+        docFrag = aNewDoc.createDocumentFragment();
+        comment = aNewDoc.createComment("descendant1");
+        aNode = docFrag.appendChild(comment);
+        aNode = doc.importNode(docFrag, true);
+        children = aNode.getChildNodes();
+        assertEquals("throw_Size", 1, children.getLength());
+        child = aNode.getFirstChild();
+        childValue = child.getNodeValue();
+        assertEquals("descendant1", "descendant1", childValue);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException.",
+        method = "importNode",
+        args = {org.w3c.dom.Node.class, boolean.class}
+    )
+    public void testImportNode5() throws Throwable {
+        Document doc;
+        Document aNewDoc;
+        Element element;
+        Node aNode;
+        boolean hasChild;
+        Document ownerDocument;
+        DocumentType docType;
+        String system;
+        String name;
+        NodeList addresses;
+        doc = (Document) load("staffNS", builder);
+        aNewDoc = (Document) load("staffNS", builder);
+        addresses = aNewDoc.getElementsByTagName("emp:address");
+        element = (Element) addresses.item(0);
+        assertNotNull("empAddressNotNull", element);
+        aNode = doc.importNode(element, false);
+        hasChild = aNode.hasChildNodes();
+        assertFalse("hasChild", hasChild);
+        ownerDocument = aNode.getOwnerDocument();
+        docType = ownerDocument.getDoctype();
+        system = docType.getSystemId();
+        assertURIEquals("dtdSystemId", null, null, null, "staffNS.dtd", null,
+                null, null, null, system);
+        name = aNode.getNodeName();
+        assertEquals("nodeName", "emp:address", name);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException.",
+        method = "importNode",
+        args = {org.w3c.dom.Node.class, boolean.class}
+    )
+    public void testImportNode6() throws Throwable {
+        Document doc;
+        Document aNewDoc;
+        Element element;
+        Node aNode;
+        boolean hasChild;
+        String name;
+        Node child;
+        String value;
+        NodeList addresses;
+        doc = (Document) load("staffNS", builder);
+        aNewDoc = (Document) load("staffNS", builder);
+        addresses = aNewDoc.getElementsByTagName("emp:address");
+        element = (Element) addresses.item(0);
+        assertNotNull("empAddressNotNull", element);
+        aNode = doc.importNode(element, true);
+        hasChild = aNode.hasChildNodes();
+        assertTrue("throw_True", hasChild);
+        name = aNode.getNodeName();
+        assertEquals("nodeName", "emp:address", name);
+        child = aNode.getFirstChild();
+        value = child.getNodeValue();
+        assertEquals("nodeValue", "27 South Road. Dallas, texas 98556", value);
+    }
+
+// Assumes validation.
+//    public void testImportNode7() throws Throwable {
+//        Document doc;
+//        Document aNewDoc;
+//        Element element;
+//        Node aNode;
+//        NamedNodeMap attributes;
+//        String name;
+//        Node attr;
+//        String lname;
+//        String namespaceURI = "http://www.nist.gov";
+//        String qualifiedName = "emp:employee";
+//        doc = (Document) load("staffNS", builder);
+//        aNewDoc = (Document) load("staff", builder);
+//        element = aNewDoc.createElementNS(namespaceURI, qualifiedName);
+//        aNode = doc.importNode(element, false);
+//        attributes = aNode.getAttributes();
+//        assertEquals("throw_Size", 1, attributes.getLength());
+//        name = aNode.getNodeName();
+//        assertEquals("nodeName", "emp:employee", name);
+//        attr = attributes.item(0);
+//        lname = attr.getLocalName();
+//        assertEquals("lname", "defaultAttr", lname);
+//    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException.",
+        method = "importNode",
+        args = {org.w3c.dom.Node.class, boolean.class}
+    )
+    public void testImportNode8() throws Throwable {
+        Document doc;
+        Document aNewDoc;
+        DocumentFragment docFrag;
+        Node aNode;
+        boolean hasChild;
+        Document ownerDocument;
+        DocumentType docType;
+        String system;
+        doc = (Document) load("staffNS", builder);
+        aNewDoc = (Document) load("staffNS", builder);
+        docFrag = aNewDoc.createDocumentFragment();
+        aNode = doc.importNode(docFrag, false);
+        hasChild = aNode.hasChildNodes();
+        assertFalse("hasChild", hasChild);
+        ownerDocument = aNode.getOwnerDocument();
+        docType = ownerDocument.getDoctype();
+        system = docType.getSystemId();
+        assertURIEquals("system", null, null, null, "staffNS.dtd", null, null,
+                null, null, system);
+    }
+
+// Assumes validation.
+//    public void testImportNode9() throws Throwable {
+//        Document doc;
+//        Document aNewDoc;
+//
+//        NamedNodeMap entityList;
+//        Entity entity2;
+//        Entity entity1;
+//        Document ownerDocument;
+//        DocumentType docType;
+//        String system;
+//        String entityName;
+//        String publicVal;
+//        String notationName;
+//        doc = (Document) load("staffNS", builder);
+//        aNewDoc = (Document) load("staffNS", builder);
+//        docType = aNewDoc.getDoctype();
+//        entityList = docType.getEntities();
+//        assertNotNull("entitiesNotNull", entityList);
+//        entity2 = (Entity) entityList.getNamedItem("ent6");
+//        entity1 = (Entity) doc.importNode(entity2, false);
+//        ownerDocument = entity1.getOwnerDocument();
+//        docType = ownerDocument.getDoctype();
+//        system = docType.getSystemId();
+//        assertURIEquals("dtdSystemId", null, null, null, "staffNS.dtd", null,
+//                null, null, null, system);
+//        entityName = entity1.getNodeName();
+//        assertEquals("entityName", "ent6", entityName);
+//        publicVal = entity1.getPublicId();
+//        assertEquals("entityPublicId", "uri", publicVal);
+//        system = entity1.getSystemId();
+//        assertURIEquals("entitySystemId", null, null, null, "file", null, null,
+//                null, null, system);
+//        notationName = entity1.getNotationName();
+//        assertEquals("notationName", "notation2", notationName);
+//    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException.",
+        method = "importNode",
+        args = {org.w3c.dom.Node.class, boolean.class}
+    )
+    public void testImportNode10() throws Throwable {
+        Document doc;
+        Document aNewDoc;
+        EntityReference entRef;
+        Node aNode;
+        Document ownerDocument;
+        DocumentType docType;
+        String system;
+        String name;
+        doc = (Document) load("staffNS", builder);
+        aNewDoc = (Document) load("staffNS", builder);
+        entRef = aNewDoc.createEntityReference("entRef1");
+        assertNotNull("createdEntRefNotNull", entRef);
+        entRef.setNodeValue("entRef1Value");
+        aNode = doc.importNode(entRef, false);
+        ownerDocument = aNode.getOwnerDocument();
+        docType = ownerDocument.getDoctype();
+        system = docType.getSystemId();
+        assertURIEquals("systemId", null, null, null, "staffNS.dtd", null,
+                null, null, null, system);
+        name = aNode.getNodeName();
+        assertEquals("nodeName", "entRef1", name);
+    }
+
+// Assumes validation
+//    public void testImportNode11() throws Throwable {
+//        Document doc;
+//        Document aNewDoc;
+//        EntityReference entRef;
+//        Node aNode;
+//        String name;
+//        Node child;
+//        String childValue;
+//        doc = (Document) load("staff", builder);
+//        aNewDoc = (Document) load("staff", builder);
+//        entRef = aNewDoc.createEntityReference("ent3");
+//        assertNotNull("createdEntRefNotNull", entRef);
+//        aNode = doc.importNode(entRef, true);
+//        name = aNode.getNodeName();
+//        assertEquals("entityName", "ent3", name);
+//        child = aNode.getFirstChild();
+//        assertNotNull("child", child);
+//        childValue = child.getNodeValue();
+//        assertEquals("childValue", "Texas", childValue);
+//    }
+
+// Assumes validation.
+//    public void testImportNode12() throws Throwable {
+//        Document doc;
+//        Document aNewDoc;
+//        DocumentType doc1Type;
+//        NamedNodeMap entityList;
+//        Entity entity2;
+//        Entity entity1;
+//        Document ownerDocument;
+//        DocumentType docType;
+//        String system;
+//        String entityName;
+//        Node child;
+//        String childName;
+//        doc = (Document) load("staffNS", builder);
+//        aNewDoc = (Document) load("staffNS", builder);
+//        doc1Type = aNewDoc.getDoctype();
+//        entityList = doc1Type.getEntities();
+//        assertNotNull("entitiesNotNull", entityList);
+//        entity2 = (Entity) entityList.getNamedItem("ent4");
+//        entity1 = (Entity) doc.importNode(entity2, true);
+//        ownerDocument = entity1.getOwnerDocument();
+//        docType = ownerDocument.getDoctype();
+//        system = docType.getSystemId();
+//        assertURIEquals("systemId", null, null, null, "staffNS.dtd", null,
+//                null, null, null, system);
+//        entityName = entity1.getNodeName();
+//        assertEquals("entityName", "ent4", entityName);
+//        child = entity1.getFirstChild();
+//        assertNotNull("notnull", child);
+//        childName = child.getNodeName();
+//        assertEquals("childName", "entElement1", childName);
+//    }
+
+// Assumes validation
+//    public void testImportNode13() throws Throwable {
+//        Document doc;
+//        Document aNewDoc;
+//        DocumentType doc1Type;
+//        NamedNodeMap notationList;
+//        Notation notation;
+//        Notation aNode;
+//        Document ownerDocument;
+//        DocumentType docType;
+//        String system;
+//        String publicVal;
+//        doc = (Document) load("staffNS", builder);
+//        aNewDoc = (Document) load("staffNS", builder);
+//        doc1Type = aNewDoc.getDoctype();
+//        notationList = doc1Type.getNotations();
+//        assertNotNull("notationsNotNull", notationList);
+//        notation = (Notation) notationList.getNamedItem("notation1");
+//        aNode = (Notation) doc.importNode(notation, false);
+//        ownerDocument = aNode.getOwnerDocument();
+//        docType = ownerDocument.getDoctype();
+//        system = docType.getSystemId();
+//        assertURIEquals("systemId", null, null, null, "staffNS.dtd", null,
+//                null, null, null, system);
+//        publicVal = aNode.getPublicId();
+//        assertEquals("publicId", "notation1File", publicVal);
+//        system = aNode.getSystemId();
+//        assertNull("notationSystemId", system);
+//    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException.",
+        method = "importNode",
+        args = {org.w3c.dom.Node.class, boolean.class}
+    )
+    public void testImportNode14() throws Throwable {
+        Document doc;
+        Document aNewDoc;
+        ProcessingInstruction pi;
+        ProcessingInstruction aNode;
+        Document ownerDocument;
+        DocumentType docType;
+        String system;
+        String target;
+        String data;
+        
+        doc = (Document) load("staffNS", builder);
+        aNewDoc = (Document) load("staffNS", builder);
+        pi = aNewDoc.createProcessingInstruction("target1", "data1");
+        aNode = (ProcessingInstruction) doc.importNode(pi, false);
+        ownerDocument = aNode.getOwnerDocument();
+        assertNotNull("ownerDocumentNotNull", ownerDocument);
+        docType = ownerDocument.getDoctype();
+        system = docType.getSystemId();
+        assertURIEquals("systemId", null, null, null, "staffNS.dtd", null,
+                null, null, null, system);
+        target = aNode.getTarget();
+        assertEquals("piTarget", "target1", target);
+        data = aNode.getData();
+        assertEquals("piData", "data1", data);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException.",
+        method = "importNode",
+        args = {org.w3c.dom.Node.class, boolean.class}
+    )
+    public void testImportNode15() throws Throwable {
+        Document doc;
+        Document aNewDoc;
+        Text text;
+        Node aNode;
+        Document ownerDocument;
+        DocumentType docType;
+        String system;
+        String value;
+        doc = (Document) load("staffNS", builder);
+        aNewDoc = (Document) load("staffNS", builder);
+        text = aNewDoc.createTextNode("this is text data");
+        aNode = doc.importNode(text, false);
+        ownerDocument = aNode.getOwnerDocument();
+        assertNotNull("ownerDocumentNotNull", ownerDocument);
+        docType = ownerDocument.getDoctype();
+        system = docType.getSystemId();
+        assertURIEquals("systemId", null, null, null, "staffNS.dtd", null,
+                null, null, null, system);
+        value = aNode.getNodeValue();
+        assertEquals("nodeValue", "this is text data", value);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that importNode method throws DOMException with NOT_SUPPORTED_ERR code.",
+        method = "importNode",
+        args = {org.w3c.dom.Node.class, boolean.class}
+    )
+    public void testImportNode16() throws Throwable {
+        Document doc;
+        Document anotherDoc;
+        DocumentType docType;
+
+        doc = (Document) load("staffNS", builder);
+        anotherDoc = (Document) load("staffNS", builder);
+        docType = anotherDoc.getDoctype();
+
+        {
+            boolean success = false;
+            try {
+                doc.importNode(docType, false);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NOT_SUPPORTED_ERR);
+            }
+            assertTrue("throw_NOT_SUPPORTED_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that importNode method throws DOMException with NOT_SUPPORTED_ERR code.",
+        method = "importNode",
+        args = {org.w3c.dom.Node.class, boolean.class}
+    )
+    public void testImportNode17() throws Throwable {
+        Document doc;
+        Document anotherDoc;
+
+        doc = (Document) load("staffNS", builder);
+        anotherDoc = (Document) load("staffNS", builder);
+
+        {
+            boolean success = false;
+            try {
+                doc.importNode(anotherDoc, false);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NOT_SUPPORTED_ERR);
+            }
+            assertTrue("throw_NOT_SUPPORTED_ERR", success);
+        }
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/InternalSubset.java b/xml/src/test/java/tests/org/w3c/dom/InternalSubset.java
new file mode 100644
index 0000000..f8f306c
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/InternalSubset.java
@@ -0,0 +1,92 @@
+
+/*
+This Java source file was generated by test-to-java.xsl
+and is a derived work from the source document.
+The source document contained the following notice:
+
+
+
+Copyright (c) 2001-2004 World Wide Web Consortium, 
+(Massachusetts Institute of Technology, Institut National de
+Recherche en Informatique et en Automatique, Keio University).  All 
+Rights Reserved.  This program is distributed under the W3C's Software
+Intellectual Property License.  This program is distributed in the 
+hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+PURPOSE.  
+
+See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+*/
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Document;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ *     The "getInternalSubset()" method returns 
+ *    the internal subset as a string or null if there is none.
+ *    This does not contain the delimiting brackets.
+ *    
+ *    Retrieve the documenttype.
+ *    Apply the "getInternalSubset()" method.  Null is returned since there 
+ *    is not an internal subset.
+* @author NIST
+* @author Mary Brady
+* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-Core-DocType-internalSubset">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-Core-DocType-internalSubset</a>
+*/
+@TestTargetClass(DocumentType.class) 
+public final class InternalSubset extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+   /**
+    * Runs the test case.
+    * @throws Throwable Any uncaught exception causes test to fail
+    */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify that getInternalSubset method returns the internal subset as a string.",
+        method = "getInternalSubset",
+        args = {}
+    )
+   public void testGetInternalSubset() throws Throwable {
+      Document doc;
+      DocumentType docType;
+      String internal;
+      doc = (Document) load("staff2", builder);
+      docType = doc.getDoctype();
+      internal = docType.getInternalSubset();
+      assertNull("internalSubsetNull", internal);
+      }
+   
+}
+
diff --git a/xml/src/test/java/tests/org/w3c/dom/IsSupported.java b/xml/src/test/java/tests/org/w3c/dom/IsSupported.java
new file mode 100644
index 0000000..318a81d
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/IsSupported.java
@@ -0,0 +1,272 @@
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The "feature" parameter in the isSupported(feature,version)" method is the
+ * name of the feature and the version is the version number of the feature to
+ * test. XXX is NOT a legal value for the feature parameter. The method should
+ * return "false" since XXX is not a valid feature.
+ * 
+ * Retrieve the root node of the DOM document by invoking the
+ * "getDocumentElement()" method. This should create a node object on which the
+ * "isSupported(feature,version)" method is invoked with "feature" equal to
+ * "XXX" and version to "1.0". The method should return a boolean "false" since
+ * XXX is not a valid feature.
+ * 
+ * @author NIST
+ * @author Mary Brady
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#Level-2-Core-Node-supports">http://www.w3.org/TR/DOM-Level-2-Core/core#Level-2-Core-Node-supports</a>
+ */
+@TestTargetClass(Document.class) 
+public final class IsSupported extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that isSupported method returns false.",
+        method = "isSupported",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testIsSupported1() throws Throwable {
+        Document doc;
+        Node rootNode;
+        boolean state;
+        doc = (Document) load("staff", builder);
+        rootNode = doc.getDocumentElement();
+        state = rootNode.isSupported("XXX", "1.0");
+        assertFalse("throw_False", state);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that isSupported method returns false value.",
+        method = "isSupported",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testIsSupported2() throws Throwable {
+        Document doc;
+        Node rootNode;
+        boolean state;
+        doc = (Document) load("staff", builder);
+        rootNode = doc.getDocumentElement();
+        state = rootNode.isSupported("XML", "9.0");
+        assertFalse("throw_False", state);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that isSupported method returns true value.",
+        method = "isSupported",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testIsSupported4() throws Throwable {
+        Document doc;
+        Node rootNode;
+        boolean state;
+        doc = (Document) load("staff", builder);
+        rootNode = doc.getDocumentElement();
+        state = rootNode.isSupported("xml", "1.0");
+        assertTrue("throw_True", state);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that isSupported method returns true value.",
+        method = "isSupported",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testIsSupported5() throws Throwable {
+        Document doc;
+        Node rootNode;
+        boolean state;
+        doc = (Document) load("staff", builder);
+        rootNode = doc.getDocumentElement();
+        state = rootNode.isSupported("core", "2.0");
+        assertTrue("throw_True", state);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that isSupported method returns true value.",
+        method = "isSupported",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testIsSupported6() throws Throwable {
+        Document doc;
+        Node rootNode;
+        boolean state;
+        doc = (Document) load("staff", builder);
+        rootNode = doc.getDocumentElement();
+        state = rootNode.isSupported("xml", "2.0");
+        assertTrue("throw_True", state);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that isSupported method returns true value.",
+        method = "isSupported",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testIsSupported7() throws Throwable {
+        Document doc;
+        Node rootNode;
+        boolean state;
+        doc = (Document) load("staff", builder);
+        rootNode = doc.getDocumentElement();
+        state = rootNode.isSupported("XML", "");
+        assertTrue("throw_True", state);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that isSupported method returns true value.",
+        method = "isSupported",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testIsSupported9() throws Throwable {
+        Document doc;
+        Node rootNode;
+        boolean state;
+        doc = (Document) load("staff", builder);
+        rootNode = doc.getDocumentElement();
+        state = rootNode.isSupported("XML", "1.0");
+        assertTrue("throw_True", state);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that isSupported method returns true.",
+        method = "isSupported",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testIsSupported10() throws Throwable {
+        Document doc;
+        Node rootNode;
+        boolean state;
+        doc = (Document) load("staff", builder);
+        rootNode = doc.getDocumentElement();
+        state = rootNode.isSupported("CORE", "2.0");
+        assertTrue("throw_True", state);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that isSupported method returns true.",
+        method = "isSupported",
+        args = {java.lang.String.class, java.lang.String.class}
+    )              
+    public void testIsSupported11() throws Throwable {
+        Document doc;
+        Node rootNode;
+        boolean state;
+        doc = (Document) load("staff", builder);
+        rootNode = doc.getDocumentElement();
+        state = rootNode.isSupported("XML", "2.0");
+        assertTrue("throw_True", state);
+    }
+              
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "",
+        method = "isSupported",
+        args = {java.lang.String.class, java.lang.String.class}
+    )       
+    public void testIsSupported12() throws Throwable {
+        List<String> features = new ArrayList<String>();
+        features.add("Core");
+        features.add("XML");
+        features.add("HTML");
+        features.add("Views");
+        features.add("StyleSheets");
+        features.add("CSS");
+        features.add("CSS2");
+        features.add("Events");
+        features.add("UIEvents");
+        features.add("MouseEvents");
+        features.add("MutationEvents");
+        features.add("HTMLEvents");
+        features.add("Range");
+        features.add("Traversal");
+        features.add("bogus.bogus.bogus");
+
+        Document doc;
+        Node rootNode;
+        String featureElement;
+        boolean state;
+        doc = (Document) load("staff", builder);
+        rootNode = doc.getDocumentElement();
+        state = rootNode.isSupported("Core", "2.0");
+        assertTrue("Core2", state);
+        for (int indexN10078 = 0; indexN10078 < features.size(); indexN10078++) {
+            featureElement = (String) features.get(indexN10078);
+            state = rootNode.isSupported(featureElement, "1.0");
+        }
+        for (int indexN10083 = 0; indexN10083 < features.size(); indexN10083++) {
+            featureElement = (String) features.get(indexN10083);
+            state = rootNode.isSupported(featureElement, "2.0");
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that isSupported method returns correct value if it has empty string as a version parameter.",
+        method = "isSupported",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testIsSupported13() throws Throwable {
+        Document doc;
+        Node rootNode;
+        boolean state;
+        doc = (Document) load("staff", builder);
+        rootNode = doc.getDocumentElement();
+        state = rootNode.isSupported("Core", "");
+        assertTrue("Core", state);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that isSupported method returns correct value if it has null as a version parameter.",
+        method = "isSupported",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testIsSupported14() throws Throwable {
+        Document doc;
+        Node rootNode;
+        boolean state;
+        String nullString = null;
+
+        doc = (Document) load("staff", builder);
+        rootNode = doc.getDocumentElement();
+        state = rootNode.isSupported("Core", nullString);
+        assertTrue("Core", state);
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/LocalName.java b/xml/src/test/java/tests/org/w3c/dom/LocalName.java
new file mode 100644
index 0000000..3f1d9c3
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/LocalName.java
@@ -0,0 +1,132 @@
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Element;
+import org.w3c.dom.Attr;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The "getLocalName()" method for a Node returns the local part of the
+ * qualified name of this node, and for nodes of any type other than
+ * ELEMENT_NODE and ATTRIBUTE_NODE and nodes created with a DOM Level 1 method,
+ * this is null.
+ * 
+ * Retrieve the first emp:address node and get the attributes of this node."
+ * Then apply the getLocalName() method to the emp:domestic attribute. The
+ * method should return "domestic".
+ * 
+ * @author NIST
+ * @author Mary Brady
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSLocalN">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSLocalN</a>
+ */
+@TestTargetClass(Node.class) 
+public final class LocalName extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies positive functionality.",
+        method = "getLocalName",
+        args = {}
+    )
+    public void testGetLocalName1() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Element testAddr;
+        Attr addrAttr;
+        String localName;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("emp:address");
+        testAddr = (Element) elementList.item(0);
+        assertNotNull("empAddrNotNull", testAddr);
+        addrAttr = testAddr.getAttributeNode("emp:domestic");
+        localName = addrAttr.getLocalName();
+        assertEquals("localName", "domestic", localName);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that getLocalName method returns null.",
+        method = "getLocalName",
+        args = {}
+    )
+    public void testGetLocalName2() throws Throwable {
+        Document doc;
+        Node createdNode;
+        String localName;
+        doc = (Document) load("staffNS", builder);
+        createdNode = doc.createElement("test:employee");
+        localName = createdNode.getLocalName();
+        assertNull("localNameNull", localName);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that getLocalName method returns null.",
+        method = "getLocalName",
+        args = {}
+    )
+    public void testGetLocalName3() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Node testEmployee;
+        Node textNode;
+        String localName;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("employeeId");
+        testEmployee = elementList.item(0);
+        textNode = testEmployee.getFirstChild();
+        localName = textNode.getLocalName();
+        assertNull("textNodeLocalName", localName);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies positive functionality.",
+        method = "getLocalName",
+        args = {}
+    )
+    public void testGetLocalName4() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Node testEmployee;
+        String employeeLocalName;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("employee");
+        testEmployee = elementList.item(0);
+        employeeLocalName = testEmployee.getLocalName();
+        assertEquals("lname", "employee", employeeLocalName);
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/NamedNodeMapGetNamedItemNS.java b/xml/src/test/java/tests/org/w3c/dom/NamedNodeMapGetNamedItemNS.java
new file mode 100644
index 0000000..e4ab1df
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/NamedNodeMapGetNamedItemNS.java
@@ -0,0 +1,229 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001-2004 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * Using the method getNamedItemNS, retreive the entity "ent1" and notation
+ * "notation1" from a NamedNodeMap of this DocumentTypes entities and notations.
+ * Both should be null since entities and notations are not namespaced.
+ * 
+ * @author IBM
+ * @author Neil Delima
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-getNamedItemNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-getNamedItemNS</a>
+ * @see <a
+ *      href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=259">http://www.w3.org/Bugs/Public/show_bug.cgi?id=259</a>
+ * @see <a
+ *      href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=407">http://www.w3.org/Bugs/Public/show_bug.cgi?id=407</a>
+ * @see <a
+ *      href="http://lists.w3.org/Archives/Member/w3c-dom-ig/2003Nov/0016.html">http://lists.w3.org/Archives/Member/w3c-dom-ig/2003Nov/0016.html</a>
+ */
+@TestTargetClass(NamedNodeMap.class) 
+public final class NamedNodeMapGetNamedItemNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+// Assumes validation.    
+//    public void testGetNamedItemNS1() throws Throwable {
+//        Document doc;
+//        DocumentType docType;
+//        NamedNodeMap entities;
+//        NamedNodeMap notations;
+//        Entity entity;
+//        Notation notation;
+//
+//        String nullNS = null;
+//
+//        doc = (Document) load("staffNS", builder);
+//        docType = doc.getDoctype();
+//        entities = docType.getEntities();
+//        assertNotNull("entitiesNotNull", entities);
+//        notations = docType.getNotations();
+//        assertNotNull("notationsNotNull", notations);
+//        entity = (Entity) entities.getNamedItemNS(nullNS, "ent1");
+//        assertNotNull("entityNull", entity);
+//        notation = (Notation) notations.getNamedItemNS(nullNS, "notation1");
+//        assertNotNull("notationNull", notation);
+//    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "getNamedItemNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetNamedItemNS2() throws Throwable {
+        Document doc;
+        NamedNodeMap attributes;
+        Node element;
+        Attr attribute;
+        NodeList elementList;
+        String attrName;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagNameNS("http://www.nist.gov",
+                "address");
+        element = elementList.item(1);
+        attributes = element.getAttributes();
+        attribute = (Attr) attributes.getNamedItemNS("http://www.nist.gov",
+                "domestic");
+        attrName = attribute.getNodeName();
+        assertEquals("namednodemapgetnameditemns02", "emp:domestic", attrName);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "getNamedItemNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetNamedItemNS3() throws Throwable {
+        Document doc;
+        NamedNodeMap attributes;
+        Node element;
+        Attr attribute;
+        Attr newAttr1;
+        Attr newAttr2;
+
+        String attrName;
+        doc = (Document) load("staffNS", builder);
+        element = doc.createElementNS("http://www.w3.org/DOM/Test", "root");
+        newAttr1 = doc.createAttributeNS("http://www.w3.org/DOM/L1", "L1:att");
+        ((Element) /* Node */element).setAttributeNodeNS(newAttr1);
+        newAttr2 = doc.createAttributeNS("http://www.w3.org/DOM/L2", "L2:att");
+        ((Element) /* Node */element).setAttributeNodeNS(newAttr2);
+        attributes = element.getAttributes();
+        attribute = (Attr) attributes.getNamedItemNS(
+                "http://www.w3.org/DOM/L2", "att");
+        attrName = attribute.getNodeName();
+        assertEquals("namednodemapgetnameditemns03", "L2:att", attrName);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "getNamedItemNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetNamedItemNS4() throws Throwable {
+        Document doc;
+        NamedNodeMap attributes;
+        Element element;
+        Attr attribute;
+        Attr newAttr1;
+        NodeList elementList;
+        String attrName;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagNameNS("*", "address");
+        element = (Element) elementList.item(1);
+        newAttr1 = doc.createAttributeNS("http://www.w3.org/DOM/L1", "street");
+        element.setAttributeNodeNS(newAttr1);
+        attributes = element.getAttributes();
+        attribute = (Attr) attributes.getNamedItemNS(
+                "http://www.w3.org/DOM/L1", "street");
+        attrName = attribute.getNodeName();
+        assertEquals("namednodemapgetnameditemns04", "street", attrName);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "getNamedItemNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testGetNamedItemNS5() throws Throwable {
+        Document doc;
+        NamedNodeMap attributes;
+        Node element;
+        Attr attribute;
+        NodeList elementList;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagNameNS("*", "address");
+        element = elementList.item(1);
+        attributes = element.getAttributes();
+        attribute = (Attr) attributes.getNamedItemNS("*", "street");
+        assertNull("namednodemapgetnameditemns05", attribute);
+    }
+
+// Assumes validation.
+//    public void testGetNamedItemNS6() throws Throwable {
+//        Document doc;
+//        NamedNodeMap attributesMap1;
+//        NamedNodeMap attributesMap2;
+//        Element element;
+//        Attr attribute;
+//        Attr newAttr1;
+//
+//        NodeList elementList;
+//        String attrName;
+//        doc = (Document) load("staffNS", builder);
+//        elementList = doc.getElementsByTagNameNS("*", "address");
+//        element = (Element) elementList.item(1);
+//        attributesMap1 = element.getAttributes();
+//        attributesMap2 = element.getAttributes();
+//        newAttr1 = doc.createAttributeNS("http://www.w3.org/DOM/L1", "street");
+//        element.setAttributeNodeNS(newAttr1);
+//        attribute = (Attr) attributesMap1.getNamedItemNS(
+//                "http://www.w3.org/DOM/L1", "street");
+//        attrName = attribute.getNodeName();
+//        assertEquals("namednodemapgetnameditemnsMap106", "street", attrName);
+//        attribute = (Attr) attributesMap2.getNamedItemNS(
+//                "http://www.w3.org/DOM/L1", "street");
+//        attrName = attribute.getNodeName();
+//        assertEquals("namednodemapgetnameditemnsMap206", "street", attrName);
+//    }
+
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/NamedNodeMapRemoveNamedItemNS.java b/xml/src/test/java/tests/org/w3c/dom/NamedNodeMapRemoveNamedItemNS.java
new file mode 100644
index 0000000..16a6cda
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/NamedNodeMapRemoveNamedItemNS.java
@@ -0,0 +1,342 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.DOMException;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The method removeNamedItemNS removes a node specified by local name and
+ * namespace
+ * 
+ * Retreive an attribute node and then remove from the NamedNodeMap. Verify if
+ * the attribute node was actually remove from the node map.
+ * 
+ * @author IBM
+ * @author Neil Delima
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-D58B193">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-D58B193</a>
+ */
+@TestTargetClass(NamedNodeMap.class) 
+public final class NamedNodeMapRemoveNamedItemNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException.",
+        method = "removeNamedItemNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testRemoveNamedItemNS1() throws Throwable {
+        Document doc;
+        NamedNodeMap attributes;
+        Node element;
+        Attr attribute;
+        NodeList elementList;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagNameNS("http://www.nist.gov",
+                "address");
+        element = elementList.item(1);
+        attributes = element.getAttributes();
+        attribute = (Attr) attributes.removeNamedItemNS("http://www.nist.gov",
+                "domestic");
+        attribute = (Attr) attributes.getNamedItemNS("http://www.nist.gov",
+                "domestic");
+        assertNull("namednodemapremovenameditemns01", attribute);
+    }
+
+// Assumes validation.
+//    public void testRemoveNamedItemNS2() throws Throwable {
+//        Document doc;
+//        NamedNodeMap attributes;
+//        Node element;
+//        Attr attribute;
+//        NodeList elementList;
+//        String attrValue;
+//        String nullNS = null;
+//
+//        doc = (Document) load("staffNS", builder);
+//        elementList = doc.getElementsByTagNameNS("http://www.nist.gov",
+//                "employee");
+//        element = elementList.item(1);
+//        attributes = element.getAttributes();
+//        attribute = (Attr) attributes.removeNamedItemNS(nullNS, "defaultAttr");
+//        attribute = (Attr) attributes.getNamedItemNS(nullNS, "defaultAttr");
+//        attrValue = attribute.getNodeValue();
+//        assertNotNull("namednodemapremovenameditemns02", attribute);
+//        assertEquals("namednodemapremovenameditemns02_attrValue", "defaultVal",
+//                attrValue);
+//    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException.",
+        method = "removeNamedItemNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testRemoveNamedItemNS3() throws Throwable {
+        Document doc;
+        NamedNodeMap attributes;
+        Node element;
+        Attr attribute;
+
+        Attr attribute1;
+        Attr attribute2;
+        String nodeName;
+        doc = (Document) load("staffNS", builder);
+        element = doc.createElementNS("http://www.w3.org/DOM/Test", "root");
+        attribute1 = doc
+                .createAttributeNS("http://www.w3.org/DOM/L1", "L1:att");
+        ((Element) /* Node */element).setAttributeNodeNS(attribute1);
+        attribute2 = doc
+                .createAttributeNS("http://www.w3.org/DOM/L2", "L2:att");
+        ((Element) /* Node */element).setAttributeNodeNS(attribute2);
+        attributes = element.getAttributes();
+        attribute = (Attr) attributes.removeNamedItemNS(
+                "http://www.w3.org/DOM/L1", "att");
+        attribute = (Attr) attributes.getNamedItemNS(
+                "http://www.w3.org/DOM/L2", "att");
+        nodeName = attribute.getNodeName();
+        assertEquals("namednodemapremovenameditemns02", "L2:att", nodeName);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException.",
+        method = "removeNamedItemNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void _testRemoveNamedItemNS4() throws Throwable {
+        Document doc;
+        NamedNodeMap attributes;
+        Node element;
+        Attr attribute;
+
+        NodeList elementList;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagNameNS("*", "employee");
+        element = elementList.item(0);
+        attributes = element.getAttributes();
+        attributes.removeNamedItemNS("http://www.w3.org/2000/xmlns/", "xmlns");
+        attribute = (Attr) attributes.getNamedItemNS(
+                "http://www.w3.org/2000/xmlns/", "xmlns");
+        assertNull("namednodemapremovenameditemns04_1", attribute);
+        attributes.removeNamedItemNS("http://www.w3.org/2000/xmlns/", "dmstc");
+        attribute = (Attr) attributes.getNamedItemNS(
+                "http://www.w3.org/2000/xmlns/", "dmstc");
+        assertNull("namednodemapremovenameditemns04_2", attribute);
+    }
+
+// Assumes validation.
+//    public void testRemoveNamedItemNS5() throws Throwable {
+//        Document doc;
+//        DocumentType docType;
+//        NamedNodeMap entities;
+//        NamedNodeMap notations;
+//
+//        String nullNS = null;
+//
+//        doc = (Document) load("staffNS", builder);
+//        docType = doc.getDoctype();
+//        entities = docType.getEntities();
+//        assertNotNull("entitiesNotNull", entities);
+//        notations = docType.getNotations();
+//        assertNotNull("notationsNotNull", notations);
+//
+//        try {
+//            entities.removeNamedItemNS(nullNS, "ent1");
+//            fail("entity_throw_DOMException");
+//
+//        } catch (DOMException ex) {
+//            switch (ex.code) {
+//            case 8:
+//                break;
+//            case 7:
+//                break;
+//            default:
+//                throw ex;
+//            }
+//        }
+//
+//        try {
+//            notations.removeNamedItemNS(nullNS, "notation1");
+//            fail("notation_throw_DOMException");
+//
+//        } catch (DOMException ex) {
+//            switch (ex.code) {
+//            case 8:
+//                break;
+//            case 7:
+//                break;
+//            default:
+//                throw ex;
+//            }
+//        }
+//    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that removeNamedItemNS method throws DOMException with NOT_FOUND_ERR code.",
+        method = "removeNamedItemNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testRemoveNamedItemNS6() throws Throwable {
+        Document doc;
+        NamedNodeMap attributes;
+        Node element;
+
+        NodeList elementList;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagNameNS("http://www.nist.gov",
+                "employee");
+        element = elementList.item(1);
+        attributes = element.getAttributes();
+
+        {
+            boolean success = false;
+            try {
+                attributes.removeNamedItemNS("http://www.Nist.gov", "domestic");
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NOT_FOUND_ERR);
+            }
+            assertTrue("throw_NOT_FOUND_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that removeNamedItemNS method throws DOMException with NOT_FOUND_ERR code.",
+        method = "removeNamedItemNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testRemoveNamedItemNS7() throws Throwable {
+        Document doc;
+        NamedNodeMap attributes;
+        Node element;
+
+        NodeList elementList;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagNameNS("http://www.nist.gov",
+                "employee");
+        element = elementList.item(1);
+        attributes = element.getAttributes();
+
+        {
+            boolean success = false;
+            try {
+                attributes.removeNamedItemNS("http://www.nist.gov", "domestic");
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NOT_FOUND_ERR);
+            }
+            assertTrue("throw_NOT_FOUND_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies that removeNamedItemNS method throws DOMException with NOT_FOUND_ERR code.",
+        method = "removeNamedItemNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testRemoveNamedItemNS8() throws Throwable {
+        Document doc;
+        NamedNodeMap attributes;
+        Element element;
+
+        NodeList elementList;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagNameNS("http://www.nist.gov",
+                "address");
+        element = (Element) elementList.item(1);
+        attributes = element.getAttributes();
+        element.removeAttributeNS("http://www.nist.gov", "domestic");
+
+        {
+            boolean success = false;
+            try {
+                attributes.removeNamedItemNS("http://www.nist.gov", "domestic");
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NOT_FOUND_ERR);
+            }
+            assertTrue("throw_NOT_FOUND_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException.",
+        method = "removeNamedItemNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testRemoveNamedItemNS9() throws Throwable {
+        Document doc;
+        NamedNodeMap attributes;
+        NamedNodeMap newAttributes;
+        Element element;
+        Attr attribute;
+        NodeList elementList;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagNameNS("http://www.nist.gov",
+                "address");
+        element = (Element) elementList.item(1);
+        attributes = element.getAttributes();
+        attribute = (Attr) attributes.removeNamedItemNS("http://www.nist.gov",
+                "domestic");
+        newAttributes = element.getAttributes();
+        attribute = (Attr) newAttributes.getNamedItemNS("http://www.nist.gov",
+                "domestic");
+        assertNull("namednodemapremovenameditemns09", attribute);
+    }
+
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/NamedNodeMapSetNamedItemNS.java b/xml/src/test/java/tests/org/w3c/dom/NamedNodeMapSetNamedItemNS.java
new file mode 100644
index 0000000..e0ec0df
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/NamedNodeMapSetNamedItemNS.java
@@ -0,0 +1,451 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Document;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Element;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.DocumentType;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The method setNamedItemNS adds a node using its namespaceURI and localName.
+ * If a node with that namespace URI and that local name is already present in
+ * this map, it is replaced by the new one.
+ * 
+ * Retreive the first element whose localName is address and namespaceURI
+ * http://www.nist.gov", and put its attributes into a named node map. Create a
+ * new attribute node and add it to this map. Verify if the attr node was
+ * successfully added by checking the nodeName of the retreived atttribute.
+ * 
+ * @author IBM
+ * @author Neil Delima
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-getNamedItemNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-getNamedItemNS</a>
+ */
+@TestTargetClass(NamedNodeMap.class) 
+public final class NamedNodeMapSetNamedItemNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            // Changed to configuration #2. This test case just doesn't make
+            // sense without a namespace-aware parser. It actually fails even
+            // on the JDK in that case.
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "setNamedItemNS",
+        args = {org.w3c.dom.Node.class}
+    )
+    public void testSetNamedItemNS1() throws Throwable {
+        Document doc;
+        NamedNodeMap attributes;
+        Node element;
+        Attr attribute;
+
+        Attr newAttr1;
+        NodeList elementList;
+        String attrName;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagNameNS("http://www.nist.gov",
+                "address");
+        element = elementList.item(0);
+        attributes = element.getAttributes();
+        newAttr1 = doc.createAttributeNS("http://www.w3.org/DOM/L1", "streets");
+        ((Element) /* Node */element).setAttributeNodeNS(newAttr1);
+        attribute = (Attr) attributes.getNamedItemNS(
+                "http://www.w3.org/DOM/L1", "streets");
+        attrName = attribute.getNodeName();
+        assertEquals("namednodemapsetnameditemns01", "streets", attrName);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException.",
+        method = "setNamedItemNS",
+        args = {org.w3c.dom.Node.class}
+    )
+    public void testSetNamedItemNS2() throws Throwable {
+        Document doc;
+        NamedNodeMap attributes;
+        Element element;
+        Attr attribute;
+        Attr attribute1;
+
+        String attrName;
+        doc = (Document) load("staffNS", builder);
+        element = doc.createElementNS("http://www.w3.org/DOM/Test", "root");
+        attribute1 = doc
+                .createAttributeNS("http://www.w3.org/DOM/L1", "L1:att");
+        attributes = element.getAttributes();
+        attributes.setNamedItemNS(attribute1);
+        attribute = (Attr) attributes.getNamedItemNS(
+                "http://www.w3.org/DOM/L1", "att");
+        attrName = attribute.getNodeName();
+        assertEquals("namednodemapsetnameditemns02", "L1:att", attrName);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that setNamedItemNS throws DOMException with WRONG_DOCUMENT_ERR code.",
+        method = "setNamedItemNS",
+        args = {org.w3c.dom.Node.class}
+    )
+    public void testSetNamedItemNS3() throws Throwable {
+
+        Document doc;
+        Document docAlt;
+        NamedNodeMap attributes;
+        NamedNodeMap attributesAlt;
+        NodeList elementList;
+        NodeList elementListAlt;
+        Element element;
+        Element elementAlt;
+        Attr attr;
+
+        String nullNS = null;
+
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagNameNS("*", "address");
+        element = (Element) elementList.item(1);
+        attributes = element.getAttributes();
+        docAlt = (Document) load("staffNS", builder);
+        elementListAlt = docAlt.getElementsByTagNameNS("*", "address");
+        elementAlt = (Element) elementListAlt.item(1);
+        attributesAlt = elementAlt.getAttributes();
+        attr = (Attr) attributesAlt.getNamedItemNS(nullNS, "street");
+        attributesAlt.removeNamedItemNS(nullNS, "street");
+
+        {
+            boolean success = false;
+            try {
+                attributes.setNamedItemNS(attr);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.WRONG_DOCUMENT_ERR);
+            }
+            assertTrue("throw_WRONG_DOCUMENT_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that setNamedItemNS throws DOMException with WRONG_DOCUMENT_ERR code.",
+        method = "setNamedItemNS",
+        args = {org.w3c.dom.Node.class}
+    )
+    public void testSetNamedItemNS4() throws Throwable {
+        Document doc;
+        DOMImplementation domImpl;
+        Document docAlt; 
+        DocumentType docType = null;
+
+        NamedNodeMap attributes;
+        NodeList elementList;
+        Element element;
+        Attr attrAlt;
+
+        String nullNS = null;
+
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagNameNS("*", "address");
+        element = (Element) elementList.item(1);
+        attributes = element.getAttributes();
+        domImpl = doc.getImplementation();
+        docAlt = domImpl.createDocument(nullNS, "newDoc", docType);
+        attrAlt = docAlt.createAttributeNS(nullNS, "street");
+
+        {
+            boolean success = false;
+            try {
+                attributes.setNamedItemNS(attrAlt);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.WRONG_DOCUMENT_ERR);
+            }
+            assertTrue("throw_WRONG_DOCUMENT_ERR", success);
+        }
+    }
+
+// Assumes validation.
+//    public void testSetNamedItemNS5() throws Throwable {
+//        Document doc;
+//        DocumentType docType;
+//        NamedNodeMap entities;
+//        NamedNodeMap notations;
+//        Entity entity;
+//        Notation notation;
+//
+//        doc = (Document) load("staffNS", builder);
+//        docType = doc.getDoctype();
+//        entities = docType.getEntities();
+//        assertNotNull("entitiesNotNull", entities);
+//        notations = docType.getNotations();
+//        assertNotNull("notationsNotNull", notations);
+//        entity = (Entity) entities.getNamedItem("ent1");
+//        notation = (Notation) notations.getNamedItem("notation1");
+//
+//        {
+//            boolean success = false;
+//            try {
+//                entities.setNamedItemNS(entity);
+//            } catch (DOMException ex) {
+//                success = (ex.code == DOMException.NO_MODIFICATION_ALLOWED_ERR);
+//            }
+//            assertTrue("throw_NO_MODIFICATION_ALLOWED_ERR_entities", success);
+//        }
+//
+//        {
+//            boolean success = false;
+//            try {
+//                notations.setNamedItemNS(notation);
+//            } catch (DOMException ex) {
+//                success = (ex.code == DOMException.NO_MODIFICATION_ALLOWED_ERR);
+//            }
+//            assertTrue("throw_NO_MODIFICATION_ALLOWED_ERR_notations", success);
+//        }
+//    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that setNamedItemNS throws DOMException with INUSE_ATTRIBUTE_ERR code.",
+        method = "setNamedItemNS",
+        args = {org.w3c.dom.Node.class}
+    )
+    public void testSetNamedItemNS6() throws Throwable {
+        Document doc;
+        NamedNodeMap attributes;
+        NodeList elementList;
+        Element element;
+        Attr attr;
+
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagNameNS("*", "address");
+        element = (Element) elementList.item(0);
+        attributes = element.getAttributes();
+        attr = (Attr) attributes.getNamedItemNS("http://www.usa.com",
+                "domestic");
+        element = (Element) elementList.item(1);
+        attributes = element.getAttributes();
+
+        {
+            boolean success = false;
+            try {
+                attributes.setNamedItemNS(attr);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.INUSE_ATTRIBUTE_ERR);
+            }
+            assertTrue("namednodemapsetnameditemns06", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that setNamedItemNS throws DOMException with INUSE_ATTRIBUTE_ERR code.",
+        method = "setNamedItemNS",
+        args = {org.w3c.dom.Node.class}
+    )
+    public void testSetNamedItemNS7() throws Throwable {
+        Document doc;
+        NamedNodeMap attributes;
+        NodeList elementList;
+        Element element;
+        Attr attr;
+
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagNameNS("*", "address");
+        element = (Element) elementList.item(0);
+        attributes = element.getAttributes();
+        attr = (Attr) attributes.getNamedItemNS("http://www.usa.com",
+                "domestic");
+        element = (Element) elementList.item(1);
+        attributes = element.getAttributes();
+
+        {
+            boolean success = false;
+            try {
+                attributes.setNamedItemNS(attr);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.INUSE_ATTRIBUTE_ERR);
+            }
+            assertTrue("namednodemapsetnameditemns07", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that setNamedItemNS throws DOMException with INUSE_ATTRIBUTE_ERR code.",
+        method = "setNamedItemNS",
+        args = {org.w3c.dom.Node.class}
+    )
+    public void testSetNamedItemNS8() throws Throwable {
+        Document doc;
+        NamedNodeMap attributes;
+        NodeList elementList;
+        Element element;
+        Attr attr;
+
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagNameNS("*", "address");
+        element = (Element) elementList.item(0);
+        attributes = element.getAttributes();
+        attr = (Attr) attributes.getNamedItemNS("http://www.usa.com",
+                "domestic");
+        element = (Element) elementList.item(1);
+        attributes = element.getAttributes();
+
+        {
+            boolean success = false;
+            try {
+                attributes.setNamedItemNS(attr);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.INUSE_ATTRIBUTE_ERR);
+            }
+            assertTrue("namednodemapsetnameditemns08", success);
+        }
+    }
+
+// Assumes validation.
+//    public void testSetNamedItemNS9() throws Throwable {
+//        Document doc;
+//        DocumentType docType;
+//        NamedNodeMap entities;
+//        NamedNodeMap notations;
+//        Attr attr;
+//        doc = (Document) load("staffNS", builder);
+//        docType = doc.getDoctype();
+//        entities = docType.getEntities();
+//        notations = docType.getNotations();
+//        attr = doc.createAttributeNS("http://www.w3.org/DOM/Test", "test");
+//
+//        {
+//            boolean success = false;
+//            try {
+//                entities.setNamedItemNS(attr);
+//            } catch (DOMException ex) {
+//                success = (ex.code == DOMException.NO_MODIFICATION_ALLOWED_ERR);
+//            }
+//            assertTrue("throw_NO_MODIFICATION_ALLOWED_ERR_entities", success);
+//        }
+//
+//        {
+//            boolean success = false;
+//            try {
+//                notations.setNamedItemNS(attr);
+//            } catch (DOMException ex) {
+//                success = (ex.code == DOMException.NO_MODIFICATION_ALLOWED_ERR);
+//            }
+//            assertTrue("throw_NO_MODIFICATION_ALLOWED_ERR_notations", success);
+//        }
+//    }
+
+// Assumes validation.
+//    public void testSetNamedItemNS10() throws Throwable {
+//        Document doc;
+//        DocumentType docType;
+//        NamedNodeMap entities;
+//        NamedNodeMap attributes;
+//        Entity entity;
+//
+//        Element element;
+//        NodeList elementList;
+//
+//        doc = (Document) load("staffNS", builder);
+//        docType = doc.getDoctype();
+//        entities = docType.getEntities();
+//        assertNotNull("entitiesNotNull", entities);
+//        entity = (Entity) entities.getNamedItem("ent1");
+//        elementList = doc.getElementsByTagNameNS("http://www.nist.gov",
+//                "address");
+//        element = (Element) elementList.item(0);
+//        attributes = element.getAttributes();
+//
+//        {
+//            boolean success = false;
+//            try {
+//                attributes.setNamedItemNS(entity);
+//            } catch (DOMException ex) {
+//                success = (ex.code == DOMException.HIERARCHY_REQUEST_ERR);
+//            }
+//            assertTrue("throw_HIERARCHY_REQUEST_ERR", success);
+//        }
+//    }
+
+// Assumes validation.
+//    public void testSetNamedItemNS11() throws Throwable {
+//        Document doc;
+//        DocumentType docType;
+//        NamedNodeMap notations;
+//        NamedNodeMap attributes;
+//        Notation notation;
+//        Element element;
+//        NodeList elementList;
+//
+//        doc = (Document) load("staffNS", builder);
+//        docType = doc.getDoctype();
+//        notations = docType.getNotations();
+//        assertNotNull("notationsNotNull", notations);
+//        notation = (Notation) notations.getNamedItem("notation1");
+//        elementList = doc.getElementsByTagNameNS("http://www.nist.gov",
+//                "address");
+//        element = (Element) elementList.item(0);
+//        attributes = element.getAttributes();
+//
+//        {
+//            boolean success = false;
+//            try {
+//                attributes.setNamedItemNS(notation);
+//            } catch (DOMException ex) {
+//                success = (ex.code == DOMException.HIERARCHY_REQUEST_ERR);
+//            }
+//            assertTrue("throw_HIERARCHY_REQUEST_ERR", success);
+//        }
+//    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/NamespaceURI.java b/xml/src/test/java/tests/org/w3c/dom/NamespaceURI.java
new file mode 100644
index 0000000..dba8b86
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/NamespaceURI.java
@@ -0,0 +1,153 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001-2003 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The "getNamespaceURI()" method for an Attribute returns the namespace URI of
+ * this node, or null if unspecified.
+ * 
+ * Retrieve the first "emp:address" node which has an attribute of
+ * "emp:district" that is specified in the DTD. Invoke the "getNamespaceURI()"
+ * method on the attribute. The method should return "http://www.nist.gov".
+ * 
+ * @author NIST
+ * @author Mary Brady
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSname">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSname</a>
+ * @see <a
+ *      href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=238">http://www.w3.org/Bugs/Public/show_bug.cgi?id=238</a>
+ */
+@TestTargetClass(Attr.class) 
+public final class NamespaceURI extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+// Assumes validation.
+//    public void testGetNamespaceURI1() throws Throwable {
+//        Document doc;
+//        NodeList elementList;
+//        Element testAddr;
+//        Attr addrAttr;
+//        String attrNamespaceURI;
+//        doc = (Document) load("staffNS", builder);
+//        elementList = doc.getElementsByTagName("emp:address");
+//        testAddr = (Element) elementList.item(0);
+//        addrAttr = testAddr.getAttributeNodeNS("http://www.nist.gov",
+//                "district");
+//        attrNamespaceURI = addrAttr.getNamespaceURI();
+//        assertEquals("namespaceURI", "http://www.nist.gov", attrNamespaceURI);
+//    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify that getNamespaceURI method returns null.",
+        method = "getNamespaceURI",
+        args = {}
+    )
+    public void testGetNamespaceURI2() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Element testAddr;
+        Attr addrAttr;
+        String attrNamespaceURI;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("emp:address");
+        testAddr = (Element) elementList.item(0);
+        assertNotNull("empAddressNotNull", testAddr);
+        addrAttr = testAddr.getAttributeNodeNS("http://www.nist.gov",
+                "domestic");
+        attrNamespaceURI = addrAttr.getNamespaceURI();
+        assertEquals("namespaceURI", "http://www.nist.gov", attrNamespaceURI);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify that getNamespaceURI method returns null.",
+        method = "getNamespaceURI",
+        args = {}
+    )
+    public void testGetNamespaceURI3() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Node testEmployee;
+        String employeeNamespace;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("employee");
+        testEmployee = elementList.item(0);
+        assertNotNull("employeeNotNull", testEmployee);
+        employeeNamespace = testEmployee.getNamespaceURI();
+        assertEquals("namespaceURI", "http://www.nist.gov", employeeNamespace);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that getNamespaceURI method returns null.",
+        method = "getNamespaceURI",
+        args = {}
+    )
+    public void testGetNamespaceURI4() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Node testEmployee;
+        String employeeNamespace;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("employee");
+        testEmployee = elementList.item(1);
+        employeeNamespace = testEmployee.getNamespaceURI();
+        assertNull("throw_Null", employeeNamespace);
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/NodeGetLocalName.java b/xml/src/test/java/tests/org/w3c/dom/NodeGetLocalName.java
new file mode 100644
index 0000000..d508465
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/NodeGetLocalName.java
@@ -0,0 +1,107 @@
+
+/*
+This Java source file was generated by test-to-java.xsl
+and is a derived work from the source document.
+The source document contained the following notice:
+
+
+
+Copyright (c) 2001 World Wide Web Consortium, 
+(Massachusetts Institute of Technology, Institut National de
+Recherche en Informatique et en Automatique, Keio University).  All 
+Rights Reserved.  This program is distributed under the W3C's Software
+Intellectual Property License.  This program is distributed in the 
+hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+PURPOSE.  
+
+See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+*/
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Attr;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ *  The method getLocalName returns the local part of the qualified name of this node.
+ *  
+ *  Ceate two new element nodes and atribute nodes, with and without namespace prefixes.
+ *  Retreive the local part of their qualified names using getLocalName and verrify
+ *  if it is correct.
+* @author IBM
+* @author Neil Delima
+* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSLocalN">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSLocalN</a>
+*/
+@TestTargetClass(Node.class) 
+public final class NodeGetLocalName extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+   /**
+    * Runs the test case.
+    * @throws Throwable Any uncaught exception causes test to fail
+    */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify that getLocalName method returns null.",
+        method = "getLocalName",
+        args = {}
+    )
+   public void testGetLocalName() throws Throwable {
+      Document doc;
+      Element element;
+      Element qelement;
+      Attr attr;
+      Attr qattr;
+      String localElemName;
+      String localQElemName;
+      String localAttrName;
+      String localQAttrName;
+      doc = (Document) load("staff", builder);
+      element = doc.createElementNS("http://www.w3.org/DOM/Test/elem", "elem");
+      qelement = doc.createElementNS("http://www.w3.org/DOM/Test/elem", "qual:qelem");
+      attr = doc.createAttributeNS("http://www.w3.org/DOM/Test/attr", "attr");
+      qattr = doc.createAttributeNS("http://www.w3.org/DOM/Test/attr", "qual:qattr");
+      localElemName = element.getLocalName();
+      localQElemName = qelement.getLocalName();
+      localAttrName = attr.getLocalName();
+      localQAttrName = qattr.getLocalName();
+      assertEquals("nodegetlocalname03_localElemName", "elem", localElemName);
+      assertEquals("nodegetlocalname03_localQElemName", "qelem", localQElemName);
+      assertEquals("nodegetlocalname03_localAttrName", "attr", localAttrName);
+      assertEquals("nodegetlocalname03_localQAttrName", "qattr", localQAttrName);
+      }
+   
+}
+
diff --git a/xml/src/test/java/tests/org/w3c/dom/NodeGetNamespaceURI.java b/xml/src/test/java/tests/org/w3c/dom/NodeGetNamespaceURI.java
new file mode 100644
index 0000000..5ed1e29
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/NodeGetNamespaceURI.java
@@ -0,0 +1,111 @@
+
+/*
+This Java source file was generated by test-to-java.xsl
+and is a derived work from the source document.
+The source document contained the following notice:
+
+
+
+Copyright (c) 2001-2003 World Wide Web Consortium, 
+(Massachusetts Institute of Technology, Institut National de
+Recherche en Informatique et en Automatique, Keio University).  All 
+Rights Reserved.  This program is distributed under the W3C's Software
+Intellectual Property License.  This program is distributed in the 
+hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+PURPOSE.  
+
+See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+*/
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Attr;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ *  The method getNamespaceURI returns the namespace URI of this node, or null if it is unspecified
+ *  For nodes of any type other than ELEMENT_NODE and ATTRIBUTE_NODE and nodes created with 
+ *  a DOM Level 1 method, such as createElement from the Document interface, this is always null.
+ *   
+ *  Ceate two new element nodes and atribute nodes, with and without namespace prefixes.
+ *  Retreive their namespaceURI's using getNamespaceURI and verrify if it is correct.
+* @author IBM
+* @author Neil Delima
+* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSname">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSname</a>
+* @see <a href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=259">http://www.w3.org/Bugs/Public/show_bug.cgi?id=259</a>
+*/
+@TestTargetClass(Node.class)
+public final class NodeGetNamespaceURI extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+    
+   /**
+    * Runs the test case.
+    * @throws Throwable Any uncaught exception causes test to fail
+    */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "getNamespaceURI",
+        args = {}
+    )
+   public void testGetNamespaceURI() throws Throwable {
+      Document doc;
+      Element element;
+      Element elementNS;
+      Attr attr;
+      Attr attrNS;
+      String elemNSURI;
+      String elemNSURINull;
+      String attrNSURI;
+      String attrNSURINull;
+      String nullNS = null;
+
+      doc = (Document) load("staff", builder);
+      element = doc.createElementNS(nullNS, "elem");
+      elementNS = doc.createElementNS("http://www.w3.org/DOM/Test/elem", "qual:qelem");
+      attr = doc.createAttributeNS(nullNS, "attr");
+      attrNS = doc.createAttributeNS("http://www.w3.org/DOM/Test/attr", "qual:qattr");
+      elemNSURI = elementNS.getNamespaceURI();
+      elemNSURINull = element.getNamespaceURI();
+      attrNSURI = attrNS.getNamespaceURI();
+      attrNSURINull = attr.getNamespaceURI();
+      assertEquals("nodegetnamespaceuri03_elemNSURI", "http://www.w3.org/DOM/Test/elem", elemNSURI);
+      assertNull("nodegetnamespaceuri03_1", elemNSURINull);
+      assertEquals("nodegetnamespaceuri03_attrNSURI", "http://www.w3.org/DOM/Test/attr", attrNSURI);
+      assertNull("nodegetnamespaceuri03_2", attrNSURINull);
+      }
+   
+}
+
diff --git a/xml/src/test/java/tests/org/w3c/dom/NodeGetOwnerDocument.java b/xml/src/test/java/tests/org/w3c/dom/NodeGetOwnerDocument.java
new file mode 100644
index 0000000..3579c15
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/NodeGetOwnerDocument.java
@@ -0,0 +1,128 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001-2003 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Element;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The method getOwnerDocument returns the Document object associated with this
+ * node
+ * 
+ * Create a new DocumentType node. Since this node is not used with any Document
+ * yet verify if the ownerDocument is null.
+ * 
+ * @author IBM
+ * @author Neil Delima
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#node-ownerDoc">http://www.w3.org/TR/DOM-Level-2-Core/core#node-ownerDoc</a>
+ * @see <a
+ *      href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=259">http://www.w3.org/Bugs/Public/show_bug.cgi?id=259</a>
+ */
+@TestTargetClass(Node.class)
+public final class NodeGetOwnerDocument extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that getOwnerDocument method returns null.",
+        method = "getOwnerDocument",
+        args = {}
+    )
+    public void testGetOwnerDocument1() throws Throwable {
+        Document doc;
+        Document ownerDoc;
+        DOMImplementation domImpl;
+        DocumentType docType;
+        String nullID = null;
+
+        doc = (Document) load("staff", builder);
+        domImpl = doc.getImplementation();
+        docType = domImpl.createDocumentType("mydoc", nullID, nullID);
+        ownerDoc = docType.getOwnerDocument();
+        assertNull("nodegetownerdocument01", ownerDoc);
+    }
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "getOwnerDocument",
+        args = {}
+    )
+    public void testGetOwnerDocument2() throws Throwable {
+        Document doc;
+        Document newDoc;
+        Element newElem;
+        Document ownerDocDoc;
+        Document ownerDocElem;
+        DOMImplementation domImpl;
+        DocumentType docType;
+        String nullNS = null;
+
+        doc = (Document) load("staff", builder);
+        domImpl = doc.getImplementation();
+        docType = domImpl.createDocumentType("mydoc", nullNS, nullNS);
+        newDoc = domImpl.createDocument("http://www.w3.org/DOM/Test", "mydoc",
+                docType);
+        ownerDocDoc = newDoc.getOwnerDocument();
+        assertNull("nodegetownerdocument02_1", ownerDocDoc);
+        newElem = newDoc
+                .createElementNS("http://www.w3.org/DOM/Test", "myelem");
+        ownerDocElem = newElem.getOwnerDocument();
+        assertNotNull("nodegetownerdocument02_2", ownerDocElem);
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/NodeGetPrefix.java b/xml/src/test/java/tests/org/w3c/dom/NodeGetPrefix.java
new file mode 100644
index 0000000..bcf8bba
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/NodeGetPrefix.java
@@ -0,0 +1,108 @@
+
+/*
+This Java source file was generated by test-to-java.xsl
+and is a derived work from the source document.
+The source document contained the following notice:
+
+
+
+Copyright (c) 2001 World Wide Web Consortium, 
+(Massachusetts Institute of Technology, Institut National de
+Recherche en Informatique et en Automatique, Keio University).  All 
+Rights Reserved.  This program is distributed under the W3C's Software
+Intellectual Property License.  This program is distributed in the 
+hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+PURPOSE.  
+
+See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+*/
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Attr;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ *     The method getPrefix returns the namespace prefix of this node, or null if it is unspecified.
+ *   
+ *   Ceate two new element nodes and atribute nodes, with and without namespace prefixes.
+ *   Retreive the prefix part of their qualified names using getPrefix and verify
+ *   if it is correct.
+* @author IBM
+* @author Neil Delima
+* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSPrefix">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSPrefix</a>
+*/
+@TestTargetClass(Node.class) 
+public final class NodeGetPrefix extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+    
+
+   /**
+    * Runs the test case.
+    * @throws Throwable Any uncaught exception causes test to fail
+    */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "getPrefix",
+        args = {}
+    )
+   public void testGetPrefix() throws Throwable {
+      Document doc;
+      Element element;
+      Element qelement;
+      Attr attr;
+      Attr qattr;
+      String elemNoPrefix;
+      String elemPrefix;
+      String attrNoPrefix;
+      String attrPrefix;
+      doc = (Document) load("staff", builder);
+      element = doc.createElementNS("http://www.w3.org/DOM/Test/elem", "elem");
+      qelement = doc.createElementNS("http://www.w3.org/DOM/Test/elem", "qual:qelem");
+      attr = doc.createAttributeNS("http://www.w3.org/DOM/Test/attr", "attr");
+      qattr = doc.createAttributeNS("http://www.w3.org/DOM/Test/attr", "qual:qattr");
+      elemNoPrefix = element.getPrefix();
+      elemPrefix = qelement.getPrefix();
+      attrNoPrefix = attr.getPrefix();
+      attrPrefix = qattr.getPrefix();
+      assertNull("nodegetprefix03_1", elemNoPrefix);
+      assertEquals("nodegetprefix03_2", "qual", elemPrefix);
+      assertNull("nodegetprefix03_3", attrNoPrefix);
+      assertEquals("nodegetprefix03_4", "qual", attrPrefix);
+      }
+   
+}
+
diff --git a/xml/src/test/java/tests/org/w3c/dom/NodeHasAttributes.java b/xml/src/test/java/tests/org/w3c/dom/NodeHasAttributes.java
new file mode 100644
index 0000000..514b205
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/NodeHasAttributes.java
@@ -0,0 +1,171 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMImplementation;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The method hasAttributes returns whether this node (if it is an element) has
+ * any attributes. Retreive an element node without attributes. Verify if
+ * hasAttributes returns false. Retreive another element node with attributes.
+ * Verify if hasAttributes returns true.
+ * 
+ * @author IBM
+ * @author Neil Delima
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeHasAttrs">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeHasAttrs</a>
+ */
+@TestTargetClass(Node.class) 
+public final class NodeHasAttributes extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "hasAttributes",
+        args = {}
+    )
+    public void testHasAttributes1() throws Throwable {
+        Document doc;
+        Element element;
+        NodeList elementList;
+        boolean hasAttributes;
+        doc = (Document) load("staff", builder);
+        elementList = doc.getElementsByTagName("employee");
+        element = (Element) elementList.item(0);
+        hasAttributes = element.hasAttributes();
+        assertFalse("nodehasattributes01_1", hasAttributes);
+        elementList = doc.getElementsByTagName("address");
+        element = (Element) elementList.item(0);
+        hasAttributes = element.hasAttributes();
+        assertTrue("nodehasattributes01_2", hasAttributes);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that hasAttributes method returns false value.",
+        method = "hasAttributes",
+        args = {}
+    )
+    public void testHasAttributes2() throws Throwable {
+        Document doc;
+        DocumentType docType;
+        boolean hasAttributes;
+        doc = (Document) load("staffNS", builder);
+        docType = doc.getDoctype();
+        hasAttributes = docType.hasAttributes();
+        assertFalse("nodehasattributes02", hasAttributes);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that hasAttributes method returns true value.",
+        method = "hasAttributes",
+        args = {}
+    )
+    public void testHasAttributes3() throws Throwable {
+        Document doc;
+        Element element;
+        NodeList elementList;
+        boolean hasAttributes;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("emp:employee");
+        element = (Element) elementList.item(0);
+        assertNotNull("empEmployeeNotNull", element);
+        hasAttributes = element.hasAttributes();
+        assertTrue("hasAttributes", hasAttributes);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that hasAttributes method returns true value.",
+        method = "hasAttributes",
+        args = {}
+    )
+    public void testHasAttributes4() throws Throwable {
+        Document doc;
+        Document newDoc;
+        DocumentType docType = null;
+
+        DOMImplementation domImpl;
+        Element element;
+        Element elementTest;
+        Element elementDoc;
+        Attr attribute;
+        
+        
+        NodeList elementList;
+        boolean hasAttributes;
+        doc = (Document) load("staffNS", builder);
+        domImpl = doc.getImplementation();
+        newDoc = domImpl.createDocument("http://www.w3.org/DOM/Test", "test",
+                docType);
+        element = newDoc.createElementNS("http://www.w3.org/DOM/Test",
+                "dom:elem");
+        attribute = newDoc.createAttribute("attr");
+        element.setAttributeNode(attribute);
+        elementDoc = newDoc.getDocumentElement();
+        elementDoc.appendChild(element);
+        elementList = newDoc.getElementsByTagNameNS(
+                "http://www.w3.org/DOM/Test", "elem");
+        elementTest = (Element) elementList.item(0);
+        hasAttributes = elementTest.hasAttributes();
+        assertTrue("nodehasattributes04", hasAttributes);
+    }
+
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/NodeIsSupported.java b/xml/src/test/java/tests/org/w3c/dom/NodeIsSupported.java
new file mode 100644
index 0000000..d88cb86
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/NodeIsSupported.java
@@ -0,0 +1,216 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001-2003 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.ProcessingInstruction;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The method "isSupported(feature,version)" Tests whether the DOM
+ * implementation implements a specific feature and that feature is supported by
+ * this node.
+ * 
+ * Call the isSupported method on the document element node with a combination
+ * of features versions and versions as below. Valid feature names are case
+ * insensitive and versions "2.0", "1.0" and if the version is not specified,
+ * supporting any version of the feature should return true. Check if the value
+ * returned value was true.
+ * 
+ * @author IBM
+ * @author Neil Delima
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#Level-2-Core-Node-supports">http://www.w3.org/TR/DOM-Level-2-Core/core#Level-2-Core-Node-supports</a>
+ */
+@TestTargetClass(Node.class) 
+public final class NodeIsSupported extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify that isSupported method can return false value.",
+        method = "isSupported",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testIsSupported1() throws Throwable {
+        Document doc;
+        Element element;
+        String version = "";
+        String version1 = "1.0";
+        String version2 = "2.0";
+        String featureCore;
+        String featureXML;
+        boolean success;
+        List<String> featuresXML = new ArrayList<String>();
+        featuresXML.add("XML");
+        featuresXML.add("xmL");
+
+        List<String> featuresCore = new ArrayList<String>();
+        featuresCore.add("Core");
+        featuresCore.add("CORE");
+
+        doc = (Document) load("staffNS", builder);
+        element = doc.getDocumentElement();
+        for (int indexN10063 = 0; indexN10063 < featuresXML.size(); indexN10063++) {
+            featureXML = (String) featuresXML.get(indexN10063);
+            success = element.isSupported(featureXML, version);
+            assertTrue("nodeissupported01_XML1", success);
+            success = element.isSupported(featureXML, version1);
+            assertTrue("nodeissupported01_XML2", success);
+        }
+        for (int indexN1007C = 0; indexN1007C < featuresCore.size(); indexN1007C++) {
+            featureCore = (String) featuresCore.get(indexN1007C);
+            success = element.isSupported(featureCore, version);
+            assertTrue("nodeissupported01_Core1", success);
+            success = element.isSupported(featureCore, version1);
+            success = element.isSupported(featureCore, version2);
+            assertTrue("nodeissupported01_Core3", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify that isSupported method can return false value.",
+        method = "isSupported",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testIsSupported2() throws Throwable {
+        Document doc;
+        Attr attribute;
+        String version = "";
+        String version1 = "1.0";
+        String version2 = "2.0";
+        String featureCore;
+        String featureXML;
+        boolean success;
+        List<String> featuresXML = new ArrayList<String>();
+        featuresXML.add("XML");
+        featuresXML.add("xmL");
+
+        List<String> featuresCore = new ArrayList<String>();
+        featuresCore.add("Core");
+        featuresCore.add("CORE");
+
+        doc = (Document) load("staffNS", builder);
+        attribute = doc.createAttribute("TestAttr");
+        for (int indexN10064 = 0; indexN10064 < featuresXML.size(); indexN10064++) {
+            featureXML = (String) featuresXML.get(indexN10064);
+            success = attribute.isSupported(featureXML, version);
+            assertTrue("nodeissupported02_XML1", success);
+            success = attribute.isSupported(featureXML, version1);
+            assertTrue("nodeissupported02_XML2", success);
+        }
+        for (int indexN1007D = 0; indexN1007D < featuresCore.size(); indexN1007D++) {
+            featureCore = (String) featuresCore.get(indexN1007D);
+            success = attribute.isSupported(featureCore, version);
+            assertTrue("nodeissupported02_Core1", success);
+            success = attribute.isSupported(featureCore, version1);
+            success = attribute.isSupported(featureCore, version2);
+            assertTrue("nodeissupported02_Core3", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that isSupported method returns false value if it's called with empty strings as parameters.",
+        method = "isSupported",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testIsSupported3() throws Throwable {
+        Document doc;
+        DocumentType docType;
+        boolean success;
+        doc = (Document) load("staffNS", builder);
+        docType = doc.getDoctype();
+        success = docType.isSupported("", "");
+        assertFalse("nodeissupported03", success);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that isSupported method returns false value.",
+        method = "isSupported",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testIsSupported4() throws Throwable {
+        Document doc;
+        EntityReference entRef;
+        boolean success;
+        doc = (Document) load("staffNS", builder);
+        entRef = doc.createEntityReference("ent1");
+        assertNotNull("createdEntRefNotNull", entRef);
+        success = entRef.isSupported("XML CORE", "");
+        assertFalse("nodeissupported04", success);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that isSupported method returns false value.",
+        method = "isSupported",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testIsSupported5() throws Throwable {
+        Document doc;
+        ProcessingInstruction pi;
+        boolean success;
+        doc = (Document) load("staffNS", builder);
+        pi = doc.createProcessingInstruction("PITarget", "PIData");
+        success = pi.isSupported("-", "+");
+        assertFalse("nodeissupported05", success);
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/NodeNormalize.java b/xml/src/test/java/tests/org/w3c/dom/NodeNormalize.java
new file mode 100644
index 0000000..d66ce58
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/NodeNormalize.java
@@ -0,0 +1,209 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001-2004 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Text;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Comment;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The method "normalize" puts all Text nodes in the full depth of the sub-tree
+ * underneath this Node, including attribute nodes, into a "normal" form where
+ * only structure (e.g., elements, comments, processing instructions, CDATA
+ * sections, and entity references) separates Text nodes, i.e., there are
+ * neither adjacent Text nodes nor empty Text nodes.
+ * 
+ * Create a dom tree consisting of elements, comments, processing instructions,
+ * CDATA sections, and entity references nodes seperated by text nodes. Check
+ * the length of the node list of each before and after normalize has been
+ * called.
+ * 
+ * @author IBM
+ * @author Neil Delima
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-normalize">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-normalize</a>
+ */
+@TestTargetClass(Node.class) 
+public final class NodeNormalize extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "normalize",
+        args = {}
+    )
+    public void testNormalize() throws Throwable {
+        Document doc;
+        Document newDoc;
+        DOMImplementation domImpl;
+
+        DocumentType docTypeNull = null;
+
+        Element documentElement;
+        Element element1;
+        Element element2;
+        Element element3;
+        Element element4;
+        Element element5;
+        Element element6;
+        Element element7;
+        Text text1;
+        Text text2;
+        Text text3;
+        ProcessingInstruction pi;
+        CDATASection cData;
+        Comment comment;
+        EntityReference entRef;
+        NodeList elementList;
+
+        doc = (Document) load("staffNS", builder);
+        domImpl = doc.getImplementation();
+        newDoc = domImpl.createDocument("http://www.w3.org/DOM/Test",
+                "dom:root", docTypeNull);
+        element1 = newDoc.createElement("element1");
+        element2 = newDoc.createElement("element2");
+        element3 = newDoc.createElement("element3");
+        element4 = newDoc.createElement("element4");
+        element5 = newDoc.createElement("element5");
+        element6 = newDoc.createElement("element6");
+        element7 = newDoc.createElement("element7");
+        text1 = newDoc.createTextNode("text1");
+        text2 = newDoc.createTextNode("text2");
+        text3 = newDoc.createTextNode("text3");
+        cData = newDoc.createCDATASection("Cdata");
+        comment = newDoc.createComment("comment");
+        pi = newDoc.createProcessingInstruction("PITarget", "PIData");
+        entRef = newDoc.createEntityReference("EntRef");
+        assertNotNull("createdEntRefNotNull", entRef);
+        documentElement = newDoc.getDocumentElement();
+        documentElement.appendChild(element1);
+        element2.appendChild(text1);
+        element2.appendChild(text2);
+        element2.appendChild(text3);
+        element1.appendChild(element2);
+        text1 = (Text) text1.cloneNode(false);
+        text2 = (Text) text2.cloneNode(false);
+        element3.appendChild(entRef);
+        element3.appendChild(text1);
+        element3.appendChild(text2);
+        element1.appendChild(element3);
+        text1 = (Text) text1.cloneNode(false);
+        text2 = (Text) text2.cloneNode(false);
+        element4.appendChild(cData);
+        element4.appendChild(text1);
+        element4.appendChild(text2);
+        element1.appendChild(element4);
+        text2 = (Text) text2.cloneNode(false);
+        text3 = (Text) text3.cloneNode(false);
+        element5.appendChild(comment);
+        element5.appendChild(text2);
+        element5.appendChild(text3);
+        element1.appendChild(element5);
+        text2 = (Text) text2.cloneNode(false);
+        text3 = (Text) text3.cloneNode(false);
+        element6.appendChild(pi);
+        element6.appendChild(text2);
+        element6.appendChild(text3);
+        element1.appendChild(element6);
+        entRef = (EntityReference) entRef.cloneNode(false);
+        text1 = (Text) text1.cloneNode(false);
+        text2 = (Text) text2.cloneNode(false);
+        text3 = (Text) text3.cloneNode(false);
+        element7.appendChild(entRef);
+        element7.appendChild(text1);
+        element7.appendChild(text2);
+        element7.appendChild(text3);
+        element1.appendChild(element7);
+        elementList = element1.getChildNodes();
+        assertEquals("nodeNormalize01_1Bef", 6, elementList.getLength());
+        elementList = element2.getChildNodes();
+        assertEquals("nodeNormalize01_2Bef", 3, elementList.getLength());
+        elementList = element3.getChildNodes();
+        assertEquals("nodeNormalize01_3Bef", 3, elementList.getLength());
+        elementList = element4.getChildNodes();
+        assertEquals("nodeNormalize01_4Bef", 3, elementList.getLength());
+        elementList = element5.getChildNodes();
+        assertEquals("nodeNormalize01_5Bef", 3, elementList.getLength());
+        elementList = element6.getChildNodes();
+        assertEquals("nodeNormalize01_6Bef", 3, elementList.getLength());
+        elementList = element7.getChildNodes();
+        assertEquals("nodeNormalize01_7Bef", 4, elementList.getLength());
+        newDoc.normalize();
+        elementList = element1.getChildNodes();
+        assertEquals("nodeNormalize01_1Aft", 6, elementList.getLength());
+        elementList = element2.getChildNodes();
+        assertEquals("nodeNormalize01_2Aft", 1, elementList.getLength());
+        elementList = element3.getChildNodes();
+        assertEquals("nodeNormalize01_3Aft", 2, elementList.getLength());
+        elementList = element4.getChildNodes();
+        assertEquals("nodeNormalize01_4Aft", 2, elementList.getLength());
+        elementList = element5.getChildNodes();
+        assertEquals("nodeNormalize01_5Aft", 2, elementList.getLength());
+        elementList = element6.getChildNodes();
+        assertEquals("nodeNormalize01_6Aft", 2, elementList.getLength());
+        elementList = element7.getChildNodes();
+        assertEquals("nodeNormalize01_7Aft", 2, elementList.getLength());
+    }
+    
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/NodeSetPrefix.java b/xml/src/test/java/tests/org/w3c/dom/NodeSetPrefix.java
new file mode 100644
index 0000000..dbecc30
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/NodeSetPrefix.java
@@ -0,0 +1,314 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.Element;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Attr;
+import org.w3c.dom.NodeList;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The method setPrefix sets the namespace prefix of this node. Note that
+ * setting this attribute, when permitted, changes the nodeName attribute, which
+ * holds the qualified name, as well as the tagName and name attributes of the
+ * Element and Attr interfaces, when applicable.
+ * 
+ * Create a new element node with a namespace prefix. Add it to a new
+ * DocumentFragment Node without a prefix. Call setPrefix on the elemen node.
+ * Check if the prefix was set correctly on the element.
+ * 
+ * @author IBM
+ * @author Neil Delima
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSPrefix">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSPrefix</a>
+ */
+@TestTargetClass(Node.class) 
+public final class NodeSetPrefix extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException.",
+        method = "setPrefix",
+        args = {java.lang.String.class}
+    )
+    public void testSetPrefix1() throws Throwable {
+        Document doc;
+        DocumentFragment docFragment;
+        Element element;
+        String elementTagName;
+        String elementNodeName;
+        
+        doc = (Document) load("staff", builder);
+        docFragment = doc.createDocumentFragment();
+        element = doc.createElementNS("http://www.w3.org/DOM/Test",
+                "emp:address");
+        docFragment.appendChild(element);
+        element.setPrefix("dmstc");
+        elementTagName = element.getTagName();
+        elementNodeName = element.getNodeName();
+        assertEquals("nodesetprefix01_tagname", "dmstc:address", elementTagName);
+        assertEquals("nodesetprefix01_nodeName", "dmstc:address",
+                elementNodeName);
+    }
+
+// TODO Fails on JDK. Why?
+//    public void testSetPrefix2() throws Throwable {
+//        Document doc;
+//        Element element;
+//        Attr attribute;
+//        Attr newAttribute;
+//        
+//        NodeList elementList;
+//        String attrName;
+//        String newAttrName;
+//        doc = (Document) load("staffNS", builder);
+//        elementList = doc.getElementsByTagName("address");
+//        element = (Element) elementList.item(1);
+//        newAttribute = doc.createAttributeNS("http://www.w3.org/DOM/Test",
+//                "test:address");
+//        element.setAttributeNodeNS(newAttribute);
+//        newAttribute.setPrefix("dom");
+//        attribute = element
+//                .getAttributeNodeNS("http://www.usa.com", "domestic");
+//        attrName = attribute.getNodeName();
+//        newAttrName = newAttribute.getNodeName();
+//        assertEquals("nodesetprefix02_attrName", "dmstc:domestic", attrName);
+//        assertEquals("nodesetprefix02_newAttrName", "dom:address", newAttrName);
+//    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies DOMException with NAMESPACE_ERR code.",
+        method = "setPrefix",
+        args = {java.lang.String.class}
+    )
+    public void testSetPrefix3() throws Throwable {
+        Document doc;
+        Element element;
+        doc = (Document) load("staffNS", builder);
+        element = doc.createElement("address");
+
+        {
+            boolean success = false;
+            try {
+                element.setPrefix("test");
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("throw_NAMESPACE_ERR", success);
+        }
+    }
+
+// Relies on validation, which we don't support.
+//    public void testSetPrefix4() throws Throwable {
+//        Document doc;
+//        Element element;
+//        Attr attribute;
+//        NodeList elementList;
+//        String nullNS = null;
+//
+//        doc = (Document) load("staffNS", builder);
+//        elementList = doc.getElementsByTagName("emp:employee");
+//        element = (Element) elementList.item(0);
+//        assertNotNull("empEmployeeNotNull", element);
+//        attribute = element.getAttributeNodeNS(nullNS, "defaultAttr");
+//
+//        {
+//            boolean success = false;
+//            try {
+//                attribute.setPrefix("test");
+//            } catch (DOMException ex) {
+//                success = (ex.code == DOMException.NAMESPACE_ERR);
+//            }
+//            assertTrue("nodesetprefix04", success);
+//        }
+//    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies DOMException with NAMESPACE_ERR code.",
+        method = "setPrefix",
+        args = {java.lang.String.class}
+    )
+    public void testSetPrefix5() throws Throwable {
+        Document doc;
+        Element element;
+        String prefixValue;
+        List<String> prefixValues = new ArrayList<String>();
+        prefixValues.add("_:");
+        prefixValues.add(":0");
+        prefixValues.add(":");
+        prefixValues.add("_::");
+        prefixValues.add("a:0:c");
+
+        doc = (Document) load("staffNS", builder);
+        element = doc.createElementNS("http://www.w3.org/DOM/Test/L2",
+                "dom:elem");
+        for (int indexN10050 = 0; indexN10050 < prefixValues.size(); indexN10050++) {
+            prefixValue = (String) prefixValues.get(indexN10050);
+
+            {
+                boolean success = false;
+                try {
+                    element.setPrefix(prefixValue);
+                } catch (DOMException ex) {
+                    success = (ex.code == DOMException.NAMESPACE_ERR);
+                }
+                assertTrue("throw_NAMESPACE_ERR", success);
+            }
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies DOMException with NAMESPACE_ERR code.",
+        method = "setPrefix",
+        args = {java.lang.String.class}
+    )
+    public void testSetPrefix6() throws Throwable {
+        Document doc;
+        Element element;
+        doc = (Document) load("staffNS", builder);
+        element = doc.createElementNS("http://www.w3.org/DOM/Test/L2",
+                "dom:elem");
+
+        {
+            boolean success = false;
+            try {
+                element.setPrefix("xml");
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("throw_NAMESPACE_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies DOMException with NAMESPACE_ERR code.",
+        method = "setPrefix",
+        args = {java.lang.String.class}
+    )
+    public void testSetPrefix7() throws Throwable {
+        Document doc;
+        Attr attribute;
+        doc = (Document) load("staffNS", builder);
+        attribute = doc.createAttributeNS("http://www.w3.org/DOM/Test/L2",
+                "abc:elem");
+
+        {
+            boolean success = false;
+            try {
+                attribute.setPrefix("xmlns");
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("throw_NAMESPACE_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies DOMException with NAMESPACE_ERR.",
+        method = "setPrefix",
+        args = {java.lang.String.class}
+    )
+    public void testSetPrefix8() throws Throwable {
+        Document doc;
+        Element element;
+        NodeList elementList;
+        Attr attribute;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("employee");
+        element = (Element) elementList.item(0);
+        attribute = element.getAttributeNode("xmlns");
+
+        {
+            boolean success = false;
+            try {
+                attribute.setPrefix("xml");
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("throw_NAMESPACE_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies DOMException with INVALID_CHARACTER_ERR code.",
+        method = "setPrefix",
+        args = {java.lang.String.class}
+    )
+    public void _testSetPrefix9() throws Throwable {
+        Document doc;
+        String value = "#$%&'()@";
+        Element element;
+        doc = (Document) load("staffNS", builder);
+        element = doc.createElementNS("http://www.w3.org/DOM/Test/L2",
+                "dom:elem");
+
+        {
+            boolean success = false;
+            try {
+                element.setPrefix(value);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.INVALID_CHARACTER_ERR);
+            }
+            assertTrue("throw_INVALID_CHARACTER_ERR", success);
+        }
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/Normalize.java b/xml/src/test/java/tests/org/w3c/dom/Normalize.java
new file mode 100644
index 0000000..36ff43c
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/Normalize.java
@@ -0,0 +1,106 @@
+
+/*
+This Java source file was generated by test-to-java.xsl
+and is a derived work from the source document.
+The source document contained the following notice:
+
+
+
+Copyright (c) 2001 World Wide Web Consortium, 
+(Massachusetts Institute of Technology, Institut National de
+Recherche en Informatique et en Automatique, Keio University).  All 
+Rights Reserved.  This program is distributed under the W3C's Software
+Intellectual Property License.  This program is distributed in the 
+hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+PURPOSE.  
+
+See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+*/
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.CharacterData;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ *     The "normalize()" method puts all the nodes in the full
+ *     depth of the sub-tree underneath this element into a 
+ *     "normal" form. 
+ *     
+ *     Retrieve the third employee and access its second child.
+ *     This child contains a block of text that is spread 
+ *     across multiple lines.   The content of the "name" child
+ *     should be parsed and treated as a single Text node.
+ *     This appears to be a duplicate of elementnormalize.xml in DOM L1 Test Suite
+* @author NIST
+* @author Mary Brady
+* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-normalize">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-normalize</a>
+* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-72AB8359">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-72AB8359</a>
+*/
+@TestTargetClass(Element.class) 
+public final class Normalize extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+   /**
+    * Runs the test case.
+    * @throws Throwable Any uncaught exception causes test to fail
+    */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "normalize",
+        args = {}
+    )
+   public void testNormalize() throws Throwable {
+      Document doc;
+      Element root;
+      NodeList elementList;
+      Node firstChild;
+      NodeList textList;
+      CharacterData textNode;
+      String data;
+      doc = (Document) load("staff", builder);
+      root = doc.getDocumentElement();
+      root.normalize();
+      elementList = root.getElementsByTagName("name");
+      firstChild = elementList.item(2);
+      textList = firstChild.getChildNodes();
+      textNode = (CharacterData) textList.item(0);
+      data = textNode.getData();
+      assertEquals("data", "Roger\n Jones", data);
+      }
+   
+}
+
diff --git a/xml/src/test/java/tests/org/w3c/dom/OwnerDocument.java b/xml/src/test/java/tests/org/w3c/dom/OwnerDocument.java
new file mode 100644
index 0000000..b5b0e94
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/OwnerDocument.java
@@ -0,0 +1,88 @@
+
+/*
+This Java source file was generated by test-to-java.xsl
+and is a derived work from the source document.
+The source document contained the following notice:
+
+
+
+Copyright (c) 2001 World Wide Web Consortium, 
+(Massachusetts Institute of Technology, Institut National de
+Recherche en Informatique et en Automatique, Keio University).  All 
+Rights Reserved.  This program is distributed under the W3C's Software
+Intellectual Property License.  This program is distributed in the 
+hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+PURPOSE.  
+
+See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+*/
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ *     The "getOwnerDocument()" method returns null if the target
+ *     node itself is a DocumentType which is not used with any document yet.
+ *     
+ *     Invoke the "getOwnerDocument()" method on the master 
+ *     document.   The DocumentType returned should be null.
+* @author NIST
+* @author Mary Brady
+* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#node-ownerDoc">http://www.w3.org/TR/DOM-Level-2-Core/core#node-ownerDoc</a>
+*/
+@TestTargetClass(Document.class) 
+public final class OwnerDocument extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+   /**
+    * Runs the test case.
+    * @throws Throwable Any uncaught exception causes test to fail
+    */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Dosn't verify that getOwnerDocument can return not null value.",
+        method = "getOwnerDocument",
+        args = {}
+    )
+   public void testGetOwnerDocument() throws Throwable {
+      Document doc;
+      DocumentType ownerDocument;
+      doc = (Document) load("staff", builder);
+      ownerDocument = (DocumentType) doc.getOwnerDocument();
+      assertNull("throw_Null", ownerDocument);
+      }
+   
+}
+
diff --git a/xml/src/test/java/tests/org/w3c/dom/OwnerElement.java b/xml/src/test/java/tests/org/w3c/dom/OwnerElement.java
new file mode 100644
index 0000000..a4af36a
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/OwnerElement.java
@@ -0,0 +1,118 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Element;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The "getOwnerElement()" will return the Element node this attribute is
+ * attached to or null if this attribute is not in use. Get the "domestic"
+ * attribute from the first "address" node. Apply the "getOwnerElement()" method
+ * to get the Element associated with the attribute. The value returned should
+ * be "address".
+ * 
+ * @author NIST
+ * @author Mary Brady
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-F68D095">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-F68D095</a>
+ */
+@TestTargetClass(Attr.class) 
+public final class OwnerElement extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies positive functionlity.",
+        method = "getOwnerElement",
+        args = {}
+    )
+    public void testGetOwnerElement1() throws Throwable {
+        Document doc;
+        NodeList addressList;
+        Node testNode;
+        NamedNodeMap attributes;
+        Attr domesticAttr;
+        Element elementNode;
+        String name;
+        doc = (Document) load("staff", builder);
+        addressList = doc.getElementsByTagName("address");
+        testNode = addressList.item(0);
+        attributes = testNode.getAttributes();
+        domesticAttr = (Attr) attributes.getNamedItem("domestic");
+        elementNode = domesticAttr.getOwnerElement();
+        name = elementNode.getNodeName();
+        assertEquals("throw_Equals", "address", name);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that getOwnerElement method returns null.",
+        method = "getOwnerElement",
+        args = {}
+    )
+    public void testGetOwnerElement2() throws Throwable {
+        Document doc;
+        Attr newAttr;
+        Element elementNode;
+        doc = (Document) load("staff", builder);
+        newAttr = doc.createAttribute("newAttribute");
+        elementNode = newAttr.getOwnerElement();
+        assertNull("throw_Null", elementNode);
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/Prefix.java b/xml/src/test/java/tests/org/w3c/dom/Prefix.java
new file mode 100644
index 0000000..f45144a
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/Prefix.java
@@ -0,0 +1,337 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Element;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The "getPrefix()" method for a Node returns the namespace prefix of the node,
+ * and for nodes of any type other than ELEMENT_NODE and ATTRIBUTE_NODE and
+ * nodes created with a DOM Level 1 method, this is null.
+ * 
+ * Create an new Element with the createElement() method. Invoke the
+ * "getPrefix()" method on the newly created element node will cause "null" to
+ * be returned.
+ * 
+ * @author NIST
+ * @author Mary Brady
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSPrefix">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-NodeNSPrefix</a>
+ */
+@TestTargetClass(Node.class) 
+public final class Prefix extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that getPrefix method can return null.",
+        method = "getPrefix",
+        args = {}
+    )
+    public void testGetPrefix1() throws Throwable {
+        Document doc;
+        Node createdNode;
+        String prefix;
+        doc = (Document) load("staffNS", builder);
+        createdNode = doc.createElement("test:employee");
+        prefix = createdNode.getPrefix();
+        assertNull("throw_Null", prefix);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies positive functionality of getPrefix method.",
+        method = "getPrefix",
+        args = {}
+    )
+    public void testGetPrefix2() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Node testEmployee;
+        Node textNode;
+        String prefix;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("emp:employeeId");
+        testEmployee = elementList.item(0);
+        assertNotNull("empEmployeeNotNull", testEmployee);
+        textNode = testEmployee.getFirstChild();
+        prefix = textNode.getPrefix();
+        assertNull("textNodePrefix", prefix);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies positive functionality of getPrefix method.",
+        method = "getPrefix",
+        args = {}
+    )
+    public void testGetPrefix3() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Node testEmployee;
+        String prefix;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("emp:employee");
+        testEmployee = elementList.item(0);
+        assertNotNull("empEmployeeNotNull", testEmployee);
+        prefix = testEmployee.getPrefix();
+        assertEquals("prefix", "emp", prefix);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that getPrefix method returns null.",
+        method = "getPrefix",
+        args = {}
+    )
+    public void testGetPrefix4() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Node testEmployee;
+        String prefix;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("employee");
+        testEmployee = elementList.item(0);
+        prefix = testEmployee.getPrefix();
+        assertNull("throw_Null", prefix);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that getPrefix method throws DOMException with NAMESPACE_ERR code.",
+        method = "getPrefix",
+        args = {}
+    )
+    public void testGetPrefix5() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Element addrNode;
+        Attr addrAttr;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("emp:address");
+        addrNode = (Element) elementList.item(0);
+        assertNotNull("empAddrNotNull", addrNode);
+        addrAttr = addrNode.getAttributeNode("emp:domestic");
+
+        {
+            boolean success = false;
+            try {
+                addrAttr.setPrefix("xmlns");
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("throw_NAMESPACE_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that getPrefix method throws DOMException with INVALID_CHARACTER_ERR code.",
+        method = "getPrefix",
+        args = {}
+    )
+    public void _testGetPrefix6() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Node employeeNode;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("employee");
+        employeeNode = elementList.item(0);
+
+        {
+            boolean success = false;
+            try {
+                employeeNode.setPrefix("pre^fix xmlns='http//www.nist.gov'");
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.INVALID_CHARACTER_ERR);
+            }
+            assertTrue("throw_INVALID_CHARACTER_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that getPrefix method throws DOMException with NAMESPACE_ERR code.",
+        method = "getPrefix",
+        args = {}
+    )
+    public void testGetPrefix7() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Node employeeNode;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("employee");
+        employeeNode = elementList.item(0);
+
+        {
+            boolean success = false;
+            try {
+                employeeNode.setPrefix("emp::");
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("throw_NAMESPACE_ERR", success);
+        }
+    }
+
+// Assumes validation.
+//    public void testGetPrefix8() throws Throwable {
+//        Document doc;
+//        NodeList genderList;
+//        Node genderNode;
+//        Node entRef;
+//        Node entElement;
+//
+//        int nodeType;
+//        doc = (Document) load("staff", builder);
+//        genderList = doc.getElementsByTagName("gender");
+//        genderNode = genderList.item(2);
+//        entRef = genderNode.getFirstChild();
+//        nodeType = (int) entRef.getNodeType();
+//
+//        if (1 == nodeType) {
+//            entRef = doc.createEntityReference("ent4");
+//            assertNotNull("createdEntRefNotNull", entRef);
+//        }
+//        entElement = entRef.getFirstChild();
+//        assertNotNull("entElement", entElement);
+//        doc.createElement("text3");
+//
+//        {
+//            boolean success = false;
+//            try {
+//                entElement.setPrefix("newPrefix");
+//            } catch (DOMException ex) {
+//                success = (ex.code == DOMException.NO_MODIFICATION_ALLOWED_ERR);
+//            }
+//            assertTrue("throw_NO_MODIFICATION_ALLOWED_ERR", success);
+//        }
+//    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that getPrefix method throws DOMException with NAMESPACE_ERR code.",
+        method = "getPrefix",
+        args = {}
+    )
+    public void _testGetPrefix9() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Element addrNode;
+        Attr addrAttr;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("address");
+        addrNode = (Element) elementList.item(3);
+        addrAttr = addrNode.getAttributeNode("xmlns");
+
+        {
+            boolean success = false;
+            try {
+                addrAttr.setPrefix("xxx");
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("throw_NAMESPACE_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that getPrefix method throws DOMException with NAMESPACE_ERR code.",
+        method = "getPrefix",
+        args = {}
+    )
+    public void testGetPrefix10() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Node employeeNode;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("employee");
+        employeeNode = elementList.item(1);
+
+        {
+            boolean success = false;
+            try {
+                employeeNode.setPrefix("xml");
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("throw_NAMESPACE_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies that getPrefix method throws DOMException with NAMESPACE_ERR code.",
+        method = "getPrefix",
+        args = {}
+    )
+    public void testGetPrefix11() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Node employeeNode;
+
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("employee");
+        employeeNode = elementList.item(1);
+        employeeNode.getNamespaceURI();
+
+        {
+            boolean success = false;
+            try {
+                employeeNode.setPrefix("employee1");
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("throw_NAMESPACE_ERR", success);
+        }
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/PublicId.java b/xml/src/test/java/tests/org/w3c/dom/PublicId.java
new file mode 100644
index 0000000..8165b2c
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/PublicId.java
@@ -0,0 +1,91 @@
+
+/*
+This Java source file was generated by test-to-java.xsl
+and is a derived work from the source document.
+The source document contained the following notice:
+
+
+
+Copyright (c) 2001 World Wide Web Consortium, 
+(Massachusetts Institute of Technology, Institut National de
+Recherche en Informatique et en Automatique, Keio University).  All 
+Rights Reserved.  This program is distributed under the W3C's Software
+Intellectual Property License.  This program is distributed in the 
+hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+PURPOSE.  
+
+See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+*/
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Document;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ *     The "getPublicId()" method of a documenttype node contains
+ *    the public identifier associated with the external subset.
+ *    
+ *    Retrieve the documenttype.
+ *    Apply the "getPublicId()" method.  The string "STAFF" should be
+ *    returned.
+* @author NIST
+* @author Mary Brady
+* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-Core-DocType-publicId">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-Core-DocType-publicId</a>
+*/
+@TestTargetClass(DocumentType.class) 
+public final class PublicId extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+   /**
+    * Runs the test case.
+    * @throws Throwable Any uncaught exception causes test to fail
+    */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "getPublicId",
+        args = {}
+    )
+   public void testGetPublicId() throws Throwable {
+      Document doc;
+      DocumentType docType;
+      String publicId;
+      doc = (Document) load("staffNS", builder);
+      docType = doc.getDoctype();
+      publicId = docType.getPublicId();
+      assertEquals("throw_Equals", "STAFF", publicId);
+      }
+   
+}
+
diff --git a/xml/src/test/java/tests/org/w3c/dom/RemoveAttributeNS.java b/xml/src/test/java/tests/org/w3c/dom/RemoveAttributeNS.java
new file mode 100644
index 0000000..6a84d1b
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/RemoveAttributeNS.java
@@ -0,0 +1,147 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001-2004 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargetClass; 
+
+import javax.xml.parsers.DocumentBuilder;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * The "removeAttributeNS(namespaceURI,localName)" method for an attribute
+ * causes the DOMException NO_MODIFICATION_ALLOWED_ERR to be raised if the node
+ * is readonly.
+ * 
+ * Obtain the children of the THIRD "gender" element. The elements content is an
+ * entity reference. Try to remove an attribute from the entity reference by
+ * executing the "removeAttributeNS(namespaceURI,localName)" method. This causes
+ * a NO_MODIFICATION_ALLOWED_ERR DOMException to be thrown.
+ * 
+ * @author NIST
+ * @author Mary Brady
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='NO_MODIFICATION_ALLOWED_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='NO_MODIFICATION_ALLOWED_ERR'])</a>
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElRemAtNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElRemAtNS</a>
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-ElRemAtNS')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='NO_MODIFICATION_ALLOWED_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-ElRemAtNS')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='NO_MODIFICATION_ALLOWED_ERR'])</a>
+ */
+@TestTargetClass(Attr.class) 
+public final class RemoveAttributeNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+// Assumes validation.
+//    public void testRemoveAttributeNS1() throws Throwable {
+//        Document doc;
+//        NodeList genderList;
+//        Node gender;
+//        Node gen;
+//        NodeList gList;
+//        Element genElement;
+//        int nodeType;
+//        doc = (Document) load("staffNS", builder);
+//        genderList = doc.getElementsByTagName("gender");
+//        gender = genderList.item(2);
+//        gen = gender.getFirstChild();
+//        nodeType = (int) gen.getNodeType();
+//
+//        if (1 == nodeType) {
+//            gen = doc.createEntityReference("ent4");
+//            assertNotNull("createdEntRefNotNull", gen);
+//        }
+//        gList = gen.getChildNodes();
+//        genElement = (Element) gList.item(0);
+//        assertNotNull("notnull", genElement);
+//
+//        {
+//            boolean success = false;
+//            try {
+//                genElement.removeAttributeNS("www.xyz.com", "local1");
+//            } catch (DOMException ex) {
+//                success = (ex.code == DOMException.NO_MODIFICATION_ALLOWED_ERR);
+//            }
+//            assertTrue("throw_NO_MODIFICATION_ALLOWED_ERR", success);
+//        }
+//    }
+
+// Assumes validation
+//    public void testRemoveAttributeNS2() throws Throwable {
+//        Document doc;
+//        NodeList elementList;
+//        Node testAddr;
+//        Attr addrAttr;
+//        String attr;
+//        String namespaceURI;
+//        String localName;
+//        String prefix;
+//        doc = (Document) load("staffNS", builder);
+//        elementList = doc.getElementsByTagName("emp:address");
+//        testAddr = elementList.item(0);
+//        ((Element) /* Node */testAddr).removeAttributeNS("http://www.nist.gov",
+//                "local1");
+//        elementList = doc.getElementsByTagName("emp:address");
+//        testAddr = elementList.item(0);
+//        addrAttr = ((Element) /* Node */testAddr).getAttributeNodeNS(
+//                "http://www.nist.gov", "local1");
+//        attr = ((Element) /* Node */testAddr).getAttributeNS(
+//                "http://www.nist.gov", "local1");
+//        namespaceURI = addrAttr.getNamespaceURI();
+//        localName = addrAttr.getLocalName();
+//        prefix = testAddr.getPrefix();
+//        assertEquals("attr", "FALSE", attr);
+//        assertEquals("uri", "http://www.nist.gov", namespaceURI);
+//        assertEquals("lname", "local1", localName);
+//        assertEquals("prefix", "emp", prefix);
+//    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/RemoveNamedItemNS.java b/xml/src/test/java/tests/org/w3c/dom/RemoveNamedItemNS.java
new file mode 100644
index 0000000..e745e74c
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/RemoveNamedItemNS.java
@@ -0,0 +1,178 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The "removeNamedItemNS(namespaceURI,localName)" method for a NamedNodeMap
+ * should remove a node specified by localName and namespaceURI.
+ * 
+ * Retrieve a list of elements with tag name "address". Access the second
+ * element from the list and get its attributes. Try to remove the attribute
+ * node with local name "domestic" and namespace uri "http://www.usa.com" with
+ * method removeNamedItemNS(namespaceURI,localName). Check to see if the node
+ * has been removed.
+ * 
+ * @author NIST
+ * @author Mary Brady
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-1074577549">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-1074577549</a>
+ */
+@TestTargetClass(NamedNodeMap.class) 
+public final class RemoveNamedItemNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify DOMException exception.",
+        method = "removeNamedItemNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testRemoveNamedItemNS1() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Node testAddress;
+        NamedNodeMap attributes;
+        Attr newAttr;
+        Node removedNode;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("address");
+        testAddress = elementList.item(1);
+        attributes = testAddress.getAttributes();
+        removedNode = attributes.removeNamedItemNS("http://www.usa.com",
+                "domestic");
+        assertNotNull("retval", removedNode);
+        newAttr = (Attr) attributes.getNamedItem("dmstc:domestic");
+        assertNull("nodeRemoved", newAttr);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Verifies DOMException with NOT_FOUND_ERR code.",
+        method = "removeNamedItemNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+    public void testRemoveNamedItemNS2() throws Throwable {
+        String namespaceURI = "http://www.usa.com";
+        String localName = "domest";
+        Document doc;
+        NodeList elementList;
+        Node testAddress;
+        NamedNodeMap attributes;
+        
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("address");
+        testAddress = elementList.item(1);
+        attributes = testAddress.getAttributes();
+
+        {
+            boolean success = false;
+            try {
+                attributes.removeNamedItemNS(namespaceURI,
+                        localName);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NOT_FOUND_ERR);
+            }
+            assertTrue("throw_NOT_FOUND_ERR", success);
+        }
+    }
+
+// Assumes validation.
+//    public void testRemoveNamedItemNS3() throws Throwable {
+//        String namespaceURI = "http://www.w3.org/2000/xmlns/";
+//        String localName = "local1";
+//        Document doc;
+//        NodeList elementList;
+//        Node testAddress;
+//        NodeList nList;
+//        Node child;
+//        NodeList n2List;
+//        Node child2;
+//        NamedNodeMap attributes;
+//        
+//        int nodeType;
+//        doc = (Document) load("staffNS", builder);
+//        elementList = doc.getElementsByTagName("gender");
+//        testAddress = elementList.item(2);
+//        nList = testAddress.getChildNodes();
+//        child = nList.item(0);
+//        nodeType = (int) child.getNodeType();
+//
+//        if (1 == nodeType) {
+//            child = doc.createEntityReference("ent4");
+//            assertNotNull("createdEntRefNotNull", child);
+//        }
+//        n2List = child.getChildNodes();
+//        child2 = n2List.item(0);
+//        assertNotNull("notnull", child2);
+//        attributes = child2.getAttributes();
+//
+//        {
+//            boolean success = false;
+//            try {
+//                attributes.removeNamedItemNS(namespaceURI,
+//                        localName);
+//            } catch (DOMException ex) {
+//                success = (ex.code == DOMException.NO_MODIFICATION_ALLOWED_ERR);
+//            }
+//            assertTrue("throw_NO_MODIFICATION_ALLOWED_ERR", success);
+//        }
+//    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/SetAttributeNS.java b/xml/src/test/java/tests/org/w3c/dom/SetAttributeNS.java
new file mode 100644
index 0000000..58c146f
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/SetAttributeNS.java
@@ -0,0 +1,353 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Attr;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The "setAttributeNS(namespaceURI,qualifiedName,Value)" method raises a
+ * INVALID_CHARACTER_ERR DOMException if the specified prefix contains an
+ * illegal character.
+ * 
+ * Attempt to add a new attribute on the first employee node. An exception
+ * should be raised since the "qualifiedName" has an invalid character.
+ * 
+ * @author NIST
+ * @author Mary Brady
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='INVALID_CHARACTER_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='INVALID_CHARACTER_ERR'])</a>
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElSetAttrNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElSetAttrNS</a>
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-ElSetAttrNS')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='INVALID_CHARACTER_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-ElSetAttrNS')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='INVALID_CHARACTER_ERR'])</a>
+ */
+@TestTargetClass(Element.class) 
+public final class SetAttributeNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies DOMException with INVALID_CHARACTER_ERR code.",
+        method = "setAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+    )
+    public void testSetAttributeNS1() throws Throwable {
+        String namespaceURI = "http://www.nist.gov";
+        String qualifiedName = "emp:qual?name";
+        Document doc;
+        NodeList elementList;
+        Node testAddr;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("employee");
+        testAddr = elementList.item(0);
+
+        {
+            boolean success = false;
+            try {
+                ((Element) /* Node */testAddr).setAttributeNS(namespaceURI,
+                        qualifiedName, "newValue");
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.INVALID_CHARACTER_ERR);
+            }
+            assertTrue("throw_INVALID_CHARACTER_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies DOMException with NAMESPACE_ERR code.",
+        method = "setAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+    )
+    public void testSetAttributeNS2() throws Throwable {
+        String namespaceURI = "http://www.nist.gov";
+        String qualifiedName = "emp:";
+        Document doc;
+        NodeList elementList;
+        Node testAddr;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("emp:employee");
+        testAddr = elementList.item(0);
+
+        {
+            boolean success = false;
+            try {
+                ((Element) /* Node */testAddr).setAttributeNS(namespaceURI,
+                        qualifiedName, "newValue");
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("throw_NAMESPACE_ERR", success);
+        }
+    }
+
+// Assumes validation.
+//    public void testSetAttributeNS3() throws Throwable {
+//        String namespaceURI = "www.xyz.com";
+//        String qualifiedName = "emp:local1";
+//        Document doc;
+//        NodeList genderList;
+//        Node gender;
+//        NodeList genList;
+//        Node gen;
+//        NodeList gList;
+//        Element genElement;
+//        int nodeType;
+//        doc = (Document) load("staffNS", builder);
+//        genderList = doc.getElementsByTagName("gender");
+//        gender = genderList.item(2);
+//        genList = gender.getChildNodes();
+//        gen = genList.item(0);
+//        nodeType = (int) gen.getNodeType();
+//
+//        if (1 == nodeType) {
+//            gen = doc.createEntityReference("ent4");
+//            assertNotNull("createdEntRefNotNull", gen);
+//        }
+//        gList = gen.getChildNodes();
+//        genElement = (Element) gList.item(0);
+//        assertNotNull("notnull", genElement);
+//
+//        {
+//            boolean success = false;
+//            try {
+//                genElement.setAttributeNS(namespaceURI, qualifiedName,
+//                        "newValue");
+//            } catch (DOMException ex) {
+//                success = (ex.code == DOMException.NO_MODIFICATION_ALLOWED_ERR);
+//            }
+//            assertTrue("throw_NO_MODIFICATION_ALLOWED_ERR", success);
+//        }
+//    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies positive functionality.",
+        method = "setAttributeNS",
+        args = {String.class, String.class, String.class}
+    )
+    public void testSetAttributeNS4() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Node testAddr;
+        Attr addrAttr;
+        String resultAttr;
+        String resultNamespaceURI;
+        String resultLocalName;
+        String resultPrefix;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("emp:address");
+        testAddr = elementList.item(0);
+        assertNotNull("empAddrNotNull", testAddr);
+        ((Element) /* Node */testAddr).setAttributeNS("http://www.nist.gov",
+                "newprefix:zone", "newValue");
+        addrAttr = ((Element) /* Node */testAddr).getAttributeNodeNS(
+                "http://www.nist.gov", "zone");
+        resultAttr = ((Element) /* Node */testAddr).getAttributeNS(
+                "http://www.nist.gov", "zone");
+        assertEquals("attrValue", "newValue", resultAttr);
+        resultNamespaceURI = addrAttr.getNamespaceURI();
+        assertEquals("nsuri", "http://www.nist.gov", resultNamespaceURI);
+        resultLocalName = addrAttr.getLocalName();
+        assertEquals("lname", "zone", resultLocalName);
+        resultPrefix = addrAttr.getPrefix();
+        assertEquals("prefix", "newprefix", resultPrefix);
+    }
+    
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies positive functionality.",
+        method = "setAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+    )
+    public void testSetAttributeNS5() throws Throwable {
+        String localName = "newAttr";
+        String namespaceURI = "http://www.newattr.com";
+        String qualifiedName = "emp:newAttr";
+        Document doc;
+        NodeList elementList;
+        Node testAddr;
+        
+        String resultAttr;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("emp:address");
+        testAddr = elementList.item(0);
+        assertNotNull("empAddrNotNull", testAddr);
+        ((Element) /* Node */testAddr).setAttributeNS(namespaceURI,
+                qualifiedName, "<newValue>");
+        resultAttr = ((Element) /* Node */testAddr).getAttributeNS(
+                namespaceURI, localName);
+        assertEquals("throw_Equals", "<newValue>", resultAttr);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies DOMException with NAMESPACE_ERR code.",
+        method = "setAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+    )
+    public void testSetAttributeNS6() throws Throwable {
+        String namespaceURI = "http://www.nist.gov";
+        String qualifiedName = "xml:qualifiedName";
+        Document doc;
+        NodeList elementList;
+        Node testAddr;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("employee");
+        testAddr = elementList.item(0);
+
+        {
+            boolean success = false;
+            try {
+                ((Element) /* Node */testAddr).setAttributeNS(namespaceURI,
+                        qualifiedName, "newValue");
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("throw_NAMESPACE_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies DOMException with NAMESPACE_ERR.",
+        method = "setAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+    )
+    public void testSetAttributeNS7() throws Throwable {
+        String namespaceURI = "http://www.nist.gov";
+        String qualifiedName = "xmlns";
+        Document doc;
+        NodeList elementList;
+        Node testAddr;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("employee");
+        testAddr = elementList.item(0);
+
+        {
+            boolean success = false;
+            try {
+                ((Element) /* Node */testAddr).setAttributeNS(namespaceURI,
+                        qualifiedName, "newValue");
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("throw_NAMESPACE_ERR", success);
+        }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies positive functionality.",
+        method = "setAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+    )
+    public void testSetAttributeNS9() throws Throwable {
+        String localName = "newAttr";
+        String namespaceURI = "http://www.newattr.com";
+        String qualifiedName = "emp:newAttr";
+        Document doc;
+        NodeList elementList;
+        Node testAddr;
+        Attr addrAttr;
+        String resultAttr;
+        String resultNamespaceURI;
+        String resultLocalName;
+        String resultPrefix;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("emp:address");
+        testAddr = elementList.item(0);
+        assertNotNull("empAddrNotNull", testAddr);
+        ((Element) /* Node */testAddr).setAttributeNS(namespaceURI,
+                qualifiedName, "newValue");
+        addrAttr = ((Element) /* Node */testAddr).getAttributeNodeNS(
+                namespaceURI, localName);
+        resultAttr = ((Element) /* Node */testAddr).getAttributeNS(
+                namespaceURI, localName);
+        assertEquals("attrValue", "newValue", resultAttr);
+        resultNamespaceURI = addrAttr.getNamespaceURI();
+        assertEquals("nsuri", "http://www.newattr.com", resultNamespaceURI);
+        resultLocalName = addrAttr.getLocalName();
+        assertEquals("lname", "newAttr", resultLocalName);
+        resultPrefix = addrAttr.getPrefix();
+        assertEquals("prefix", "emp", resultPrefix);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies DOMException with NAMESPACE_ERR code.",
+        method = "setAttributeNS",
+        args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+    )
+    public void testSetAttributeNS10() throws Throwable {
+        String namespaceURI = "http://www.example.gov";
+        Document doc;
+        NodeList elementList;
+        Node testAddr;
+        doc = (Document) load("hc_staff", builder);
+        elementList = doc.getElementsByTagName("em");
+        testAddr = elementList.item(0);
+
+        {
+            boolean success = false;
+            try {
+                ((Element) /* Node */testAddr).setAttributeNS(namespaceURI, "",
+                        "newValue");
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.NAMESPACE_ERR);
+            }
+            assertTrue("throw_NAMESPACE_ERR", success);
+        }
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/SetAttributeNodeNS.java b/xml/src/test/java/tests/org/w3c/dom/SetAttributeNodeNS.java
new file mode 100644
index 0000000..3960a4f
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/SetAttributeNodeNS.java
@@ -0,0 +1,237 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001-2004 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The "setAttributeNode(newAttr)" method raises an "INUSE_ATTRIBUTE_ERR
+ * DOMException if the "newAttr" is already an attribute of another element.
+ * 
+ * Retrieve the first emp:address and append a newly created element. The
+ * "createAttributeNS(namespaceURI,qualifiedName)" and
+ * "setAttributeNodeNS(newAttr)" methods are invoked to create and add a new
+ * attribute to the newly created Element. The "setAttributeNodeNS(newAttr)"
+ * method is once again called to add the new attribute causing an exception to
+ * be raised since the attribute is already an attribute of another element.
+ * 
+ * @author NIST
+ * @author Mary Brady
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='INUSE_ATTRIBUTE_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='INUSE_ATTRIBUTE_ERR'])</a>
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElSetAtNodeNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElSetAtNodeNS</a>
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-ElSetAtNodeNS')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='INUSE_ATTRIBUTE_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-ElSetAtNodeNS')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='INUSE_ATTRIBUTE_ERR'])</a>
+ */
+@TestTargetClass(Element.class) 
+public final class SetAttributeNodeNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies DOMException with INUSE_ATTRIBUTE_ERR code.",
+        method = "setAttributeNodeNS",
+        args = {org.w3c.dom.Attr.class}
+    )
+    public void testSetAttributeNode1() throws Throwable {
+        String namespaceURI = "http://www.newattr.com";
+        String qualifiedName = "emp:newAttr";
+        Document doc;
+        Element newElement;
+        Attr newAttr;
+        NodeList elementList;
+        Node testAddr;
+
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("emp:address");
+        testAddr = elementList.item(0);
+        assertNotNull("empAddrNotNull", testAddr);
+        newElement = doc.createElement("newElement");
+        testAddr.appendChild(newElement);
+        newAttr = doc.createAttributeNS(namespaceURI, qualifiedName);
+        newElement.setAttributeNodeNS(newAttr);
+
+        {
+            boolean success = false;
+            try {
+                ((Element) /* Node */testAddr).setAttributeNodeNS(newAttr);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.INUSE_ATTRIBUTE_ERR);
+            }
+            assertTrue("throw_INUSE_ATTRIBUTE_ERR", success);
+        }
+    }
+
+// Assumes validation.
+//    public void testSetAttributeNode2() throws Throwable {
+//        Document doc;
+//        NodeList genderList;
+//        Node gender;
+//        NodeList genList;
+//        Node gen;
+//        NodeList gList;
+//        Element genElement;
+//        Attr newAttr;
+//        
+//        doc = (Document) load("staffNS", builder);
+//
+//        if (!factory.isExpandEntityReferences()) {
+//            genderList = doc.getElementsByTagName("gender");
+//            gender = genderList.item(2);
+//            genList = gender.getChildNodes();
+//            gen = genList.item(0);
+//        } else {
+//            gen = doc.createEntityReference("ent4");
+//        }
+//
+//        gList = gen.getChildNodes();
+//        genElement = (Element) gList.item(0);
+//        assertNotNull("notnull", genElement);
+//        newAttr = doc.createAttributeNS("www.xyz.com", "emp:local1");
+//
+//        {
+//            boolean success = false;
+//            try {
+//                genElement.setAttributeNodeNS(newAttr);
+//            } catch (DOMException ex) {
+//                success = (ex.code == DOMException.NO_MODIFICATION_ALLOWED_ERR);
+//            }
+//            assertTrue("throw_NO_MODIFICATION_ALLOWED_ERR", success);
+//        }
+//    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException.",
+        method = "setAttributeNodeNS",
+        args = {org.w3c.dom.Attr.class}
+    )
+    public void testSetAttributeNode3() throws Throwable {
+        String namespaceURI = "http://www.newattr.com";
+        String qualifiedName = "emp:newAttr";
+        Document doc;
+        NodeList elementList;
+        Node testAddr;
+        Attr newAttr;
+        Attr newAddrAttr;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("emp:address");
+        testAddr = elementList.item(0);
+        assertNotNull("empAddrNotNull", testAddr);
+        newAttr = doc.createAttributeNS(namespaceURI, qualifiedName);
+        newAddrAttr = ((Element) /* Node */testAddr)
+                .setAttributeNodeNS(newAttr);
+        assertNull("throw_Null", newAddrAttr);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Doesn't verify DOMException.",
+        method = "setAttributeNodeNS",
+        args = {org.w3c.dom.Attr.class}
+    )
+    public void testSetAttributeNode4() throws Throwable {
+        Document doc;
+        NodeList elementList;
+        Node testAddr;
+        Attr newAttr;
+        Attr newAddrAttr;
+        String newName;
+        doc = (Document) load("staffNS", builder);
+        elementList = doc.getElementsByTagName("emp:address");
+        testAddr = elementList.item(0);
+        assertNotNull("empAddrNotNull", testAddr);
+        newAttr = doc.createAttributeNS("http://www.nist.gov", "xxx:domestic");
+        newAddrAttr = ((Element) /* Node */testAddr)
+                .setAttributeNodeNS(newAttr);
+        newName = newAddrAttr.getNodeName();
+        assertEquals("nodeName", "emp:domestic", newName);
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies DOMException with WRONG_DOCUMENT_ERR code.",
+        method = "setAttributeNodeNS",
+        args = {org.w3c.dom.Attr.class}
+    )
+    public void testSetAttributeNode5() throws Throwable {
+        String namespaceURI = "http://www.newattr.com";
+        String qualifiedName = "emp:newAttr";
+        Document doc1;
+        Document doc2;
+        Attr newAttr;
+        NodeList elementList;
+        Node testAddr;
+
+        doc1 = (Document) load("staffNS", builder);
+        doc2 = (Document) load("staffNS", builder);
+        newAttr = doc2.createAttributeNS(namespaceURI, qualifiedName);
+        elementList = doc1.getElementsByTagName("emp:address");
+        testAddr = elementList.item(0);
+
+        {
+            boolean success = false;
+            try {
+                ((Element) /* Node */testAddr).setAttributeNodeNS(newAttr);
+            } catch (DOMException ex) {
+                success = (ex.code == DOMException.WRONG_DOCUMENT_ERR);
+            }
+            assertTrue("throw_WRONG_DOCUMENT_ERR", success);
+        }
+    }
+}
diff --git a/xml/src/test/java/tests/org/w3c/dom/SetNamedItemNS.java b/xml/src/test/java/tests/org/w3c/dom/SetNamedItemNS.java
new file mode 100644
index 0000000..ae364ec
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/SetNamedItemNS.java
@@ -0,0 +1,248 @@
+
+/*
+This Java source file was generated by test-to-java.xsl
+and is a derived work from the source document.
+The source document contained the following notice:
+
+
+
+Copyright (c) 2001 World Wide Web Consortium, 
+(Massachusetts Institute of Technology, Institut National de
+Recherche en Informatique et en Automatique, Keio University).  All 
+Rights Reserved.  This program is distributed under the W3C's Software
+Intellectual Property License.  This program is distributed in the 
+hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+PURPOSE.  
+
+See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+*/
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.DOMException;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ *     The "setNamedItemNS(arg)" method for a 
+ *    NamedNodeMap should raise INUSE_ATTRIBUTE_ERR DOMException if 
+ *    arg is an Attr that is already an attribute of another Element object.
+ *    
+ *    Retrieve an attr node from the third "address" element whose local name
+ *    is "domestic" and namespaceURI is "http://www.netzero.com".
+ *    Invoke method setNamedItemNS(arg) on the map of the first "address" element with
+ *    arg being the attr node from above.  Method should raise
+ *    INUSE_ATTRIBUTE_ERR DOMException.
+* @author NIST
+* @author Mary Brady
+* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='INUSE_ATTRIBUTE_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='INUSE_ATTRIBUTE_ERR'])</a>
+* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-setNamedItemNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-setNamedItemNS</a>
+* @see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-setNamedItemNS')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='INUSE_ATTRIBUTE_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-setNamedItemNS')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='INUSE_ATTRIBUTE_ERR'])</a>
+*/
+@TestTargetClass(NamedNodeMap.class) 
+public final class SetNamedItemNS extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration2());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+   /**
+    * Runs the test case.
+    * @throws Throwable Any uncaught exception causes test to fail
+    */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies DOMException with INUSE_ATTRIBUTE_ERR code.",
+        method = "setNamedItemNS",
+        args = {org.w3c.dom.Node.class}
+    )
+   public void testSetNamedItemNS1() throws Throwable {
+      Document doc;
+      NodeList elementList;
+      Node anotherElement;
+      NamedNodeMap anotherMap;
+      Node arg;
+      Node testAddress;
+      NamedNodeMap map;
+      
+      doc = (Document) load("staffNS", builder);
+      elementList = doc.getElementsByTagName("address");
+      anotherElement = elementList.item(2);
+      anotherMap = anotherElement.getAttributes();
+      arg = anotherMap.getNamedItemNS("http://www.netzero.com", "domestic");
+      testAddress = elementList.item(0);
+      map = testAddress.getAttributes();
+      
+      {
+         boolean success = false;
+         try {
+            map.setNamedItemNS(arg);
+          } catch (DOMException ex) {
+            success = (ex.code == DOMException.INUSE_ATTRIBUTE_ERR);
+         }
+         assertTrue("throw_INUSE_ATTRIBUTE_ERR", success);
+      }
+}
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies DOMException with WRONG_DOCUMENT_ERR code.",
+        method = "setNamedItemNS",
+        args = {org.w3c.dom.Node.class}
+    )
+   public void testSetNamedItemNS2() throws Throwable {
+          String namespaceURI = "http://www.usa.com";
+          String qualifiedName = "dmstc:domestic";
+          Document doc;
+          Document anotherDoc;
+          Node arg;
+          NodeList elementList;
+          Node testAddress;
+          NamedNodeMap attributes;
+         
+          doc = (Document) load("staffNS", builder);
+          anotherDoc = (Document) load("staffNS", builder);
+          arg = anotherDoc.createAttributeNS(namespaceURI, qualifiedName);
+          arg.setNodeValue("Maybe");
+          elementList = doc.getElementsByTagName("address");
+          testAddress = elementList.item(0);
+          attributes = testAddress.getAttributes();
+          
+          {
+             boolean success = false;
+             try {
+                attributes.setNamedItemNS(arg);
+              } catch (DOMException ex) {
+                success = (ex.code == DOMException.WRONG_DOCUMENT_ERR);
+             }
+             assertTrue("throw_WRONG_DOCUMENT_ERR", success);
+          }
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies positive fnctionality.",
+        method = "getNamedItemNS",
+        args = {java.lang.String.class, java.lang.String.class}
+    )
+   public void testSetNamedItemNS3() throws Throwable {
+          String namespaceURI = "http://www.nist.gov";
+          String qualifiedName = "prefix:newAttr";
+          Document doc;
+          Node arg;
+          NodeList elementList;
+          Node testAddress;
+          NamedNodeMap attributes;
+          Node retnode;
+          String value;
+          
+          doc = (Document) load("staffNS", builder);
+          arg = doc.createAttributeNS(namespaceURI, qualifiedName);
+          arg.setNodeValue("newValue");
+          elementList = doc.getElementsByTagName("address");
+          testAddress = elementList.item(0);
+          attributes = testAddress.getAttributes();
+          attributes.setNamedItemNS(arg);
+          retnode = attributes.getNamedItemNS(namespaceURI, "newAttr");
+          value = retnode.getNodeValue();
+          assertEquals("throw_Equals", "newValue", value);
+          }
+
+// Assumes validation.
+//   public void testSetNamedItemNS4() throws Throwable {
+//          String namespaceURI = "http://www.w3.org/2000/xmlns/";
+//          String localName = "local1";
+//          Document doc;
+//          NodeList elementList;
+//          Node testAddress;
+//          NodeList nList;
+//          Node child;
+//          NodeList n2List;
+//          Node child2;
+//          NamedNodeMap attributes;
+//          Node arg;
+//          
+//          int nodeType;
+//          doc = (Document) load("staffNS", builder);
+//          elementList = doc.getElementsByTagName("gender");
+//          testAddress = elementList.item(2);
+//          nList = testAddress.getChildNodes();
+//          child = nList.item(0);
+//          nodeType = (int) child.getNodeType();
+//          
+//          if (1 == nodeType) {
+//              child = doc.createEntityReference("ent4");
+//          assertNotNull("createdEntRefNotNull", child);
+//          }
+//        n2List = child.getChildNodes();
+//          child2 = n2List.item(0);
+//          assertNotNull("notnull", child2);
+//          attributes = child2.getAttributes();
+//          arg = attributes.getNamedItemNS(namespaceURI, localName);
+//          
+//          {
+//             boolean success = false;
+//             try {
+//                attributes.setNamedItemNS(arg);
+//              } catch (DOMException ex) {
+//                success = (ex.code == DOMException.NO_MODIFICATION_ALLOWED_ERR);
+//             }
+//             assertTrue("throw_NO_MODIFICATION_ALLOWED_ERR", success);
+//          }
+//    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Verifies positive fnctionality.",
+        method = "setNamedItemNS",
+        args = {org.w3c.dom.Node.class}
+    )
+   public void testSetNamedItemNS5() throws Throwable {
+          String namespaceURI = "http://www.usa.com";
+          String qualifiedName = "dmstc:domestic";
+          Document doc;
+          Node arg;
+          NodeList elementList;
+          Node testAddress;
+          NamedNodeMap attributes;
+          Node retnode;
+          String value;
+          doc = (Document) load("staffNS", builder);
+          arg = doc.createAttributeNS(namespaceURI, qualifiedName);
+          arg.setNodeValue("newValue");
+          elementList = doc.getElementsByTagName("address");
+          testAddress = elementList.item(0);
+          attributes = testAddress.getAttributes();
+          retnode = attributes.setNamedItemNS(arg);
+          value = retnode.getNodeValue();
+          assertEquals("throw_Equals", "Yes", value);
+          }
+  
+}
+
diff --git a/xml/src/test/java/tests/org/w3c/dom/SystemId.java b/xml/src/test/java/tests/org/w3c/dom/SystemId.java
new file mode 100644
index 0000000..3e1b903
--- /dev/null
+++ b/xml/src/test/java/tests/org/w3c/dom/SystemId.java
@@ -0,0 +1,94 @@
+/*
+ This Java source file was generated by test-to-java.xsl
+ and is a derived work from the source document.
+ The source document contained the following notice:
+
+
+
+ Copyright (c) 2001 World Wide Web Consortium, 
+ (Massachusetts Institute of Technology, Institut National de
+ Recherche en Informatique et en Automatique, Keio University).  All 
+ Rights Reserved.  This program is distributed under the W3C's Software
+ Intellectual Property License.  This program is distributed in the 
+ hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ PURPOSE.  
+
+ See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+
+ */
+
+package tests.org.w3c.dom;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Document;
+
+import javax.xml.parsers.DocumentBuilder;
+
+/**
+ * The "getSystemId()" method of a documenttype node contains the system
+ * identifier associated with the external subset.
+ * 
+ * Retrieve the documenttype. Apply the "getSystemId()" method. The string
+ * "staffNS.dtd" should be returned.
+ * 
+ * @author NIST
+ * @author Mary Brady
+ * @see <a
+ *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-Core-DocType-systemId">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-Core-DocType-systemId</a>
+ */
+@TestTargetClass(DocumentType.class) 
+public final class SystemId extends DOMTestCase {
+
+    DOMDocumentBuilderFactory factory;
+
+    DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        try {
+            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
+                    .getConfiguration1());
+            builder = factory.getBuilder();
+        } catch (Exception e) {
+            fail("Unexpected exception" + e.getMessage());
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        factory = null;
+        builder = null;
+        super.tearDown();
+    }
+
+    /**
+     * Runs the test case.
+     * 
+     * @throws Throwable
+     *             Any uncaught exception causes test to fail
+     */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "getSystemId",
+        args = {}
+    )
+    public void testGetSystemId() throws Throwable {
+        Document doc;
+        DocumentType docType;
+        String systemId;
+
+        doc = (Document) load("staffNS", builder);
+        docType = doc.getDoctype();
+        systemId = docType.getSystemId();
+        assertURIEquals("systemId", null, null, null, "staffNS.dtd", null,
+                null, null, null, systemId);
+    }
+
+}
diff --git a/xml/src/test/java/tests/xml/AllTests.java b/xml/src/test/java/tests/xml/AllTests.java
new file mode 100644
index 0000000..eefae50
--- /dev/null
+++ b/xml/src/test/java/tests/xml/AllTests.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.xml;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+
+    public static Test suite() {
+        TestSuite suite = tests.TestSuiteFactory.createTestSuite();
+
+        suite.addTestSuite(SimpleParserTest.class);
+        suite.addTestSuite(SimpleBuilderTest.class);
+        
+        //suite.addTest(tests.org.w3c.dom.AllTests.suite());
+        suite.addTest(tests.api.javax.xml.parsers.AllTests.suite());
+
+        suite.addTest(tests.api.org.xml.sax.AllTests.suite());
+        
+        return suite;
+    }
+
+}
diff --git a/xml/src/test/java/tests/xml/SimpleBuilderTest.java b/xml/src/test/java/tests/xml/SimpleBuilderTest.java
new file mode 100644
index 0000000..1a555c6
--- /dev/null
+++ b/xml/src/test/java/tests/xml/SimpleBuilderTest.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.xml;
+
+import dalvik.annotation.BrokenTest;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import junit.framework.TestCase;
+
+import org.w3c.dom.Comment;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+@TestTargetClass(DocumentBuilder.class) 
+public class SimpleBuilderTest extends TestCase {
+
+    private DocumentBuilder builder;
+
+    protected void setUp() throws Exception {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        factory.setValidating(false);
+        factory.setNamespaceAware(true);
+
+        builder = factory.newDocumentBuilder();
+    }
+
+    protected void tearDown() throws Exception {
+        builder = null;
+    }
+
+    private String getTextContent(Node node) {
+        String result = (node instanceof Text ? ((Text) node).getData() : "");
+
+        Node child = node.getFirstChild();
+        while (child != null) {
+            result = result + getTextContent(child);
+            child = child.getNextSibling();
+        }
+
+        return result;
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Regression test.",
+        method = "parse",
+        args = {java.io.InputStream.class}
+    )
+    public void testGoodFile1() throws Exception {
+        Document document = builder.parse(getClass().getResourceAsStream(
+                "/SimpleBuilderTest.xml"));
+
+        Element root = document.getDocumentElement();
+        assertNotNull(root);
+        assertEquals("http://www.foo.bar", root.getNamespaceURI());
+        assertEquals("t", root.getPrefix());
+        assertEquals("stuff", root.getLocalName());
+
+        NodeList list = root.getElementsByTagName("nestedStuff");
+        assertNotNull(list);
+        assertEquals(list.getLength(), 4);
+
+        Element one = (Element) list.item(0);
+        Element two = (Element) list.item(1);
+        Element three = (Element) list.item(2);
+        Element four = (Element) list.item(3);
+
+        assertEquals("This space intentionally left blank.",
+                getTextContent(one));
+        assertEquals("Nothing to see here - please get along!",
+                getTextContent(two));
+        assertEquals("Rent this space!", getTextContent(three));
+        assertEquals("", getTextContent(four));
+
+        assertEquals("eins", one.getAttribute("one"));
+        assertEquals("zwei", two.getAttribute("two"));
+        assertEquals("drei", three.getAttribute("three"));
+
+        assertEquals("vier", four.getAttribute("t:four"));
+        assertEquals("vier", four.getAttributeNS("http://www.foo.bar", "four"));
+
+        list = document.getChildNodes();
+        assertNotNull(list);
+
+        String proinst = "";
+        String comment = "";
+
+        for (int i = 0; i < list.getLength(); i++) {
+            Node node = list.item(i);
+
+            if (node instanceof ProcessingInstruction) {
+                proinst = proinst + node.getNodeValue();
+            } else if (node instanceof Comment) {
+                comment = comment + node.getNodeValue();
+            }
+        }
+
+        assertEquals("The quick brown fox jumps over the lazy dog.", proinst);
+        assertEquals(" Fragile!  Handle me with care! ", comment);
+    }
+    @TestTargetNew(
+        level = TestLevel.ADDITIONAL,
+        method = "!todo parse",
+        args = {java.io.InputStream.class}
+    )
+    @BrokenTest("Doesn't verify anything.")
+    public void testGoodFile2() throws Exception {
+        Document document = builder.parse(getClass().getResourceAsStream(
+                "/staffNS.xml"));
+
+        Element root = document.getDocumentElement();
+        assertNotNull(root);
+        
+        // dump("", root);
+    }
+    
+    private void dump(String prefix, Element element) {
+        System.out.print(prefix + "<" + element.getTagName());
+        
+        NamedNodeMap attrs = element.getAttributes();
+        for (int i = 0; i < attrs.getLength(); i++) {
+            Node item = attrs.item(i);
+            System.out.print(" " + item.getNodeName() + "=" + item.getNodeValue());
+        }
+        
+        System.out.println(">");
+        
+        NodeList children = element.getChildNodes();
+        for (int i = 0; i < children.getLength(); i++) {
+            Node item = children.item(i);
+            if (item instanceof Element) {
+                dump(prefix + "  ", (Element)item);
+            }
+        }
+        
+        System.out.println(prefix + "</" + element.getTagName() + ">");
+    }
+}
diff --git a/xml/src/test/java/tests/xml/SimpleParserTest.java b/xml/src/test/java/tests/xml/SimpleParserTest.java
new file mode 100644
index 0000000..4651039
--- /dev/null
+++ b/xml/src/test/java/tests/xml/SimpleParserTest.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 tests.xml;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+@TestTargetClass(SAXParser.class) 
+public class SimpleParserTest extends TestCase implements ContentHandler {
+
+    private SAXParser parser;
+
+    private StringBuffer instructions;
+
+    private Map<String, String> namespaces1;
+    private Map<String, String> namespaces2;
+
+    private StringBuffer elements1;
+    private StringBuffer elements2;
+
+    private Map<String, String> attributes1;
+    private Map<String, String> attributes2;
+
+    private StringBuffer text;
+
+    @Override
+    protected void setUp() throws Exception {
+        SAXParserFactory factory = SAXParserFactory.newInstance();
+        factory.setValidating(false);
+        factory.setNamespaceAware(true);
+
+        parser = factory.newSAXParser();
+        parser.getXMLReader().setContentHandler(this);
+
+        instructions = new StringBuffer();
+        namespaces1 = new HashMap<String, String>();
+        namespaces2 = new HashMap<String, String>();
+        elements1 = new StringBuffer();
+        elements2 = new StringBuffer();
+        attributes1 = new HashMap<String, String>();
+        attributes2 = new HashMap<String, String>();
+        text = new StringBuffer();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        instructions = null;
+        parser = null;
+        namespaces1 = null;
+        namespaces2 = null;
+        attributes1 = null;
+        attributes2 = null;
+        elements1 = null;
+        elements2 = null;
+        text = null;
+    }
+
+    public void characters(char[] ch, int start, int length) {
+
+        String s = new String(ch, start, length).trim();
+        if (s.length() != 0) {
+            if (text.length() != 0) {
+                text.append(",");
+            }
+
+            text.append(s);
+        }
+    }
+
+    public void endDocument() {
+    }
+
+    public void endElement(String uri, String localName, String qName) {
+    }
+
+    public void endPrefixMapping(String prefix) {
+    }
+
+    public void ignorableWhitespace(char[] ch, int start, int length) {
+    }
+
+    public void processingInstruction(String target, String data) {
+        String s = target + ":" + data;
+
+        if (instructions.length() != 0) {
+            instructions.append(",");
+        }
+
+        instructions.append(s);
+    }
+
+    public void setDocumentLocator(Locator locator) {
+    }
+
+    public void skippedEntity(String name) {
+    }
+
+    public void startDocument() {
+    }
+
+    public void startElement(String uri, String localName, String qName,
+            Attributes atts) {
+
+        if (elements1.length() != 0) {
+            elements1.append(",");
+        }
+
+        elements1.append(localName);
+
+        if (!"".equals(uri)) {
+            namespaces1.put(localName, uri);
+        }
+
+        for (int i = 0; i < atts.getLength(); i++) {
+            attributes1.put(atts.getLocalName(i), atts.getValue(i));
+        }
+
+        if (elements2.length() != 0) {
+            elements2.append(",");
+        }
+
+        elements2.append(qName);
+
+        if (!"".equals(uri)) {
+            namespaces2.put(qName, uri);
+        }
+
+        for (int i = 0; i < atts.getLength(); i++) {
+            attributes2.put(atts.getQName(i), atts.getValue(i));
+        }
+    }
+
+    public void startPrefixMapping(String prefix, String uri) {
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "",
+        method = "parse",
+        args = {java.io.InputStream.class, org.xml.sax.helpers.DefaultHandler.class}
+    )
+    public void testWorkingFile1() throws Exception {
+        SAXParserFactory factory = SAXParserFactory.newInstance();
+        factory.setValidating(false);
+        factory.setNamespaceAware(true);
+
+        SAXParser parser = factory.newSAXParser();
+        parser.getXMLReader().setContentHandler(this);
+
+        parser.parse(getClass().getResourceAsStream("/SimpleParserTest.xml"),
+                (DefaultHandler) null);
+
+        assertEquals("The:quick,brown:fox", instructions.toString());
+
+        assertEquals("stuff,nestedStuff,nestedStuff,nestedStuff", elements1
+                .toString());
+
+        assertEquals("Some text here,some more here...", text.toString());
+
+        assertEquals("eins", attributes1.get("one"));
+        assertEquals("zwei", attributes1.get("two"));
+        assertEquals("drei", attributes1.get("three"));
+
+        assertEquals("http://www.foobar.org", namespaces1.get("stuff"));
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "",
+        method = "parse",
+        args = {java.io.InputStream.class, org.xml.sax.helpers.DefaultHandler.class}
+    )
+    public void testWorkingFile2() throws Exception {
+        SAXParserFactory factory = SAXParserFactory.newInstance();
+
+        factory.setValidating(false);
+        factory.setNamespaceAware(false);
+        factory.setFeature("http://xml.org/sax/features/namespace-prefixes",
+                true);
+
+        SAXParser parser = factory.newSAXParser();
+        parser.getXMLReader().setContentHandler(this);
+        parser.parse(getClass().getResourceAsStream("/SimpleParserTest.xml"),
+                (DefaultHandler) null);
+
+        assertFalse(parser.isNamespaceAware());
+
+        assertEquals("The:quick,brown:fox", instructions.toString());
+
+        assertEquals("t:stuff,nestedStuff,nestedStuff,nestedStuff", elements2
+                .toString());
+
+        assertEquals("Some text here,some more here...", text.toString());
+
+        assertEquals("eins", attributes2.get("one"));
+        assertEquals("zwei", attributes2.get("two"));
+        assertEquals("drei", attributes2.get("three"));
+
+        assertEquals(0, namespaces2.size());
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify exceptions.",
+        method = "parse",
+        args = {java.io.InputStream.class, org.xml.sax.helpers.DefaultHandler.class}
+    )
+    public void testEntityResolver() throws Exception {
+        final StringBuilder text = new StringBuilder();
+        DefaultHandler handler = new DefaultHandler() {
+            public void characters(char[] ch, int start, int length) {
+                String s = new String(ch, start, length).trim();
+                if (s.length() != 0) {
+                    if (text.length() != 0) {
+                        text.append(",");
+                    }
+                    text.append(s);
+                }
+            }
+
+            public InputSource resolveEntity(String publicId, String systemId)
+                    throws IOException, SAXException {
+                return new InputSource(new InputStreamReader(
+                        new ByteArrayInputStream("test".getBytes())));
+            }
+        };
+
+        SAXParserFactory spf = SAXParserFactory.newInstance();
+        spf.setValidating(false);
+        parser = spf.newSAXParser();
+        parser.parse(this.getClass().getResourceAsStream("/staffEntRes.xml"),
+                handler);
+        assertTrue(
+                "resolved external entity must be in parser character stream",
+                text.toString().contains("test"));
+    }
+    @TestTargetNew(
+        level = TestLevel.PARTIAL,
+        notes = "Doesn't verify exceptions.",
+        method = "parse",
+        args = {java.io.InputStream.class, org.xml.sax.helpers.DefaultHandler.class}
+    )
+    public void testGetValue() throws Exception{
+        parser.parse(getClass().getResourceAsStream("/staffNS.xml"), 
+                new DefaultHandler() {
+            boolean firstAddressElem = true;
+            @Override
+            public void startElement (String uri, String localName,
+                    String qName, Attributes attributes) {
+                if(firstAddressElem && localName.equals("address")) {
+                    firstAddressElem = false;
+                    assertNotNull(attributes.getValue("http://www.usa.com",
+                            "domestic"));
+                }
+            }
+        });
+    }
+}
diff --git a/xml/src/test/resources/SimpleBuilderTest.xml b/xml/src/test/resources/SimpleBuilderTest.xml
new file mode 100644
index 0000000..23edce7
--- /dev/null
+++ b/xml/src/test/resources/SimpleBuilderTest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+
+<!-- Fragile! -->
+
+<!-- Handle me with care! -->
+
+<?cmd The quick brown fox ?>
+
+<t:stuff xmlns:t="http://www.foo.bar" xmlns:u="http://www.bar.foo">
+
+	<nestedStuff one="eins">This space intentionally left blank.</nestedStuff>
+
+	<nestedStuff two="zwei">Nothing to see here - please get along!</nestedStuff>
+
+	<nestedStuff three="drei" title="">Rent this space!</nestedStuff>
+
+	<nestedStuff t:four="vier"/>
+
+</t:stuff>
+
+<?cmd jumps over the lazy dog.?>
diff --git a/xml/src/test/resources/SimpleParserTest.xml b/xml/src/test/resources/SimpleParserTest.xml
new file mode 100644
index 0000000..e18bf3e
--- /dev/null
+++ b/xml/src/test/resources/SimpleParserTest.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+
+<!-- This space intentionally left blank. -->
+
+<?The quick?>
+
+<t:stuff xmlns:t="http://www.foobar.org">
+
+	<nestedStuff one="eins">   Some text here   </nestedStuff>
+
+	<nestedStuff two="zwei"></nestedStuff>
+
+    some more here...
+
+	<nestedStuff three="drei" />
+
+</t:stuff>
+
+<?brown fox?>
diff --git a/xml/src/test/resources/hc_staff.xml b/xml/src/test/resources/hc_staff.xml
new file mode 100644
index 0000000..2df9a74
--- /dev/null
+++ b/xml/src/test/resources/hc_staff.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0"?><?TEST-STYLE PIDATA?>
+<!DOCTYPE html
+   PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+   "xhtml1-strict.dtd" [
+   <!ENTITY alpha "&#945;">
+   <!ENTITY beta "&#946;">
+   <!ENTITY gamma "&#947;">
+   <!ENTITY delta "&#948;">
+   <!ENTITY epsilon "&#949;">
+   <!ENTITY alpha "&#950;">
+   <!NOTATION notation1 PUBLIC "notation1File">
+   <!NOTATION notation2 SYSTEM "notation2File">
+   <!ATTLIST acronym dir CDATA "ltr">
+]>
+<!-- This is comment number 1.-->
+<html xmlns='http://www.w3.org/1999/xhtml'><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><title>hc_staff</title><script type="text/javascript" src="svgunit.js"/><script charset="UTF-8" type="text/javascript" src="svgtest.js"/><script type='text/javascript'>function loadComplete() { startTest(); }</script></head><body onload="parent.loadComplete()">
+ <p>
+  <em>EMP0001</em>
+  <strong>Margaret Martin</strong>
+  <code>Accountant</code>           
+  <sup>56,000</sup>
+  <var>Female</var>
+  <acronym title="Yes">1230 North Ave. Dallas, Texas 98551</acronym>
+ </p>
+ <p>
+  <em>EMP0002</em>
+  <strong>Martha RaynoldsThis is a CDATASection with EntityReference number 2 &amp;ent2;
+This is an adjacent CDATASection with a reference to a tab &amp;tab;</strong>
+  <code>Secretary</code>
+  <sup>35,000</sup>
+  <var>Female</var>
+  <acronym title="Yes" class="Yes">&beta; Dallas, &gamma;
+ 98554</acronym>
+ </p>
+ <p>
+  <em>EMP0003</em>
+  <strong>Roger
+ Jones</strong>
+  <code>Department Manager</code>
+  <sup>100,000</sup>
+  <var>&delta;</var>
+  <acronym title="Yes" class="No">PO Box 27 Irving, texas 98553</acronym>
+ </p>
+ <p>
+  <em>EMP0004</em>
+  <strong>Jeny Oconnor</strong>
+  <code>Personnel Director</code>
+  <sup>95,000</sup>
+  <var>Female</var>
+  <acronym title="Yes" class="Y&alpha;">27 South Road. Dallas, Texas 98556</acronym>
+ </p>
+ <p>
+  <em>EMP0005</em>
+  <strong>Robert Myers</strong>
+  <code>Computer Specialist</code>
+  <sup>90,000</sup>
+  <var>male</var>
+  <acronym title="Yes">1821 Nordic. Road, Irving Texas 98558</acronym>
+ </p>
+</body></html>
diff --git a/xml/src/test/resources/nwf/staff.dtd b/xml/src/test/resources/nwf/staff.dtd
new file mode 100644
index 0000000..02a994d
--- /dev/null
+++ b/xml/src/test/resources/nwf/staff.dtd
@@ -0,0 +1,17 @@
+<!ELEMENT employeeId (#PCDATA)>
+<!ELEMENT name (#PCDATA)>
+<!ELEMENT position (#PCDATA)>
+<!ELEMENT salary (#PCDATA)>
+<!ELEMENT address (#PCDATA)>
+<!ELEMENT entElement ( #PCDATA ) >
+<!ELEMENT gender ( #PCDATA | entElement )* >
+<!ELEMENT employee (employeeId, name, position, salary, gender, address) >
+<!ELEMENT staff (employee)+>
+<!ATTLIST entElement 
+          attr1 CDATA "Attr">
+<!ATTLIST address
+          domestic CDATA #IMPLIED 
+          street CDATA "Yes">
+<!ATTLIST entElement 
+          domestic CDATA "MALE" >
+
diff --git a/xml/src/test/resources/nwf/staff.xml b/xml/src/test/resources/nwf/staff.xml
new file mode 100644
index 0000000..b600fcf
--- /dev/null
+++ b/xml/src/test/resources/nwf/staff.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0"?><?TEST-STYLE PIDATA?>
+<!DOCTYPE staff SYSTEM "staff.dtd" [
+   <!ENTITY ent1 "es">
+   <!ENTITY ent2 "1900 Dallas Road">
+   <!ENTITY ent3 "Texas">
+   <!ENTITY ent4 "<entElement domestic='Yes'>Element data</entElement><?PItarget PIdata?>">
+   <!ENTITY ent5 PUBLIC "entityURI" "entityFile" NDATA notation1>
+   <!ENTITY ent1 "This entity should be discarded">
+   <!NOTATION notation1 PUBLIC "notation1File">
+   <!NOTATION notation2 SYSTEM "notation2File">
+]>
+<!-- This is comment number 1.-->
+<staff>
+ <employee22>
+  <employeeId>EMP0001</employeeId>
+  <name>Margaret Martin</name>
+  <position>Accountant</position>           
+  <salary>56,000</salary>
+  <gender>Female</gender>
+  <address domestic="Yes">1230 North Ave. Dallas, Texas 98551</address>
+ </employee>
+ <employee>
+  <employeeId>EMP0002</employeeId>
+  <name>Martha Raynolds<![CDATA[This is a CDATASection with EntityReference number 2 &ent2;]]>
+<![CDATA[This is an adjacent CDATASection with a reference to a tab &tab;]]></name>
+  <position>Secretary</position>
+  <salary>35,000</salary>
+  <gender>Female</gender>
+  <address domestic="Yes" street="Yes">&ent2; Dallas, &ent3;
+ 98554</address>
+ </employee>
+ <employee>
+  <employeeId>EMP0003</employeeId>
+  <name>Roger
+ Jones</name>
+  <position>Department Manager</position>
+  <salary>100,000</salary>
+  <gender>&ent4;</gender>
+  <address domestic="Yes" street="No">PO Box 27 Irving, texas 98553</address>
+ </employee>
+ <employee>
+  <employeeId>EMP0004</employeeId>
+  <name>Jeny Oconnor</name>
+  <position>Personnel Director</position>
+  <salary>95,000</salary>
+  <gender>Female</gender>
+  <address domestic="Yes" street="Y&ent1;">27 South Road. Dallas, Texas 98556</address>
+ </employee>
+ <employee>
+  <employeeId>EMP0005</employeeId>
+  <name>Robert Myers</name>
+  <position>Computer Specialist</position>
+  <salary>90,000</salary>
+  <gender>male</gender>
+  <address street="Yes">1821 Nordic. Road, Irving Texas 98558</address>
+ </employee>
+ </staff>
diff --git a/xml/src/test/resources/out_dh/staff.out b/xml/src/test/resources/out_dh/staff.out
new file mode 100644
index 0000000..467fd08
--- /dev/null
+++ b/xml/src/test/resources/out_dh/staff.out
@@ -0,0 +1,45 @@
+true^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#true^#
+ 
+  EMP0001
+  Margaret Martin
+  Accountant           
+  56,000
+  Female
+  1230 North Ave. Dallas, Texas 98551
+ 
+ 
+  EMP0002
+  Martha RaynoldsThis is a CDATASection with EntityReference number 2 &ent2;
+This is an adjacent CDATASection with a reference to a tab &tab;
+  Secretary
+  35,000
+  Female
+  1900 Dallas Road Dallas, Texas
+ 98554
+ 
+ 
+  EMP0003
+  Roger
+ Jones
+  Department Manager
+  100,000
+  Element data
+  PO Box 27 Irving, texas 98553
+ 
+ 
+  EMP0004
+  Jeny Oconnor
+  Personnel Director
+  95,000
+  Female
+  27 South Road. Dallas, Texas 98556
+ 
+ 
+  EMP0005
+  Robert Myers
+  Computer Specialist
+  90,000
+  male
+  1821 Nordic. Road, Irving Texas 98558
+ 
+ ####$employeeId$employeeId^$name$name^$position$position^$salary$salary^$gender$gender^$address$address^$employee$employee^$employeeId$employeeId^$name$name^$position$position^$salary$salary^$gender$gender^$address$address^$employee$employee^$employeeId$employeeId^$name$name^$position$position^$salary$salary^$entElement$entElement^$gender$gender^$address$address^$employee$employee^$employeeId$employeeId^$name$name^$position$position^$salary$salary^$gender$gender^$address$address^$employee$employee^$employeeId$employeeId^$name$name^$position$position^$salary$salary^$gender$gender^$address$address^$employee$employee^$staff$staff^##TEST-STYLE$PIDATA^PItarget$PIdata^##$staff$staff$employee$employee$employeeId$employeeId$name$name$position$position$salary$salary$gender$gender$address$address$domestic$Yes$employee$employee$employeeId$employeeId$name$name$position$position$salary$salary$gender$gender$address$address$domestic$Yes$street$Yes$employee$employee$employeeId$employeeId$name$name$position$position$salary$salary$gender$gender$entElement$entElement$domestic$Yes$address$address$domestic$Yes$street$No$employee$employee$employeeId$employeeId$name$name$position$position$salary$salary$gender$gender$address$address$domestic$Yes$street$Yes$employee$employee$employeeId$employeeId$name$name$position$position$salary$salary$gender$gender$address$address$street$Yes##
diff --git a/xml/src/test/resources/out_hb/staff.out b/xml/src/test/resources/out_hb/staff.out
new file mode 100644
index 0000000..c6d61ad
--- /dev/null
+++ b/xml/src/test/resources/out_hb/staff.out
@@ -0,0 +1,45 @@
+true^#true^#
+ 
+  EMP0001
+  Margaret Martin
+  Accountant           
+  56,000
+  Female
+  1230 North Ave. Dallas, Texas 98551
+ 
+ 
+  EMP0002
+  Martha RaynoldsThis is a CDATASection with EntityReference number 2 &ent2;
+This is an adjacent CDATASection with a reference to a tab &tab;
+  Secretary
+  35,000
+  Female
+  1900 Dallas Road Dallas, Texas
+ 98554
+ 
+ 
+  EMP0003
+  Roger
+ Jones
+  Department Manager
+  100,000
+  Element data
+  PO Box 27 Irving, texas 98553
+ 
+ 
+  EMP0004
+  Jeny Oconnor
+  Personnel Director
+  95,000
+  Female
+  27 South Road. Dallas, Texas 98556
+ 
+ 
+  EMP0005
+  Robert Myers
+  Computer Specialist
+  90,000
+  male
+  1821 Nordic. Road, Irving Texas 98558
+ 
+ ######TEST-STYLE$PIDATA^PItarget$PIdata^####
diff --git a/xml/src/test/resources/recipe.xml b/xml/src/test/resources/recipe.xml
new file mode 100644
index 0000000..d7cf0fb
--- /dev/null
+++ b/xml/src/test/resources/recipe.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE collection SYSTEM "./recipt.dtd">
+<!--comment1 -->
+<collection>
+  <description>
+     Some recipes used for the XML tutorial.
+  </description>
+  <recipe>
+    <title>Beef Parmesan<![CDATA[<title> with Garlic Angel Hair Pasta</title>]]></title>
+    <ingredient name="beef cube steak" amount="1.5" unit="pound"/>
+    <preparation>
+      <step>
+        Preheat oven to 350 degrees F (175 degrees C).
+      </step>
+    </preparation>
+    <comment>
+      Make the meat ahead of time, and refrigerate over night, the acid in the
+      tomato sauce will tenderize the meat even more. If you do this, save the
+      mozzarella till the last minute.
+    </comment>
+    <nutrition calories="1167" fat="23" carbohydrates="45" protein="32"/>
+  </recipe>
+</collection>
+<!--comment2 -->
diff --git a/xml/src/test/resources/recipe1.xml b/xml/src/test/resources/recipe1.xml
new file mode 100644
index 0000000..d7cf0fb
--- /dev/null
+++ b/xml/src/test/resources/recipe1.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE collection SYSTEM "./recipt.dtd">
+<!--comment1 -->
+<collection>
+  <description>
+     Some recipes used for the XML tutorial.
+  </description>
+  <recipe>
+    <title>Beef Parmesan<![CDATA[<title> with Garlic Angel Hair Pasta</title>]]></title>
+    <ingredient name="beef cube steak" amount="1.5" unit="pound"/>
+    <preparation>
+      <step>
+        Preheat oven to 350 degrees F (175 degrees C).
+      </step>
+    </preparation>
+    <comment>
+      Make the meat ahead of time, and refrigerate over night, the acid in the
+      tomato sauce will tenderize the meat even more. If you do this, save the
+      mozzarella till the last minute.
+    </comment>
+    <nutrition calories="1167" fat="23" carbohydrates="45" protein="32"/>
+  </recipe>
+</collection>
+<!--comment2 -->
diff --git a/xml/src/test/resources/recipt.dtd b/xml/src/test/resources/recipt.dtd
new file mode 100644
index 0000000..370112c
--- /dev/null
+++ b/xml/src/test/resources/recipt.dtd
@@ -0,0 +1,17 @@
+<!ELEMENT collection (description,recipe+)>
+<!ELEMENT description ANY>
+<!ELEMENT recipe (title,ingredient*,preparation,comment?,nutrition)>
+<!ELEMENT title (#PCDATA)>
+<!ELEMENT ingredient (ingredient*,preparation)?>
+<!ATTLIST ingredient name CDATA #REQUIRED
+                     amount CDATA #IMPLIED
+                     unit CDATA #IMPLIED>
+<!ELEMENT preparation (step*)>
+<!ELEMENT step (#PCDATA)>
+<!ELEMENT comment (#PCDATA)>
+<!ELEMENT nutrition EMPTY>
+<!ATTLIST nutrition protein CDATA #REQUIRED
+                    carbohydrates CDATA #REQUIRED
+                    fat CDATA #REQUIRED
+                    calories CDATA #REQUIRED
+                    alcohol CDATA #IMPLIED>
diff --git a/xml/src/test/resources/recipt.xml b/xml/src/test/resources/recipt.xml
new file mode 100644
index 0000000..d7cf0fb
--- /dev/null
+++ b/xml/src/test/resources/recipt.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE collection SYSTEM "./recipt.dtd">
+<!--comment1 -->
+<collection>
+  <description>
+     Some recipes used for the XML tutorial.
+  </description>
+  <recipe>
+    <title>Beef Parmesan<![CDATA[<title> with Garlic Angel Hair Pasta</title>]]></title>
+    <ingredient name="beef cube steak" amount="1.5" unit="pound"/>
+    <preparation>
+      <step>
+        Preheat oven to 350 degrees F (175 degrees C).
+      </step>
+    </preparation>
+    <comment>
+      Make the meat ahead of time, and refrigerate over night, the acid in the
+      tomato sauce will tenderize the meat even more. If you do this, save the
+      mozzarella till the last minute.
+    </comment>
+    <nutrition calories="1167" fat="23" carbohydrates="45" protein="32"/>
+  </recipe>
+</collection>
+<!--comment2 -->
diff --git a/xml/src/test/resources/reciptWrong.xml b/xml/src/test/resources/reciptWrong.xml
new file mode 100644
index 0000000..ce32d09
--- /dev/null
+++ b/xml/src/test/resources/reciptWrong.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE collection SYSTEM "./recipt.dtd">
+<!--comment1 -->
+<collection>
+  <recipe>
+    <title>Beef Parmesan<![CDATA[<title> with Garlic Angel Hair Pasta</title>]]></title>
+    <ingredient name="beef cube steak" amount="1.5" unit="pound"/>
+    <preparation>
+      <step>
+        Preheat oven to 350 degrees F (175 degrees C).
+      </step>
+    </preparation>
+    <comment>
+      Make the meat ahead of time, and refrigerate over night, the acid in the
+      tomato sauce will tenderize the meat even more. If you do this, save the
+      mozzarella till the last minute.
+    </comment>
+    <nutrition calories="1167" fat="23" carbohydrates="45" protein="32"/>
+  </recipe>
+</collection>
+<!--comment2 -->
diff --git a/xml/src/test/resources/simple.xml b/xml/src/test/resources/simple.xml
new file mode 100644
index 0000000..de39181
--- /dev/null
+++ b/xml/src/test/resources/simple.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!-- Edited with XML Spy v2007 (http://www.altova.com) -->
+<breakfast_menu>
+	<food>
+		<name>Belgian Waffles</name>
+		<price>$5.95</price>
+		<description>two of our famous Belgian Waffles with plenty of real maple syrup</description>
+		<calories>650</calories>
+	</food>
+	<food>
+		<name>Strawberry Belgian Waffles</name>
+		<price>$7.95</price>
+		<description>light Belgian waffles covered with strawberries and whipped cream</description>
+		<calories>900</calories>
+	</food>
+	<food>
+		<name>Berry-Berry Belgian Waffles</name>
+		<price>$8.95</price>
+		<description>light Belgian waffles covered with an assortment of fresh berries and whipped cream</description>
+		<calories>900</calories>
+	</food>
+	<food>
+		<name>French Toast</name>
+		<price>$4.50</price>
+		<description>thick slices made from our homemade sourdough bread</description>
+		<calories>600</calories>
+	</food>
+	<food>
+		<name>Homestyle Breakfast</name>
+		<price>$6.95</price>
+		<description>two eggs, bacon or sausage, toast, and our ever-popular hash browns</description>
+		<calories>950</calories>
+	</food>
+</breakfast_menu>
diff --git a/xml/src/test/resources/simple_ns.dtd b/xml/src/test/resources/simple_ns.dtd
new file mode 100644
index 0000000..7643773
--- /dev/null
+++ b/xml/src/test/resources/simple_ns.dtd
@@ -0,0 +1,45 @@
+<!ELEMENT staff (employee+,emp:employee,employee) >
+<!ELEMENT employee (employeeId,name,position,salary,gender,address) >
+<!ATTLIST employee xmlns CDATA #IMPLIED>
+<!ATTLIST employee xmlns:dmstc CDATA #IMPLIED>
+<!ATTLIST employee xmlns:emp2 CDATA #IMPLIED>
+
+<!ELEMENT employeeId (#PCDATA) >
+
+<!ELEMENT name (#PCDATA) >
+
+<!ELEMENT position (#PCDATA) >
+
+<!ELEMENT salary (#PCDATA) >
+
+<!ELEMENT entElement1 (#PCDATA) >
+<!ELEMENT gender (#PCDATA | entElement1)* >
+<!ATTLIST entElement1 xmlns:local1 CDATA #IMPLIED >
+
+<!ELEMENT address (#PCDATA) >
+<!ATTLIST address dmstc:domestic CDATA #IMPLIED>
+<!ATTLIST address street CDATA #IMPLIED>
+<!ATTLIST address domestic CDATA #IMPLIED>
+<!ATTLIST address xmlns CDATA #IMPLIED>
+
+<!ELEMENT emp:employee (emp:employeeId,nm:name,emp:position,emp:salary,emp:gender,emp:address) >
+<!ATTLIST emp:employee xmlns:emp CDATA #IMPLIED>
+<!ATTLIST emp:employee xmlns:nm CDATA #IMPLIED>
+<!ATTLIST emp:employee defaultAttr CDATA 'defaultVal'>
+
+<!ELEMENT emp:employeeId (#PCDATA) >
+
+<!ELEMENT nm:name (#PCDATA) >
+
+<!ELEMENT emp:position (#PCDATA) >
+
+<!ELEMENT emp:salary (#PCDATA) >
+
+<!ELEMENT emp:gender (#PCDATA) >
+
+<!ELEMENT emp:address (#PCDATA) >
+<!ATTLIST emp:address emp:domestic CDATA #IMPLIED>
+<!ATTLIST emp:address street CDATA #IMPLIED>
+<!ATTLIST emp:address emp:zone ID #IMPLIED>
+<!ATTLIST emp:address emp:district CDATA 'DISTRICT'>
+<!ATTLIST emp:address emp:local1 CDATA 'FALSE'>
diff --git a/xml/src/test/resources/simple_ns.xml b/xml/src/test/resources/simple_ns.xml
new file mode 100644
index 0000000..a5dc4a3
--- /dev/null
+++ b/xml/src/test/resources/simple_ns.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0"?><?TEST-STYLE PIDATA?>
+<!DOCTYPE staff PUBLIC "STAFF" "simple_ns.dtd" 
+[
+   <!ENTITY ent1 "es">
+   <!ENTITY ent2 "1900 Dallas Road">
+   <!ENTITY ent3 "Texas">
+   <!ENTITY ent4 "<entElement1 xmlns:local1='www.xyz.com'>Element data</entElement1><?PItarget PIdata?>">
+   <!ENTITY ent5 PUBLIC "entityURI" "entityFile" NDATA notation1>
+   <!ENTITY ent6 PUBLIC "uri" "file" NDATA notation2>
+   <!ENTITY ent1 "This entity should be discarded">
+   <!NOTATION notation1 PUBLIC "notation1File">
+   <!NOTATION notation2 SYSTEM "notation2File">
+]>
+<!-- This is comment number 1.-->
+<staff>
+ <employee xmlns="http://www.nist.gov" xmlns:dmstc="http://www.usa.com">
+  <employeeId>EMP0001</employeeId>
+  <name>Margaret Martin</name>
+  <position>Accountant</position>           
+  <salary>56,000</salary>
+  <gender>Female</gender>
+  <address dmstc:domestic="Yes">1230 North Ave. Dallas, Texas 98551</address>
+ </employee>
+ <employee xmlns:dmstc="http://www.usa.com">
+  <employeeId>EMP0002</employeeId>
+  <name>Martha Raynolds
+<![CDATA[This is a CDATASection with EntityReference number 2 &ent2;]]>
+<![CDATA[This is an adjacent CDATASection with a reference to a tab &tab;]]></name>
+  <position>Secretary</position>
+  <salary>35,000</salary>
+  <gender>Female</gender>
+  <address dmstc:domestic="Yes" street="Yes">&ent2; Dallas, &ent3;
+ 98554</address>
+ </employee>
+ <employee xmlns:dmstc="http://www.netzero.com">
+  <employeeId>EMP0003</employeeId>
+  <name>Roger
+ Jones</name>
+  <position>Department Manager</position>
+  <salary>100,000</salary>
+  <gender>&ent4;</gender>
+  <address dmstc:domestic="Yes" street="No">PO Box 27 Irving, texas 98553</address>
+ </employee>
+ <emp:employee xmlns:emp="http://www.nist.gov" xmlns:nm="http://www.altavista.com" >    <emp:employeeId>EMP0004</emp:employeeId>
+  <nm:name>Jeny Oconnor</nm:name>
+  <emp:position>Personnel Director</emp:position>
+  <emp:salary>95,000</emp:salary>
+  <emp:gender>Female</emp:gender>
+  <emp:address emp:domestic="Yes" street="Y&ent1;" emp:zone="CANADA" emp:local1="TRUE">27 South Road. Dallas, texas 98556</emp:address>
+ </emp:employee>
+ <employee xmlns:emp2="http://www.nist.gov">
+  <employeeId>EMP0005</employeeId>
+  <name>Robert Myers</name>
+  <position>Computer Specialist</position>
+  <salary>90,000</salary>
+  <gender>male</gender>
+  <address street="Yes" xmlns="http://www.nist.gov">1821 Nordic. Road, Irving Texas 98558</address>
+ </employee>
+ </staff>
diff --git a/xml/src/test/resources/staff.dtd b/xml/src/test/resources/staff.dtd
new file mode 100644
index 0000000..02a994d
--- /dev/null
+++ b/xml/src/test/resources/staff.dtd
@@ -0,0 +1,17 @@
+<!ELEMENT employeeId (#PCDATA)>
+<!ELEMENT name (#PCDATA)>
+<!ELEMENT position (#PCDATA)>
+<!ELEMENT salary (#PCDATA)>
+<!ELEMENT address (#PCDATA)>
+<!ELEMENT entElement ( #PCDATA ) >
+<!ELEMENT gender ( #PCDATA | entElement )* >
+<!ELEMENT employee (employeeId, name, position, salary, gender, address) >
+<!ELEMENT staff (employee)+>
+<!ATTLIST entElement 
+          attr1 CDATA "Attr">
+<!ATTLIST address
+          domestic CDATA #IMPLIED 
+          street CDATA "Yes">
+<!ATTLIST entElement 
+          domestic CDATA "MALE" >
+
diff --git a/xml/src/test/resources/staff.xml b/xml/src/test/resources/staff.xml
new file mode 100644
index 0000000..f89c510
--- /dev/null
+++ b/xml/src/test/resources/staff.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0"?><?TEST-STYLE PIDATA?>
+<!DOCTYPE staff SYSTEM "staff.dtd" [
+   <!ENTITY ent1 "es">
+   <!ENTITY ent2 "1900 Dallas Road">
+   <!ENTITY ent3 "Texas">
+   <!ENTITY ent4 "<entElement domestic='Yes'>Element data</entElement><?PItarget PIdata?>">
+   <!ENTITY ent5 PUBLIC "entityURI" "entityFile" NDATA notation1>
+   <!ENTITY ent1 "This entity should be discarded">
+   <!NOTATION notation1 PUBLIC "notation1File">
+   <!NOTATION notation2 SYSTEM "notation2File">
+]>
+<!-- This is comment number 1.-->
+<staff>
+ <employee>
+  <employeeId>EMP0001</employeeId>
+  <name>Margaret Martin</name>
+  <position>Accountant</position>           
+  <salary>56,000</salary>
+  <gender>Female</gender>
+  <address domestic="Yes">1230 North Ave. Dallas, Texas 98551</address>
+ </employee>
+ <employee>
+  <employeeId>EMP0002</employeeId>
+  <name>Martha Raynolds<![CDATA[This is a CDATASection with EntityReference number 2 &ent2;]]>
+<![CDATA[This is an adjacent CDATASection with a reference to a tab &tab;]]></name>
+  <position>Secretary</position>
+  <salary>35,000</salary>
+  <gender>Female</gender>
+  <address domestic="Yes" street="Yes">&ent2; Dallas, &ent3;
+ 98554</address>
+ </employee>
+ <employee>
+  <employeeId>EMP0003</employeeId>
+  <name>Roger
+ Jones</name>
+  <position>Department Manager</position>
+  <salary>100,000</salary>
+  <gender>&ent4;</gender>
+  <address domestic="Yes" street="No">PO Box 27 Irving, texas 98553</address>
+ </employee>
+ <employee>
+  <employeeId>EMP0004</employeeId>
+  <name>Jeny Oconnor</name>
+  <position>Personnel Director</position>
+  <salary>95,000</salary>
+  <gender>Female</gender>
+  <address domestic="Yes" street="Y&ent1;">27 South Road. Dallas, Texas 98556</address>
+ </employee>
+ <employee>
+  <employeeId>EMP0005</employeeId>
+  <name>Robert Myers</name>
+  <position>Computer Specialist</position>
+  <salary>90,000</salary>
+  <gender>male</gender>
+  <address street="Yes">1821 Nordic. Road, Irving Texas 98558</address>
+ </employee>
+ </staff>
diff --git a/xml/src/test/resources/staff2.dtd b/xml/src/test/resources/staff2.dtd
new file mode 100644
index 0000000..0bac8f2
--- /dev/null
+++ b/xml/src/test/resources/staff2.dtd
@@ -0,0 +1,24 @@
+<!ELEMENT employeeId (#PCDATA)>
+<!ELEMENT name (#PCDATA)>
+<!ELEMENT position (#PCDATA)>
+<!ELEMENT salary (#PCDATA)>
+<!ELEMENT address (#PCDATA)>
+<!ELEMENT gender ( #PCDATA)>
+<!ELEMENT employee (employeeId, name, position, salary, gender, address) >
+<!ATTLIST employee xmlns CDATA #IMPLIED>
+<!ELEMENT staff (employee)+>
+<!ELEMENT svg (rect, script, employee+)>
+<!ATTLIST svg 
+      xmlns CDATA #FIXED "http://www.w3.org/2000/svg"
+      name CDATA #IMPLIED>
+<!ELEMENT rect EMPTY>
+<!ATTLIST rect 
+      x CDATA #REQUIRED
+      y CDATA #REQUIRED
+      width CDATA #REQUIRED
+      height CDATA #REQUIRED>
+<!ELEMENT script (#PCDATA)>
+<!ATTLIST script type CDATA #IMPLIED>      
+<!ENTITY svgunit SYSTEM "svgunit.js">
+<!ENTITY svgtest SYSTEM "internalSubset01.js">
+
diff --git a/xml/src/test/resources/staff2.xml b/xml/src/test/resources/staff2.xml
new file mode 100644
index 0000000..d3d9a13
--- /dev/null
+++ b/xml/src/test/resources/staff2.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0"?><?TEST-STYLE PIDATA?>
+<!DOCTYPE staff SYSTEM "staff2.dtd" []>
+<!-- This is comment number 1.-->
+<staff>
+ <employee>
+  <employeeId>EMP0001</employeeId>
+  <name>Margaret Martin</name>
+  <position>Accountant</position>           
+  <salary>56,000</salary>
+  <gender>Female</gender>
+  <address>1230 North Ave. Dallas, Texas 98551</address>
+ </employee>
+ </staff>
diff --git a/xml/src/test/resources/staffEntRes.xml b/xml/src/test/resources/staffEntRes.xml
new file mode 100644
index 0000000..0c24c83
--- /dev/null
+++ b/xml/src/test/resources/staffEntRes.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0"?><?TEST-STYLE PIDATA?>
+<!DOCTYPE staff
+[
+   <!ENTITY ent1 "es">
+   <!ENTITY ent2 "1900 Dallas Road">
+   <!ENTITY ent3 "Texas">
+   <!ENTITY chap1 SYSTEM "chap1.xml">
+   <!ENTITY ent4 "<entElement1 xmlns:local1='www.xyz.com'>Element data</entElement1><?PItarget PIdata?>">
+   <!ENTITY ent5 PUBLIC "entityURI" "entityFile" NDATA notation1>
+   <!ENTITY ent6 PUBLIC "uri" "file" NDATA notation2>
+   <!ENTITY ent1 "This entity should be discarded">
+   <!NOTATION notation1 PUBLIC "notation1File">
+   <!NOTATION notation2 SYSTEM "notation2File">
+]>
+<!-- This is comment number 1.-->
+<staff>
+ <employee xmlns="http://www.nist.gov" xmlns:dmstc="http://www.usa.com">
+  <employeeId>EMP0001</employeeId>
+  <name>Margaret Martin</name>
+  <position>Accountant</position>           
+  <salary>56,000</salary>
+  <gender>Female</gender>
+  <address dmstc:domestic="Yes">1230 North Ave. Dallas, Texas 98551</address>
+ </employee>
+ <employee xmlns:dmstc="http://www.usa.com">
+  <employeeId>EMP0002</employeeId>
+  <name>Martha Raynolds &chap1; 
+<![CDATA[This is a CDATASection with EntityReference number 2 &ent2;]]>
+<![CDATA[This is an adjacent CDATASection with a reference to a tab &tab;]]></name>
+  <position>Secretary</position>
+  <salary>35,000</salary>
+  <gender>Female</gender>
+  <address dmstc:domestic="Yes" street="Yes">&ent2; Dallas, &ent3;
+ 98554</address>
+ </employee>
+ <employee xmlns:dmstc="http://www.netzero.com">
+  <employeeId>EMP0003</employeeId>
+  <name>Roger
+ Jones</name>
+  <position>Department Manager</position>
+  <salary>100,000</salary>
+  <gender>&ent4;</gender>
+  <address dmstc:domestic="Yes" street="No">PO Box 27 Irving, texas 98553</address>
+ </employee>
+ <emp:employee xmlns:emp="http://www.nist.gov" xmlns:nm="http://www.altavista.com" >    <emp:employeeId>EMP0004</emp:employeeId>
+  <nm:name>Jeny Oconnor</nm:name>
+  <emp:position>Personnel Director</emp:position>
+  <emp:salary>95,000</emp:salary>
+  <emp:gender>Female</emp:gender>
+  <emp:address emp:domestic="Yes" street="Y&ent1;" emp:zone="CANADA" emp:local1="TRUE">27 South Road. Dallas, texas 98556</emp:address>
+ </emp:employee>
+ <employee xmlns:emp2="http://www.nist.gov">
+  <employeeId>EMP0005</employeeId>
+  <name>Robert Myers</name>
+  <position>Computer Specialist</position>
+  <salary>90,000</salary>
+  <gender>male</gender>
+  <address street="Yes" xmlns="http://www.nist.gov">1821 Nordic. Road, Irving Texas 98558</address>
+ </employee>
+ </staff>
diff --git a/xml/src/test/resources/staffNS.dtd b/xml/src/test/resources/staffNS.dtd
new file mode 100644
index 0000000..7643773
--- /dev/null
+++ b/xml/src/test/resources/staffNS.dtd
@@ -0,0 +1,45 @@
+<!ELEMENT staff (employee+,emp:employee,employee) >
+<!ELEMENT employee (employeeId,name,position,salary,gender,address) >
+<!ATTLIST employee xmlns CDATA #IMPLIED>
+<!ATTLIST employee xmlns:dmstc CDATA #IMPLIED>
+<!ATTLIST employee xmlns:emp2 CDATA #IMPLIED>
+
+<!ELEMENT employeeId (#PCDATA) >
+
+<!ELEMENT name (#PCDATA) >
+
+<!ELEMENT position (#PCDATA) >
+
+<!ELEMENT salary (#PCDATA) >
+
+<!ELEMENT entElement1 (#PCDATA) >
+<!ELEMENT gender (#PCDATA | entElement1)* >
+<!ATTLIST entElement1 xmlns:local1 CDATA #IMPLIED >
+
+<!ELEMENT address (#PCDATA) >
+<!ATTLIST address dmstc:domestic CDATA #IMPLIED>
+<!ATTLIST address street CDATA #IMPLIED>
+<!ATTLIST address domestic CDATA #IMPLIED>
+<!ATTLIST address xmlns CDATA #IMPLIED>
+
+<!ELEMENT emp:employee (emp:employeeId,nm:name,emp:position,emp:salary,emp:gender,emp:address) >
+<!ATTLIST emp:employee xmlns:emp CDATA #IMPLIED>
+<!ATTLIST emp:employee xmlns:nm CDATA #IMPLIED>
+<!ATTLIST emp:employee defaultAttr CDATA 'defaultVal'>
+
+<!ELEMENT emp:employeeId (#PCDATA) >
+
+<!ELEMENT nm:name (#PCDATA) >
+
+<!ELEMENT emp:position (#PCDATA) >
+
+<!ELEMENT emp:salary (#PCDATA) >
+
+<!ELEMENT emp:gender (#PCDATA) >
+
+<!ELEMENT emp:address (#PCDATA) >
+<!ATTLIST emp:address emp:domestic CDATA #IMPLIED>
+<!ATTLIST emp:address street CDATA #IMPLIED>
+<!ATTLIST emp:address emp:zone ID #IMPLIED>
+<!ATTLIST emp:address emp:district CDATA 'DISTRICT'>
+<!ATTLIST emp:address emp:local1 CDATA 'FALSE'>
diff --git a/xml/src/test/resources/staffNS.xml b/xml/src/test/resources/staffNS.xml
new file mode 100644
index 0000000..1cb1459
--- /dev/null
+++ b/xml/src/test/resources/staffNS.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0"?><?TEST-STYLE PIDATA?>
+<!DOCTYPE staff PUBLIC "STAFF" "staffNS.dtd" 
+[
+   <!ENTITY ent1 "es">
+   <!ENTITY ent2 "1900 Dallas Road">
+   <!ENTITY ent3 "Texas">
+   <!ENTITY ent4 "<entElement1 xmlns:local1='www.xyz.com'>Element data</entElement1><?PItarget PIdata?>">
+   <!ENTITY ent5 PUBLIC "entityURI" "entityFile" NDATA notation1>
+   <!ENTITY ent6 PUBLIC "uri" "file" NDATA notation2>
+   <!ENTITY ent1 "This entity should be discarded">
+   <!NOTATION notation1 PUBLIC "notation1File">
+   <!NOTATION notation2 SYSTEM "notation2File">
+]>
+<!-- This is comment number 1.-->
+<staff>
+ <employee xmlns="http://www.nist.gov" xmlns:dmstc="http://www.usa.com">
+  <employeeId>EMP0001</employeeId>
+  <name>Margaret Martin</name>
+  <position>Accountant</position>           
+  <salary>56,000</salary>
+  <gender>Female</gender>
+  <address dmstc:domestic="Yes">1230 North Ave. Dallas, Texas 98551</address>
+ </employee>
+ <employee xmlns:dmstc="http://www.usa.com">
+  <employeeId>EMP0002</employeeId>
+  <name>Martha Raynolds
+<![CDATA[This is a CDATASection with EntityReference number 2 &ent2;]]>
+<![CDATA[This is an adjacent CDATASection with a reference to a tab &tab;]]></name>
+  <position>Secretary</position>
+  <salary>35,000</salary>
+  <gender>Female</gender>
+  <address dmstc:domestic="Yes" street="Yes">&ent2; Dallas, &ent3;
+ 98554</address>
+ </employee>
+ <employee xmlns:dmstc="http://www.netzero.com">
+  <employeeId>EMP0003</employeeId>
+  <name>Roger
+ Jones</name>
+  <position>Department Manager</position>
+  <salary>100,000</salary>
+  <gender>&ent4;</gender>
+  <address dmstc:domestic="Yes" street="No">PO Box 27 Irving, texas 98553</address>
+ </employee>
+ <emp:employee xmlns:emp="http://www.nist.gov" xmlns:nm="http://www.altavista.com" >    <emp:employeeId>EMP0004</emp:employeeId>
+  <nm:name>Jeny Oconnor</nm:name>
+  <emp:position>Personnel Director</emp:position>
+  <emp:salary>95,000</emp:salary>
+  <emp:gender>Female</emp:gender>
+  <emp:address emp:domestic="Yes" street="Y&ent1;" emp:zone="CANADA" emp:local1="TRUE">27 South Road. Dallas, texas 98556</emp:address>
+ </emp:employee>
+ <employee xmlns:emp2="http://www.nist.gov">
+  <employeeId>EMP0005</employeeId>
+  <name>Robert Myers</name>
+  <position>Computer Specialist</position>
+  <salary>90,000</salary>
+  <gender>male</gender>
+  <address street="Yes" xmlns="http://www.nist.gov">1821 Nordic. Road, Irving Texas 98558</address>
+ </employee>
+ </staff>
diff --git a/xml/src/test/resources/systemid.xml b/xml/src/test/resources/systemid.xml
new file mode 100644
index 0000000..d7cf0fb
--- /dev/null
+++ b/xml/src/test/resources/systemid.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE collection SYSTEM "./recipt.dtd">
+<!--comment1 -->
+<collection>
+  <description>
+     Some recipes used for the XML tutorial.
+  </description>
+  <recipe>
+    <title>Beef Parmesan<![CDATA[<title> with Garlic Angel Hair Pasta</title>]]></title>
+    <ingredient name="beef cube steak" amount="1.5" unit="pound"/>
+    <preparation>
+      <step>
+        Preheat oven to 350 degrees F (175 degrees C).
+      </step>
+    </preparation>
+    <comment>
+      Make the meat ahead of time, and refrigerate over night, the acid in the
+      tomato sauce will tenderize the meat even more. If you do this, save the
+      mozzarella till the last minute.
+    </comment>
+    <nutrition calories="1167" fat="23" carbohydrates="45" protein="32"/>
+  </recipe>
+</collection>
+<!--comment2 -->
diff --git a/xml/src/test/resources/systemid/recipt.dtd b/xml/src/test/resources/systemid/recipt.dtd
new file mode 100644
index 0000000..370112c
--- /dev/null
+++ b/xml/src/test/resources/systemid/recipt.dtd
@@ -0,0 +1,17 @@
+<!ELEMENT collection (description,recipe+)>
+<!ELEMENT description ANY>
+<!ELEMENT recipe (title,ingredient*,preparation,comment?,nutrition)>
+<!ELEMENT title (#PCDATA)>
+<!ELEMENT ingredient (ingredient*,preparation)?>
+<!ATTLIST ingredient name CDATA #REQUIRED
+                     amount CDATA #IMPLIED
+                     unit CDATA #IMPLIED>
+<!ELEMENT preparation (step*)>
+<!ELEMENT step (#PCDATA)>
+<!ELEMENT comment (#PCDATA)>
+<!ELEMENT nutrition EMPTY>
+<!ATTLIST nutrition protein CDATA #REQUIRED
+                    carbohydrates CDATA #REQUIRED
+                    fat CDATA #REQUIRED
+                    calories CDATA #REQUIRED
+                    alcohol CDATA #IMPLIED>
diff --git a/xml/src/test/resources/systemid/staff.dtd b/xml/src/test/resources/systemid/staff.dtd
new file mode 100644
index 0000000..02a994d
--- /dev/null
+++ b/xml/src/test/resources/systemid/staff.dtd
@@ -0,0 +1,17 @@
+<!ELEMENT employeeId (#PCDATA)>
+<!ELEMENT name (#PCDATA)>
+<!ELEMENT position (#PCDATA)>
+<!ELEMENT salary (#PCDATA)>
+<!ELEMENT address (#PCDATA)>
+<!ELEMENT entElement ( #PCDATA ) >
+<!ELEMENT gender ( #PCDATA | entElement )* >
+<!ELEMENT employee (employeeId, name, position, salary, gender, address) >
+<!ELEMENT staff (employee)+>
+<!ATTLIST entElement 
+          attr1 CDATA "Attr">
+<!ATTLIST address
+          domestic CDATA #IMPLIED 
+          street CDATA "Yes">
+<!ATTLIST entElement 
+          domestic CDATA "MALE" >
+
diff --git a/xml/src/test/resources/wf/staff.dtd b/xml/src/test/resources/wf/staff.dtd
new file mode 100644
index 0000000..02a994d
--- /dev/null
+++ b/xml/src/test/resources/wf/staff.dtd
@@ -0,0 +1,17 @@
+<!ELEMENT employeeId (#PCDATA)>
+<!ELEMENT name (#PCDATA)>
+<!ELEMENT position (#PCDATA)>
+<!ELEMENT salary (#PCDATA)>
+<!ELEMENT address (#PCDATA)>
+<!ELEMENT entElement ( #PCDATA ) >
+<!ELEMENT gender ( #PCDATA | entElement )* >
+<!ELEMENT employee (employeeId, name, position, salary, gender, address) >
+<!ELEMENT staff (employee)+>
+<!ATTLIST entElement 
+          attr1 CDATA "Attr">
+<!ATTLIST address
+          domestic CDATA #IMPLIED 
+          street CDATA "Yes">
+<!ATTLIST entElement 
+          domestic CDATA "MALE" >
+
diff --git a/xml/src/test/resources/wf/staff.xml b/xml/src/test/resources/wf/staff.xml
new file mode 100644
index 0000000..f89c510
--- /dev/null
+++ b/xml/src/test/resources/wf/staff.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0"?><?TEST-STYLE PIDATA?>
+<!DOCTYPE staff SYSTEM "staff.dtd" [
+   <!ENTITY ent1 "es">
+   <!ENTITY ent2 "1900 Dallas Road">
+   <!ENTITY ent3 "Texas">
+   <!ENTITY ent4 "<entElement domestic='Yes'>Element data</entElement><?PItarget PIdata?>">
+   <!ENTITY ent5 PUBLIC "entityURI" "entityFile" NDATA notation1>
+   <!ENTITY ent1 "This entity should be discarded">
+   <!NOTATION notation1 PUBLIC "notation1File">
+   <!NOTATION notation2 SYSTEM "notation2File">
+]>
+<!-- This is comment number 1.-->
+<staff>
+ <employee>
+  <employeeId>EMP0001</employeeId>
+  <name>Margaret Martin</name>
+  <position>Accountant</position>           
+  <salary>56,000</salary>
+  <gender>Female</gender>
+  <address domestic="Yes">1230 North Ave. Dallas, Texas 98551</address>
+ </employee>
+ <employee>
+  <employeeId>EMP0002</employeeId>
+  <name>Martha Raynolds<![CDATA[This is a CDATASection with EntityReference number 2 &ent2;]]>
+<![CDATA[This is an adjacent CDATASection with a reference to a tab &tab;]]></name>
+  <position>Secretary</position>
+  <salary>35,000</salary>
+  <gender>Female</gender>
+  <address domestic="Yes" street="Yes">&ent2; Dallas, &ent3;
+ 98554</address>
+ </employee>
+ <employee>
+  <employeeId>EMP0003</employeeId>
+  <name>Roger
+ Jones</name>
+  <position>Department Manager</position>
+  <salary>100,000</salary>
+  <gender>&ent4;</gender>
+  <address domestic="Yes" street="No">PO Box 27 Irving, texas 98553</address>
+ </employee>
+ <employee>
+  <employeeId>EMP0004</employeeId>
+  <name>Jeny Oconnor</name>
+  <position>Personnel Director</position>
+  <salary>95,000</salary>
+  <gender>Female</gender>
+  <address domestic="Yes" street="Y&ent1;">27 South Road. Dallas, Texas 98556</address>
+ </employee>
+ <employee>
+  <employeeId>EMP0005</employeeId>
+  <name>Robert Myers</name>
+  <position>Computer Specialist</position>
+  <salary>90,000</salary>
+  <gender>male</gender>
+  <address street="Yes">1821 Nordic. Road, Irving Texas 98558</address>
+ </employee>
+ </staff>
diff --git a/xml/src/test/resources/wrong.xml b/xml/src/test/resources/wrong.xml
new file mode 100644
index 0000000..9d4b41d
--- /dev/null
+++ b/xml/src/test/resources/wrong.xml
@@ -0,0 +1 @@
+<wrong1>wrong</wrong2>
\ No newline at end of file
diff --git a/xml/src/test/resources/xhtml1-strict.dtd b/xml/src/test/resources/xhtml1-strict.dtd
new file mode 100644
index 0000000..60bbaf7
--- /dev/null
+++ b/xml/src/test/resources/xhtml1-strict.dtd
@@ -0,0 +1,65 @@
+<!--
+
+Copyright (c) 2001-2004 World Wide Web Consortium, 
+(Massachusetts Institute of Technology, Institut National de
+Recherche en Informatique et en Automatique, Keio University).  All 
+Rights Reserved.  This program is distributed under the W3C's Software
+Intellectual Property License.  This program is distributed in the 
+hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+PURPOSE.  
+
+See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+-->
+
+<!--
+
+This is a radically simplified DTD for use in the DOM Test Suites
+due to a XML non-conformance of one implementation in processing
+parameter entities.  When that non-conformance is resolved,
+this DTD can be replaced by the normal DTD for XHTML.
+
+-->
+
+
+<!ELEMENT html (head, body)>
+<!ATTLIST html xmlns CDATA #IMPLIED>
+<!ELEMENT head (meta,title,script*)>
+<!ELEMENT meta EMPTY>
+<!ATTLIST meta 
+	http-equiv CDATA #IMPLIED
+	content CDATA #IMPLIED>
+<!ELEMENT title (#PCDATA)>
+<!ELEMENT body (p*)>
+<!ATTLIST body onload CDATA #IMPLIED>
+<!ELEMENT p (#PCDATA|em|strong|code|sup|var|acronym|abbr)*>
+<!ATTLIST p 
+  xmlns:dmstc CDATA #IMPLIED
+  xmlns:nm CDATA #IMPLIED
+  xmlns:emp2 CDATA #IMPLIED
+  id ID #IMPLIED  
+>
+<!ELEMENT em (#PCDATA)>
+<!ELEMENT span (#PCDATA)>
+<!ELEMENT strong (#PCDATA)>
+<!ELEMENT code (#PCDATA)>
+<!ELEMENT sup (#PCDATA)>
+<!ELEMENT var (#PCDATA|span)*>
+<!ELEMENT acronym (#PCDATA)>
+<!ATTLIST acronym
+    title CDATA #IMPLIED
+    class CDATA #IMPLIED
+    id ID #IMPLIED
+>
+<!ELEMENT abbr (#PCDATA)>
+<!ATTLIST abbr
+    title CDATA #IMPLIED
+    class CDATA #IMPLIED
+    id ID #IMPLIED
+>
+<!ELEMENT script (#PCDATA)>
+<!ATTLIST script 
+   type CDATA #IMPLIED
+   src CDATA #IMPLIED
+   charset CDATA #IMPLIED>