[jdom-interest] How to kill a parser - nicely
Alex Rosen
arosen at silverstream.com
Tue Aug 14 07:53:04 PDT 2001
Specifically, you should throw a particular subclass of SAXParseException,
so you can tell it from a real error. Here's the code I use to retrieve only
up to the root element (i.e. it stops processing when it hits the root
element's closing >.) It seems to work fine.
Alex
// Setup the SAXBuilder.
StoppableSAXBuilder builder = new StoppableSAXBuilder();
builder.setValidation(false);
// Parse the document.
InputStream in = null;
try
{
in = new BufferedInputStream(instream);
m_document = builder.build(in);
m_gotEntireDocument = true;
}
catch(JDOMException ex)
{
m_document = builder.getDocument();
m_gotEntireDocument = false;
// This exception was thrown to tell us that the root node was found,
// and to halt further processing (to save time). This indicates success,
// not failure, so we just swallow the exception here.
if (!(ex.getRootCause() instanceof RootFoundException))
throw ex;
}
finally
{
if (in != null)
in.close();
}
}
// Subclass of SAXBuilder that creates our special SAXHandler.
private class StoppableSAXBuilder extends SAXBuilder
{
protected SAXHandler createContentHandler() throws Exception
{
m_handler = new StoppableSAXHandler(factory);
return m_handler;
}
// If we've at least finished with the root element, then we return
// the document that's been built so far.
Document getDocument()
{
if (m_handler.m_gotRootElementEnd)
return m_handler.getDocument();
else
return null;
}
private StoppableSAXHandler m_handler;
}
// Subclass of SAXHandler that stops the build process after the
// root element has been found.
private class StoppableSAXHandler extends SAXHandler
{
public StoppableSAXHandler(JDOMFactory factory) throws IOException
{
super(factory);
}
public void startElement(String uri, String localName, String qName,
Attributes attributes)
throws SAXException
{
checkRoot();
// Record the fact that we've gotten to the root element.
if (!m_gotRootElementStart)
m_gotRootElementStart = true;
super.startElement(uri, localName, qName, attributes);
}
public void characters(char[] ch, int start, int length) throws
SAXException
{
checkRoot();
super.characters(ch, start, length);
}
public void ignorableWhitespace(char[] ch, int start, int length) throws
SAXException
{
checkRoot();
super.ignorableWhitespace(ch, start, length);
}
public void comment(char[] ch, int start, int length) throws
SAXException
{
checkRoot();
super.comment(ch, start, length);
}
public void startEntity(String name) throws SAXException
{
checkRoot();
super.startEntity(name);
}
public void processingInstruction(String target, String data) throws
SAXException
{
checkRoot();
super.processingInstruction(target, data);
}
private void checkRoot() throws RootFoundException
{
// If we've started the root, then we now know that we've finished it.
// Record that fact, and throw a RootFoundException if we only need
// the root node. This will halt the parsing.
if (m_gotRootElementStart && !m_gotRootElementEnd)
{
m_gotRootElementEnd = true;
throw new RootFoundException();
}
}
private boolean m_gotRootElementStart;
private boolean m_gotRootElementEnd;
}
private static class RootFoundException extends SAXException
{
RootFoundException()
{
// This should never be visible to the user.
super("Root element was successfully found. (This is not an error.)");
}
}
More information about the jdom-interest
mailing list