void doParse(String systemId, String publicId, Reader reader,
            InputStream stream, String encoding) throws Exception {
        if (handler == null) {
            throw new IllegalStateException("no callback handler");
        }

        alreadyWarnedAboutPrivateUseCharacters = false;
        initializeVariables();

        // predeclare the built-in entities here (replacement texts)
        // we don't need to intern(), since we're guaranteed literals
        // are always (globally) interned.
        setInternalEntity("amp", "&#38;");
        setInternalEntity("lt", "&#60;");
        setInternalEntity("gt", "&#62;");
        setInternalEntity("apos", "&#39;");
        setInternalEntity("quot", "&#34;");

        try {
            // pushURL first to ensure locator is correct in startDocument
            // ... it might report an IO or encoding exception.
            handler.startDocument();
            pushURL(false, "[document]",
                    // default baseURI: null
                    new ExternalIdentifiers(publicId, systemId, null), reader,
                    stream, encoding, false);

            parseDocument();
        } catch (EOFException e) {
            // empty input
            fatal("Empty document, with no root element.");
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    /* ignore */
                }
            }
            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException e) {
                    /* ignore */
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    /* ignore */
                }
            }
        }
    }
Parse an XML document from the character stream, byte stream, or URI that
you provide (in that order of preference). Any URI that you supply will
become the base URI for resolving relative URI, and may be used to
acquire a reader or byte stream.

<p>
Only one thread at a time may use this parser; since it is private to
this package, post-parse cleanup is done by the caller, which MUST NOT
REUSE the parser (just null it).

@param systemId
           Absolute URI of the document; should never be null, but may be
           so iff a reader <em>or</em> a stream is provided.
@param publicId
           The public identifier of the document, or null.
@param reader
           A character stream; must be null if stream isn't.
@param stream
           A byte input stream; must be null if reader isn't.
@param characterEncoding
           The suggested encoding, or null if unknown.
@exception java.lang.Exception
               Basically SAXException or IOException
src/nu/validator/gnu/xml/aelfred2/XmlParser.java