org.dom4j.io.XPPReader Maven / Gradle / Ivy
/*
* Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
*
* This software is open source.
* See the bottom of this file for the licence.
*/
package org.dom4j.io;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import org.dom4j.ElementHandler;
import org.dom4j.xpp.ProxyXmlStartTag;
import org.gjt.xpp.XmlEndTag;
import org.gjt.xpp.XmlPullParser;
import org.gjt.xpp.XmlPullParserException;
import org.gjt.xpp.XmlPullParserFactory;
/**
*
* XPPReader
is a Reader of DOM4J documents that uses the fast XML Pull Parser 2.x . It
* does not currently support comments, CDATA or ProcessingInstructions or
* validation but it is very fast for use in SOAP style environments.
*
*
* @author James Strachan
* @version $Revision: 1.7 $
*/
public class XPPReader {
/** DocumentFactory
used to create new document objects */
private DocumentFactory factory;
/** XmlPullParser
used to parse XML */
private XmlPullParser xppParser;
/** XmlPullParser
used to parse XML */
private XmlPullParserFactory xppFactory;
/** DispatchHandler to call when each Element
is encountered */
private DispatchHandler dispatchHandler;
public XPPReader() {
}
public XPPReader(DocumentFactory factory) {
this.factory = factory;
}
/**
*
* Reads a Document from the given File
*
*
* @param file
* is the File
to read from.
*
* @return the newly created Document instance
*
* @throws DocumentException
* if an error occurs during parsing.
* @throws IOException
* if a URL could not be made for the given File
* @throws XmlPullParserException
* DOCUMENT ME!
*/
public Document read(File file) throws DocumentException, IOException,
XmlPullParserException {
String systemID = file.getAbsolutePath();
return read(new BufferedReader(new FileReader(file)), systemID);
}
/**
*
* Reads a Document from the given URL
*
*
* @param url
* URL
to read from.
*
* @return the newly created Document instance
*
* @throws DocumentException
* if an error occurs during parsing.
* @throws IOException
* DOCUMENT ME!
* @throws XmlPullParserException
* DOCUMENT ME!
*/
public Document read(URL url) throws DocumentException, IOException,
XmlPullParserException {
String systemID = url.toExternalForm();
return read(createReader(url.openStream()), systemID);
}
/**
*
* Reads a Document from the given URL or filename.
*
*
*
* If the systemID contains a ':'
character then it is
* assumed to be a URL otherwise its assumed to be a file name. If you want
* finer grained control over this mechansim then please explicitly pass in
* either a {@link URL}or a {@link File}instance instead of a {@link
* String} to denote the source of the document.
*
*
* @param systemID
* is a URL for a document or a file name.
*
* @return the newly created Document instance
*
* @throws DocumentException
* if an error occurs during parsing.
* @throws IOException
* if a URL could not be made for the given File
* @throws XmlPullParserException
* DOCUMENT ME!
*/
public Document read(String systemID) throws DocumentException,
IOException, XmlPullParserException {
if (systemID.indexOf(':') >= 0) {
// lets assume its a URL
return read(new URL(systemID));
} else {
// lets assume that we are given a file name
return read(new File(systemID));
}
}
/**
*
* Reads a Document from the given stream
*
*
* @param in
* InputStream
to read from.
*
* @return the newly created Document instance
*
* @throws DocumentException
* if an error occurs during parsing.
* @throws IOException
* DOCUMENT ME!
* @throws XmlPullParserException
* DOCUMENT ME!
*/
public Document read(InputStream in) throws DocumentException, IOException,
XmlPullParserException {
return read(createReader(in));
}
/**
*
* Reads a Document from the given Reader
*
*
* @param reader
* is the reader for the input
*
* @return the newly created Document instance
*
* @throws DocumentException
* if an error occurs during parsing.
* @throws IOException
* DOCUMENT ME!
* @throws XmlPullParserException
* DOCUMENT ME!
*/
public Document read(Reader reader) throws DocumentException, IOException,
XmlPullParserException {
getXPPParser().setInput(reader);
return parseDocument();
}
/**
*
* Reads a Document from the given array of characters
*
*
* @param text
* is the text to parse
*
* @return the newly created Document instance
*
* @throws DocumentException
* if an error occurs during parsing.
* @throws IOException
* DOCUMENT ME!
* @throws XmlPullParserException
* DOCUMENT ME!
*/
public Document read(char[] text) throws DocumentException, IOException,
XmlPullParserException {
getXPPParser().setInput(text);
return parseDocument();
}
/**
*
* Reads a Document from the given stream
*
*
* @param in
* InputStream
to read from.
* @param systemID
* is the URI for the input
*
* @return the newly created Document instance
*
* @throws DocumentException
* if an error occurs during parsing.
* @throws IOException
* DOCUMENT ME!
* @throws XmlPullParserException
* DOCUMENT ME!
*/
public Document read(InputStream in, String systemID)
throws DocumentException, IOException, XmlPullParserException {
return read(createReader(in), systemID);
}
/**
*
* Reads a Document from the given Reader
*
*
* @param reader
* is the reader for the input
* @param systemID
* is the URI for the input
*
* @return the newly created Document instance
*
* @throws DocumentException
* if an error occurs during parsing.
* @throws IOException
* DOCUMENT ME!
* @throws XmlPullParserException
* DOCUMENT ME!
*/
public Document read(Reader reader, String systemID)
throws DocumentException, IOException, XmlPullParserException {
Document document = read(reader);
document.setName(systemID);
return document;
}
// Properties
// -------------------------------------------------------------------------
public XmlPullParser getXPPParser() throws XmlPullParserException {
if (xppParser == null) {
xppParser = getXPPFactory().newPullParser();
}
return xppParser;
}
public XmlPullParserFactory getXPPFactory() throws XmlPullParserException {
if (xppFactory == null) {
xppFactory = XmlPullParserFactory.newInstance();
}
return xppFactory;
}
public void setXPPFactory(XmlPullParserFactory xPPFactory) {
this.xppFactory = xPPFactory;
}
/**
* DOCUMENT ME!
*
* @return the DocumentFactory
used to create document
* objects
*/
public DocumentFactory getDocumentFactory() {
if (factory == null) {
factory = DocumentFactory.getInstance();
}
return factory;
}
/**
*
* This sets the DocumentFactory
used to create new
* documents. This method allows the building of custom DOM4J tree objects
* to be implemented easily using a custom derivation of
* {@link DocumentFactory}
*
*
* @param documentFactory
* DocumentFactory
used to create DOM4J objects
*/
public void setDocumentFactory(DocumentFactory documentFactory) {
this.factory = documentFactory;
}
/**
* Adds the ElementHandler
to be called when the specified
* path is encounted.
*
* @param path
* is the path to be handled
* @param handler
* is the ElementHandler
to be called by the event
* based processor.
*/
public void addHandler(String path, ElementHandler handler) {
getDispatchHandler().addHandler(path, handler);
}
/**
* Removes the ElementHandler
from the event based processor,
* for the specified path.
*
* @param path
* is the path to remove the ElementHandler
for.
*/
public void removeHandler(String path) {
getDispatchHandler().removeHandler(path);
}
/**
* When multiple ElementHandler
instances have been
* registered, this will set a default ElementHandler
to be
* called for any path which does NOT have a handler registered.
*
* @param handler
* is the ElementHandler
to be called by the event
* based processor.
*/
public void setDefaultHandler(ElementHandler handler) {
getDispatchHandler().setDefaultHandler(handler);
}
// Implementation methods
// -------------------------------------------------------------------------
protected Document parseDocument() throws DocumentException, IOException,
XmlPullParserException {
Document document = getDocumentFactory().createDocument();
Element parent = null;
XmlPullParser parser = getXPPParser();
parser.setNamespaceAware(true);
ProxyXmlStartTag startTag = new ProxyXmlStartTag();
XmlEndTag endTag = xppFactory.newEndTag();
while (true) {
int type = parser.next();
switch (type) {
case XmlPullParser.END_DOCUMENT:
return document;
case XmlPullParser.START_TAG: {
parser.readStartTag(startTag);
Element newElement = startTag.getElement();
if (parent != null) {
parent.add(newElement);
} else {
document.add(newElement);
}
parent = newElement;
break;
}
case XmlPullParser.END_TAG: {
parser.readEndTag(endTag);
if (parent != null) {
parent = parent.getParent();
}
break;
}
case XmlPullParser.CONTENT: {
String text = parser.readContent();
if (parent != null) {
parent.addText(text);
} else {
String msg = "Cannot have text content outside of the "
+ "root document";
throw new DocumentException(msg);
}
break;
}
default:
throw new DocumentException("Error: unknown type: " + type);
}
}
}
protected DispatchHandler getDispatchHandler() {
if (dispatchHandler == null) {
dispatchHandler = new DispatchHandler();
}
return dispatchHandler;
}
protected void setDispatchHandler(DispatchHandler dispatchHandler) {
this.dispatchHandler = dispatchHandler;
}
/**
* Factory method to create a Reader from the given InputStream.
*
* @param in
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws IOException
* DOCUMENT ME!
*/
protected Reader createReader(InputStream in) throws IOException {
return new BufferedReader(new InputStreamReader(in));
}
}
/*
* Redistribution and use of this software and associated documentation
* ("Software"), with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain copyright statements and
* notices. Redistributions must also contain a copy of this document.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name "DOM4J" must not be used to endorse or promote products derived
* from this Software without prior written permission of MetaStuff, Ltd. For
* written permission, please contact [email protected].
*
* 4. Products derived from this Software may not be called "DOM4J" nor may
* "DOM4J" appear in their names without prior written permission of MetaStuff,
* Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
*
* 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
*
* THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
*/