xmlparser.java

来自「kaffe Java 解释器语言,源码,Java的子集系统,开放源代码」· Java 代码 · 共 2,494 行 · 第 1/5 页

JAVA
2,494
字号
		    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;    }    /**     * Parse an attribute assignment.     * <pre>     * [41] Attribute ::= Name Eq AttValue     * </pre>     * @param name The name of the attribute's element.     * @see SAXDriver#attribute     */    private void parseAttribute (String name)    throws Exception    {	String aname;	String type;	String value;	int flags = LIT_ATTRIBUTE |  LIT_ENTITY_REF;	// Read the attribute name.	aname = readNmtoken (true);	type = getAttributeType (name, aname);	// Parse '='	parseEq ();	// Read the value, normalizing whitespace	// unless it is CDATA.	if (type == "CDATA" || type == null) {	    value = readLiteral (flags);	} else {	    value = readLiteral (flags | LIT_NORMALIZE);	}	// WFC: no duplicate attributes	for (int i = 0; i < tagAttributePos; i++)	    if (aname.equals (tagAttributes [i]))		error ("duplicate attribute", aname, null);	// Inform the handler about the	// attribute.	handler.attribute (aname, value, true);	dataBufferPos = 0;	// Note that the attribute has been	// specified.	if (tagAttributePos == tagAttributes.length) {	    String newAttrib[] = new String [tagAttributes.length * 2];	    System.arraycopy (tagAttributes, 0, newAttrib, 0, tagAttributePos);	    tagAttributes = newAttrib;	}	tagAttributes [tagAttributePos++] = aname;    }    /**     * Parse an equals sign surrounded by optional whitespace.     * <pre>     * [25] Eq ::= S? '=' S?     * </pre>     */    private void parseEq ()    throws SAXException, IOException    {	skipWhitespace ();	require ('=');	skipWhitespace ();    }    /**     * Parse an end tag.     * <pre>     * [42] ETag ::= '</' Name S? '>'     * </pre>     * <p>NOTE: parseContent () chains to here, we already read the     * "&lt;/".     */    private void parseETag ()    throws Exception    {	require (currentElement);	skipWhitespace ();	require ('>');	handler.endElement (currentElement);	// not re-reporting any SAXException re bogus end tags,	// even though that diagnostic might be clearer ...    }    /**     * Parse the content of an element.     * <pre>     * [43] content ::= (element | CharData | Reference     *		| CDSect | PI | Comment)*     * [67] Reference ::= EntityRef | CharRef     * </pre>     * <p> NOTE: consumes ETtag.     */    private void parseContent ()    throws Exception    {	char c;	while (true) {	    // consume characters (or ignorable whitspace) until delimiter	    parseCharData ();	    // Handle delimiters	    c = readCh ();	    switch (c) {	    case '&': 			// Found "&"		c = readCh ();		if (c == '#') {		    parseCharRef ();		} else {		    unread (c);		    parseEntityRef (true);		}		break;	      case '<': 			// Found "<"		dataBufferFlush ();		c = readCh ();		switch (c) {		  case '!': 			// Found "<!"		    c = readCh ();		    switch (c) {		      case '-': 		// Found "<!-"			require ('-');			parseComment ();			break;		      case '[': 		// Found "<!["			require ("CDATA[");			handler.startCDATA ();			inCDATA = true;			parseCDSect ();			inCDATA = false;			handler.endCDATA ();			break;		      default:			error ("expected comment or CDATA section", c, null);			break;		    }		    break;		  case '?': 		// Found "<?"		    parsePI ();		    break;		  case '/': 		// Found "</"		    parseETag ();		    return;		  default: 		// Found "<" followed by something else		    unread (c);		    parseElement (false);		    break;		}	    }	}    }    /**     * Parse an element type declaration.     * <pre>     * [45] elementdecl ::= '&lt;!ELEMENT' S Name S contentspec S? '&gt;'     * </pre>     * <p> NOTE: the '&lt;!ELEMENT' has already been read.     */    private void parseElementDecl ()    throws Exception    {	String name;	requireWhitespace ();	// Read the element type name.	name = readNmtoken (true);	requireWhitespace ();	// Read the content model.	parseContentspec (name);	skipWhitespace ();	require ('>');    }    /**     * Content specification.     * <pre>     * [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | elements     * </pre>     */    private void parseContentspec (String name)    throws Exception    {// FIXME: move elementDecl() into setElement(), pass EMTPY/ANY ...	if (tryRead ("EMPTY")) {	    setElement (name, CONTENT_EMPTY, null, null);	    if (!skippedPE)		handler.getDeclHandler ().elementDecl (name, "EMPTY");	    return;	} else if (tryRead ("ANY")) {	    setElement (name, CONTENT_ANY, null, null);	    if (!skippedPE)		handler.getDeclHandler ().elementDecl (name, "ANY");	    return;	} else {	    String	model;	    char	saved []; 	    require ('(');	    saved = readBuffer;	    dataBufferAppend ('(');	    skipWhitespace ();	    if (tryRead ("#PCDATA")) {		dataBufferAppend ("#PCDATA");		parseMixed (saved);		model = dataBufferToString ();		setElement (name, CONTENT_MIXED, model, null);	    } else {		parseElements (saved);		model = dataBufferToString ();		setElement (name, CONTENT_ELEMENTS, model, null);	    }	    if (!skippedPE)		handler.getDeclHandler ().elementDecl (name, model);	}    }    /**     * Parse an element-content model.     * <pre>     * [47] elements ::= (choice | seq) ('?' | '*' | '+')?     * [49] choice ::= '(' S? cp (S? '|' S? cp)+ S? ')'     * [50] seq ::= '(' S? cp (S? ',' S? cp)* S? ')'     * </pre>     *     * <p> NOTE: the opening '(' and S have already been read.     *     * @param saved Buffer for entity that should have the terminal ')'     */    private void parseElements (char saved [])    throws Exception    {	char c;	char sep;	// Parse the first content particle	skipWhitespace ();	parseCp ();	// Check for end or for a separator.	skipWhitespace ();	c = readCh ();	switch (c) {	case ')':	    // VC: Proper Group/PE Nesting	    if (readBuffer != saved)		handler.verror ("Illegal Group/PE nesting");	    dataBufferAppend (')');	    c = readCh ();	    switch (c) {	    case '*':	    case '+':	    case '?':		dataBufferAppend (c);		break;	    default:		unread (c);	    }	    return;	case ',': 			// Register the separator.	case '|':	    sep = c;	    dataBufferAppend (c);	    break;	default:	    error ("bad separator in content model", c, null);	    return;	}	// Parse the rest of the content model.	while (true) {	    skipWhitespace ();	    parseCp ();	    skipWhitespace ();	    c = readCh ();	    if (c == ')') {		// VC: Proper Group/PE Nesting		if (readBuffer != saved)		    handler.verror ("Illegal Group/PE nesting");		dataBufferAppend (')');		break;	    } else if (c != sep) {		error ("bad separator in content model", c, null);		return;	    } else {		dataBufferAppend (c);	    }	}	// Check for the occurrence indicator.	c = readCh ();	switch (c) {	case '?':	case '*':	case '+':	    dataBufferAppend (c);	    return;	default:	    unread (c);	    return;	}    }    /**     * Parse a content particle.     * <pre>     * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?     * </pre>     */    private void parseCp ()    throws Exception    {	if (tryRead ('(')) {	    dataBufferAppend ('(');	    parseElements (readBuffer);	} else {	    dataBufferAppend (readNmtoken (true));	    char c = readCh ();	    switch (c) {	    case '?':	    case '*':	    case '+':		dataBufferAppend (c);		break;	    default:		unread (c);		break;	    }	}    }    /**     * Parse mixed content.     * <pre>     * [51] Mixed ::= '(' S? ( '#PCDATA' (S? '|' S? Name)*) S? ')*'     *	      | '(' S? ('#PCDATA') S? ')'     * </pre>     *     * @param saved Buffer for entity that should have the terminal ')'     */    private void parseMixed (char saved [])    throws Exception    {	// Check for PCDATA alone.	skipWhitespace ();	if (tryRead (')')) {	    // VC: Proper Group/PE Nesting	    if (readBuffer != saved)		handler.verror ("Illegal Group/PE nesting");	    dataBufferAppend (")*");	    tryRead ('*');	    return;	}	// Parse mixed content.	skipWhitespace ();	while (!tryRead (")")) {	    require ('|');	    dataBufferAppend ('|');	    skipWhitespace ();	    dataBufferAppend (readNmtoken (true));	    skipWhitespace ();	}	// VC: Proper Group/PE Nesting	if (readBuffer != saved)	    handler.verror ("Illegal Group/PE nesting");	require ('*');	dataBufferAppend (")*");    }    /**     * Parse an attribute list declaration.     * <pre>     * [52] AttlistDecl ::= '&lt;!ATTLIST' S Name AttDef* S? '&gt;'     * </pre>     * <p>NOTE: the '&lt;!ATTLIST' has already been read.     */    private void parseAttlistDecl ()    throws Exception    {	String elementName;	requireWhitespace ();	elementName = readNmtoken (true);	boolean white = tryWhitespace ();	while (!tryRead ('>')) {	    if (!white)		error ("whitespace required before attribute definition");	    parseAttDef (elementName);	    white = tryWhitespace ();	}    }    /**     * Parse a single attribute definition.     * <pre>     * [53] AttDef ::= S Name S AttType S DefaultDecl     * </pre>     */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?