/*
 * 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.

For example, passing this XML:

<feed xmlns='http://www.w3.org/2005/Atom'>
  <entry>
    <id>bob</id>
  </entry>
</feed>
to this code:
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(...);
would output:
Entry ID: bob
/** * The root XML element. The entry point for this API. Not safe for concurrent * use. * * <p>For example, passing this XML: * * <pre> * &lt;feed xmlns='http://www.w3.org/2005/Atom'> * &lt;entry> * &lt;id>bob&lt;/id> * &lt;/entry> * &lt;/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.
Params:
  • uri – the namespace
  • localName – the local name
/** * 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.
Params:
  • localName – the local name
/** * 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 ContentHandler. Pass this to your SAX parser.
/** * 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--; } } }