summaryrefslogtreecommitdiffstats
path: root/xml/src/main/java/org
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
commitfdb2704414a9ed92394ada0d1395e4db86889465 (patch)
tree9b591a4a50054274a197f02b3ccb51313681879f /xml/src/main/java/org
downloadlibcore-fdb2704414a9ed92394ada0d1395e4db86889465.zip
libcore-fdb2704414a9ed92394ada0d1395e4db86889465.tar.gz
libcore-fdb2704414a9ed92394ada0d1395e4db86889465.tar.bz2
Initial Contribution
Diffstat (limited to 'xml/src/main/java/org')
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/ExpatAttributes.java154
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/ExpatException.java28
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/ExpatParser.java794
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/ExpatPullParser.java964
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/ExpatReader.java335
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java177
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/dom/CDATASectionImpl.java49
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/dom/CharacterDataImpl.java93
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/dom/CommentImpl.java49
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/dom/DOMImplementationImpl.java78
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/dom/DocumentFragmentImpl.java50
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java298
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/dom/DocumentTypeImpl.java110
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/dom/ElementImpl.java446
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/dom/EntityImpl.java71
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/dom/EntityReferenceImpl.java52
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java221
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/dom/LeafNodeImpl.java70
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/dom/NamedNodeMapImpl.java176
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java191
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/dom/NodeListImpl.java63
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/dom/NotationImpl.java64
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/dom/ProcessingInstructionImpl.java74
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/dom/TextImpl.java70
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderFactoryImpl.java106
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java436
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/parsers/SAXParserFactoryImpl.java123
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/parsers/SAXParserImpl.java91
-rw-r--r--xml/src/main/java/org/kxml2/io/KXmlParser.java1438
-rw-r--r--xml/src/main/java/org/kxml2/io/KXmlSerializer.java562
-rw-r--r--xml/src/main/java/org/kxml2/kdom/Document.java129
-rw-r--r--xml/src/main/java/org/kxml2/kdom/Element.java336
-rw-r--r--xml/src/main/java/org/kxml2/kdom/Node.java366
-rw-r--r--xml/src/main/java/org/kxml2/wap/Wbxml.java49
-rw-r--r--xml/src/main/java/org/kxml2/wap/WbxmlParser.java1050
-rw-r--r--xml/src/main/java/org/kxml2/wap/WbxmlSerializer.java418
-rw-r--r--xml/src/main/java/org/kxml2/wap/syncml/SyncML.java192
-rw-r--r--xml/src/main/java/org/kxml2/wap/wml/Wml.java233
-rw-r--r--xml/src/main/java/org/kxml2/wap/wv/WV.java593
-rw-r--r--xml/src/main/java/org/w3c/dom/Attr.java134
-rw-r--r--xml/src/main/java/org/w3c/dom/CDATASection.java48
-rw-r--r--xml/src/main/java/org/w3c/dom/CharacterData.java171
-rw-r--r--xml/src/main/java/org/w3c/dom/Comment.java24
-rw-r--r--xml/src/main/java/org/w3c/dom/DOMException.java130
-rw-r--r--xml/src/main/java/org/w3c/dom/DOMImplementation.java105
-rw-r--r--xml/src/main/java/org/w3c/dom/Document.java382
-rw-r--r--xml/src/main/java/org/w3c/dom/DocumentFragment.java52
-rw-r--r--xml/src/main/java/org/w3c/dom/DocumentType.java99
-rw-r--r--xml/src/main/java/org/w3c/dom/Element.java314
-rw-r--r--xml/src/main/java/org/w3c/dom/Entity.java82
-rw-r--r--xml/src/main/java/org/w3c/dom/EntityReference.java39
-rw-r--r--xml/src/main/java/org/w3c/dom/NamedNodeMap.java168
-rw-r--r--xml/src/main/java/org/w3c/dom/Node.java454
-rw-r--r--xml/src/main/java/org/w3c/dom/NodeList.java53
-rw-r--r--xml/src/main/java/org/w3c/dom/Notation.java49
-rw-r--r--xml/src/main/java/org/w3c/dom/ProcessingInstruction.java58
-rw-r--r--xml/src/main/java/org/w3c/dom/Text.java61
-rw-r--r--xml/src/main/java/org/w3c/dom/package.html12
-rw-r--r--xml/src/main/java/org/xml/sax/AttributeList.java193
-rw-r--r--xml/src/main/java/org/xml/sax/Attributes.java257
-rw-r--r--xml/src/main/java/org/xml/sax/ContentHandler.java419
-rw-r--r--xml/src/main/java/org/xml/sax/DTDHandler.java117
-rw-r--r--xml/src/main/java/org/xml/sax/DocumentHandler.java232
-rw-r--r--xml/src/main/java/org/xml/sax/EntityResolver.java119
-rw-r--r--xml/src/main/java/org/xml/sax/ErrorHandler.java139
-rw-r--r--xml/src/main/java/org/xml/sax/HandlerBase.java369
-rw-r--r--xml/src/main/java/org/xml/sax/InputSource.java337
-rw-r--r--xml/src/main/java/org/xml/sax/Locator.java136
-rw-r--r--xml/src/main/java/org/xml/sax/Parser.java209
-rw-r--r--xml/src/main/java/org/xml/sax/SAXException.java153
-rw-r--r--xml/src/main/java/org/xml/sax/SAXNotRecognizedException.java53
-rw-r--r--xml/src/main/java/org/xml/sax/SAXNotSupportedException.java53
-rw-r--r--xml/src/main/java/org/xml/sax/SAXParseException.java269
-rw-r--r--xml/src/main/java/org/xml/sax/XMLFilter.java65
-rw-r--r--xml/src/main/java/org/xml/sax/XMLReader.java404
-rw-r--r--xml/src/main/java/org/xml/sax/ext/Attributes2.java132
-rw-r--r--xml/src/main/java/org/xml/sax/ext/Attributes2Impl.java313
-rw-r--r--xml/src/main/java/org/xml/sax/ext/DeclHandler.java146
-rw-r--r--xml/src/main/java/org/xml/sax/ext/DefaultHandler2.java185
-rw-r--r--xml/src/main/java/org/xml/sax/ext/EntityResolver2.java197
-rw-r--r--xml/src/main/java/org/xml/sax/ext/LexicalHandler.java212
-rw-r--r--xml/src/main/java/org/xml/sax/ext/Locator2.java75
-rw-r--r--xml/src/main/java/org/xml/sax/ext/Locator2Impl.java105
-rw-r--r--xml/src/main/java/org/xml/sax/ext/package.html48
-rw-r--r--xml/src/main/java/org/xml/sax/helpers/AttributeListImpl.java314
-rw-r--r--xml/src/main/java/org/xml/sax/helpers/AttributesImpl.java618
-rw-r--r--xml/src/main/java/org/xml/sax/helpers/DefaultHandler.java467
-rw-r--r--xml/src/main/java/org/xml/sax/helpers/LocatorImpl.java214
-rw-r--r--xml/src/main/java/org/xml/sax/helpers/NamespaceSupport.java840
-rw-r--r--xml/src/main/java/org/xml/sax/helpers/NewInstance.java79
-rw-r--r--xml/src/main/java/org/xml/sax/helpers/ParserAdapter.java1046
-rw-r--r--xml/src/main/java/org/xml/sax/helpers/ParserFactory.java133
-rw-r--r--xml/src/main/java/org/xml/sax/helpers/XMLFilterImpl.java715
-rw-r--r--xml/src/main/java/org/xml/sax/helpers/XMLReaderAdapter.java538
-rw-r--r--xml/src/main/java/org/xml/sax/helpers/XMLReaderFactory.java206
-rw-r--r--xml/src/main/java/org/xml/sax/helpers/package.html13
-rw-r--r--xml/src/main/java/org/xml/sax/package.html299
-rw-r--r--xml/src/main/java/org/xmlpull/v1/XmlPullParser.java1116
-rw-r--r--xml/src/main/java/org/xmlpull/v1/XmlPullParserException.java76
-rw-r--r--xml/src/main/java/org/xmlpull/v1/XmlPullParserFactory.java349
-rw-r--r--xml/src/main/java/org/xmlpull/v1/XmlSerializer.java326
-rw-r--r--xml/src/main/java/org/xmlpull/v1/sax2/Driver.java469
102 files changed, 25989 insertions, 0 deletions
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..8125745
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/io/KXmlParser.java
@@ -0,0 +1,1438 @@
+/* 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 HashMap 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() {
+// srcBuf = new char[Runtime.getRuntime().freeMemory() >= 1048576 ? 8192 : 128];
+
+ // XXX: We don't have a Runtime class at this time.
+ srcBuf = new char[8192];
+ }
+
+ 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 HashMap();
+ 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..61d5111
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/kdom/Element.java
@@ -0,0 +1,336 @@
+/* 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 ArrayList attributes;
+ protected Node parent;
+ protected ArrayList 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.get(index)) [0];
+ }
+
+ public String getAttributeName (int index) {
+ return ((String []) attributes.get(index)) [1];
+ }
+
+
+ public String getAttributeValue (int index) {
+ return ((String []) attributes.get(index)) [2];
+ }
+
+
+ public String
+ getAttributeValue(String name)
+ {
+ return getAttributeValue(null, name);
+ }
+
+ 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.get(i)) [0];
+ }
+
+ public String getNamespaceUri (int i) {
+ return ((String []) prefixes.get(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 ArrayList();
+
+ if (namespace == null)
+ namespace = "";
+
+ for (int i = attributes.size()-1; i >=0; i--){
+ String[] attribut = (String[]) attributes.get(i);
+ if (attribut[0].equals(namespace) &&
+ attribut[1].equals(name)){
+
+ if (value == null) {
+ attributes.remove(i);
+ }
+ else {
+ attribut[2] = value;
+ }
+ return;
+ }
+ }
+
+ attributes.add(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 ArrayList();
+ prefixes.add(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..4855893
--- /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 ArrayList 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 ArrayList();
+ 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.add(index, child);
+ 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.get(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.remove(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.get(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..c3852eb
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/wap/WbxmlParser.java
@@ -0,0 +1,1050 @@
+/* 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,
+// 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 {
+
+ 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();
+
+ int version;
+ int publicIdentifierId;
+ int charSet;
+
+ // StartTag current;
+ // ParseEvent next;
+
+ private String prefix;
+ private String namespace;
+ private String name;
+ private String text;
+ // private String encoding;
+ private Object wapExtensionData;
+ private int wapExtensionCode;
+
+ private int type;
+ private int codePage;
+
+ private boolean degenerated;
+ private boolean isWhitespace;
+ private String encoding = null;
+
+ public boolean getFeature(String feature) {
+ if (XmlPullParser
+ .FEATURE_PROCESS_NAMESPACES
+ .equals(feature))
+ return processNsp;
+ else
+ return false;
+ }
+
+ public String getInputEncoding() {
+ // should return someting depending on charSet here!!!!!
+ 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;
+ }
+
+ 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.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: " + 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 :
+ 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;
+ }
+
+
+
+ public void parseWapExtension(int id)
+ throws IOException, XmlPullParserException {
+
+ type = WAP_EXTENSION;
+ wapExtensionCode = id;
+
+ switch (id) {
+ case Wbxml.EXT_I_0 :
+ case Wbxml.EXT_I_1 :
+ case Wbxml.EXT_I_2 :
+ wapExtensionData = readStrI();
+ break;
+
+ case Wbxml.EXT_T_0 :
+ case Wbxml.EXT_T_1 :
+ case Wbxml.EXT_T_2 :
+ wapExtensionData = new Integer(readInt());
+ break;
+
+ case Wbxml.EXT_0 :
+ case Wbxml.EXT_1 :
+ case Wbxml.EXT_2 :
+ break;
+
+ case Wbxml.OPAQUE :
+ {
+ int len = readInt();
+ byte[] buf = new byte[len];
+
+ for (int i = 0;
+ i < len;
+ i++) // enhance with blockread!
+ buf[i] = (byte) readByte();
+
+ wapExtensionData = buf;
+ } // case OPAQUE
+ break;
+
+ default:
+ exception("illegal id: "+id);
+ } // 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 :
+
+ throw new RuntimeException("wap extension in attr not supported yet");
+
+ /*
+ ParseEvent e = parseWapExtension(id);
+ if (!(e.getType() != Xml.TEXT
+ && e.getType() != Xml.WHITESPACE))
+ throw new RuntimeException("parse WapExtension must return Text Event in order to work inside Attributes!");
+
+ value.append(e.getText());
+
+ //value.append (handleExtension (id)); // skip EXT in ATTR
+ //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;
+ }
+
+
+
+
+ String resolveId(String[] tab, int id) throws IOException {
+ int idx = (id & 0x07f) - 5;
+ if (idx == -1)
+ return readStrT();
+ if (idx < 0
+ || tab == null
+ || idx >= tab.length
+ || tab[idx] == null)
+ throw new IOException("id " + id + " undef.");
+
+ 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);
+ }
+
+}
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..e4447b0
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/wap/WbxmlSerializer.java
@@ -0,0 +1,418 @@
+/* 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: Bogdan Onoiu (Genderal character encoding abstraction and UTF-8 Support)
+
+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 = null;
+
+
+ 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
+ need 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);
+ }
+ else {
+ if(idx[0] != tagPage){
+ tagPage=idx[0];
+ buf.write(0);
+ 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));
+ }
+ else {
+ if(idx[0] != attrPage){
+ attrPage = idx[1];
+ buf.write(0);
+ buf.write(attrPage);
+ }
+ buf.write(idx[1]);
+ }
+ idx = (int[]) attrValueTable.get(attributes.elementAt(++i));
+ if (idx == null) {
+ buf.write(Wbxml.STR_I);
+ writeStrI(buf, (String) attributes.elementAt(i));
+ }
+ else {
+ if(idx[0] != attrPage){
+ attrPage = idx[1];
+ 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 {
+
+ if (encoding != null) throw new IllegalArgumentException ("encoding not yet supported for WBXML");
+
+ 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
+ String[] encodings = { "UTF-8", "ISO-8859-1" };
+ if (s == null || s.toUpperCase().equals(encodings[0])){
+ encoding = encodings[0];
+ out.write(106);
+ }else if (true == s.toUpperCase().equals(encodings[1])){
+ encoding = encodings[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);
+
+ buf.write(Wbxml.STR_I);
+ writeStrI(buf, new String(chars, start, len));
+
+ return this;
+ }
+
+ public XmlSerializer text(String text) throws IOException {
+
+ checkPending(false);
+
+ buf.write(Wbxml.STR_I);
+ writeStrI(buf, text);
+
+ return this;
+ }
+
+
+
+ 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;
+ }
+
+ /** currently ignored! */
+
+ public void writeLegacy(int type, String data) {
+ }
+
+ // ------------- 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]);
+ }
+
+ static void writeStrI(OutputStream out, String s) throws IOException {
+ for (int i = 0; i < s.length(); i++) {
+ out.write((byte) s.charAt(i));
+ }
+ out.write(0);
+ }
+
+ void writeStrT(String s) throws IOException {
+
+ Integer idx = (Integer) stringTable.get(s);
+
+ if (idx == null) {
+ idx = new Integer(stringTableBuf.size());
+ stringTable.put(s, idx);
+ writeStrI(stringTableBuf, s);
+ stringTableBuf.flush();
+ }
+
+ writeInt(buf, idx.intValue());
+ }
+
+ /**
+ * 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) {
+ // clear entries in tagTable!
+ if (page != 0)
+ return;
+
+ 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..81b9b93
--- /dev/null
+++ b/xml/src/main/java/org/xml/sax/ext/Attributes2Impl.java
@@ -0,0 +1,313 @@
+// 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 () { }
+
+
+ /**
+ * 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 ();
+
+ if (length < specified.length) {
+ 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);
+ }
+
+}