tagAttributePos = 0;
tagAttributePos = 0;   gi = readNmtoken(true);    if (maybeGetSubset) { InputSource subset = handler.getExternalSubset(gi, handler.getSystemId()); if (subset != null) { String publicId = subset.getPublicId(); String systemId = subset.getSystemId();  handler.warn("modifying document by adding DTD"); handler.doctypeDecl(gi, publicId, systemId); pushString(null, ">");    pushURL(true, "[dtd]", new ExternalIdentifiers(publicId, systemId, null), subset.getCharacterStream(), subset.getByteStream(), subset.getEncoding(), false);   while (true) { doReport = expandPE = true; skipWhitespace(); doReport = expandPE = false; if (tryRead('>')) { break; } else { expandPE = true; parseMarkupdecl(); expandPE = false; } }   if (inputStack.size() != 1) { error("external subset has unmatched '>'"); }  handler.endDoctype(); } }   currentElement = gi; element = (ElementDecl) elementInfo.get(gi); currentElementContent = getContentType(element, CONTENT_ANY);
    private void parseElement (boolean maybeGetSubset)    throws Exception    {	String	gi;	char	c;	int	oldElementContent = currentElementContent;	String	oldElement = currentElement;	Object	element [];	// This is the (global) counter for the	// array of specified attributes.	tagAttributePos = 0;	// Read the element type name.	gi = readNmtoken (true);	// If we saw no DTD, and this is the document root element,	// let the application modify the input stream by providing one.	if (maybeGetSubset) {	    InputSource	subset = handler.getExternalSubset (gi,	    		handler.getSystemId ());	    if (subset != null) {		String	publicId = subset.getPublicId ();		String	systemId = subset.getSystemId ();		handler.warn ("modifying document by adding DTD");		handler.doctypeDecl (gi, publicId, systemId);		pushString (null, ">");		// NOTE:  [dtd] is so we say what SAX2 expects,		// though it's misleading (subset, not entire dtd)		pushURL (true, "[dtd]",		    new String [] { publicId, systemId, null },		    subset.getCharacterStream (),		    subset.getByteStream (),		    subset.getEncoding (),		    false);		// Loop until we end up back at '>'		while (true) {		    doReport = expandPE = true;		    skipWhitespace ();		    doReport = expandPE = false;		    if (tryRead ('>')) {			break;		    } else {			expandPE = true;			parseMarkupdecl ();			expandPE = false;		    }		}		// the ">" string isn't popped yet		if (inputStack.size () != 1)		    error ("external subset has unmatched '>'");		handler.endDoctype ();	    }	}	// Determine the current content type.	currentElement = gi;	element = (Object []) elementInfo.get (gi);	currentElementContent = getContentType (element, CONTENT_ANY);	// Read the attributes, if any.	// After this loop, "c" is the closing delimiter.	boolean white = tryWhitespace ();	c = readCh ();	while (c != '/' && c != '>') {	    unread (c);	    if (!white)		error ("need whitespace between attributes");	    parseAttribute (gi);	    white = tryWhitespace ();	    c = readCh ();	}	// Supply any defaulted attributes.	Enumeration atts = declaredAttributes (element);	if (atts != null) {	    String aname;loop:	    while (atts.hasMoreElements ()) {		aname = (String) atts.nextElement ();		// See if it was specified.		for (int i = 0; i < tagAttributePos; i++) {		    if (tagAttributes [i] == aname) {			continue loop;		    }		}		// ... or has a default		String value = getAttributeDefaultValue (gi, aname);		if (value == null)		    continue;		handler.attribute (aname, value, false);	    }	}	// Figure out if this is a start tag	// or an empty element, and dispatch an	// event accordingly.	switch (c) {	case '>':	    handler.startElement (gi);	    parseContent ();	    break;	case '/':	    require ('>');	    handler.startElement (gi);	    handler.endElement (gi);	    break;	}	// Restore the previous state.	currentElement = oldElement;	currentElementContent = oldElementContent;    }