diff options
Diffstat (limited to 'sax/java/android/sax/RootElement.java')
-rw-r--r-- | sax/java/android/sax/RootElement.java | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/sax/java/android/sax/RootElement.java b/sax/java/android/sax/RootElement.java new file mode 100644 index 0000000..4fd6f6b --- /dev/null +++ b/sax/java/android/sax/RootElement.java @@ -0,0 +1,207 @@ +/* + * 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 android.sax; + +import org.xml.sax.helpers.DefaultHandler; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.ContentHandler; +import org.xml.sax.Locator; + +/** + * The root XML element. The entry point for this API. Not safe for concurrent + * use. + * + * <p>For example, passing this XML: + * + * <pre> + * <feed xmlns='http://www.w3.org/2005/Atom'> + * <entry> + * <id>bob</id> + * </entry> + * </feed> + * </pre> + * + * to this code: + * + * <pre> + * static final String ATOM_NAMESPACE = "http://www.w3.org/2005/Atom"; + * + * ... + * + * RootElement root = new RootElement(ATOM_NAMESPACE, "feed"); + * Element entry = root.getChild(ATOM_NAMESPACE, "entry"); + * entry.getChild(ATOM_NAMESPACE, "id").setEndTextElementListener( + * new EndTextElementListener() { + * public void end(String body) { + * System.out.println("Entry ID: " + body); + * } + * }); + * + * XMLReader reader = ...; + * reader.setContentHandler(root.getContentHandler()); + * reader.parse(...); + * </pre> + * + * would output: + * + * <pre> + * Entry ID: bob + * </pre> + */ +public class RootElement extends Element { + + final Handler handler = new Handler(); + + /** + * Constructs a new root element with the given name. + * + * @param uri the namespace + * @param localName the local name + */ + public RootElement(String uri, String localName) { + super(null, uri, localName, 0); + } + + /** + * Constructs a new root element with the given name. Uses an empty string + * as the namespace. + * + * @param localName the local name + */ + public RootElement(String localName) { + this("", localName); + } + + /** + * Gets the SAX {@code ContentHandler}. Pass this to your SAX parser. + */ + public ContentHandler getContentHandler() { + return this.handler; + } + + class Handler extends DefaultHandler { + + Locator locator; + int depth = -1; + Element current = null; + StringBuilder bodyBuilder = null; + + @Override + public void setDocumentLocator(Locator locator) { + this.locator = locator; + } + + @Override + public void startElement(String uri, String localName, String qName, + Attributes attributes) throws SAXException { + int depth = ++this.depth; + + if (depth == 0) { + // This is the root element. + startRoot(uri, localName, attributes); + return; + } + + // Prohibit mixed text and elements. + if (bodyBuilder != null) { + throw new BadXmlException("Encountered mixed content" + + " within text element named " + current + ".", + locator); + } + + // If we're one level below the current element. + if (depth == current.depth + 1) { + // Look for a child to push onto the stack. + Children children = current.children; + if (children != null) { + Element child = children.get(uri, localName); + if (child != null) { + start(child, attributes); + } + } + } + } + + void startRoot(String uri, String localName, Attributes attributes) + throws SAXException { + Element root = RootElement.this; + if (root.uri.compareTo(uri) != 0 + || root.localName.compareTo(localName) != 0) { + throw new BadXmlException("Root element name does" + + " not match. Expected: " + root + ", Got: " + + Element.toString(uri, localName), locator); + } + + start(root, attributes); + } + + void start(Element e, Attributes attributes) { + // Push element onto the stack. + this.current = e; + + if (e.startElementListener != null) { + e.startElementListener.start(attributes); + } + + if (e.endTextElementListener != null) { + this.bodyBuilder = new StringBuilder(); + } + + e.resetRequiredChildren(); + e.visited = true; + } + + @Override + public void characters(char[] buffer, int start, int length) + throws SAXException { + if (bodyBuilder != null) { + bodyBuilder.append(buffer, start, length); + } + } + + @Override + public void endElement(String uri, String localName, String qName) + throws SAXException { + Element current = this.current; + + // If we've ended the current element... + if (depth == current.depth) { + current.checkRequiredChildren(locator); + + // Invoke end element listener. + if (current.endElementListener != null) { + current.endElementListener.end(); + } + + // Invoke end text element listener. + if (bodyBuilder != null) { + String body = bodyBuilder.toString(); + bodyBuilder = null; + + // We can assume that this listener is present. + current.endTextElementListener.end(body); + } + + // Pop element off the stack. + this.current = current.parent; + } + + depth--; + } + } +} |