xmlparser.java

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

JAVA
2,494
字号
    private void parseAttDef (String elementName)    throws Exception    {	String name;	String type;	String enum = null;	// Read the attribute name.	name = readNmtoken (true);	// Read the attribute type.	requireWhitespace ();	type = readAttType ();	// Get the string of enumerated values if necessary.	if ("ENUMERATION" == type || "NOTATION" == type)	    enum = dataBufferToString ();	// Read the default value.	requireWhitespace ();	parseDefault (elementName, name, type, enum);    }    /**     * Parse the attribute type.     * <pre>     * [54] AttType ::= StringType | TokenizedType | EnumeratedType     * [55] StringType ::= 'CDATA'     * [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY'     *		| 'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'     * [57] EnumeratedType ::= NotationType | Enumeration     * </pre>     */    private String readAttType ()    throws Exception    {	if (tryRead ('(')) {	    parseEnumeration (false);	    return "ENUMERATION";	} else {	    String typeString = readNmtoken (true);	    if ("NOTATION" == typeString) {		parseNotationType ();		return typeString;	    } else if ("CDATA" == typeString		    || "ID" == typeString		    || "IDREF" == typeString		    || "IDREFS" == typeString		    || "ENTITY" == typeString		    || "ENTITIES" == typeString		    || "NMTOKEN" == typeString		    || "NMTOKENS" == typeString)		return typeString;	    error ("illegal attribute type", typeString, null);	    return null;	}    }    /**     * Parse an enumeration.     * <pre>     * [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'     * </pre>     * <p>NOTE: the '(' has already been read.     */    private void parseEnumeration (boolean isNames)    throws Exception    {	dataBufferAppend ('(');	// Read the first token.	skipWhitespace ();	dataBufferAppend (readNmtoken (isNames));	// Read the remaining tokens.	skipWhitespace ();	while (!tryRead (')')) {	    require ('|');	    dataBufferAppend ('|');	    skipWhitespace ();	    dataBufferAppend (readNmtoken (isNames));	    skipWhitespace ();	}	dataBufferAppend (')');    }    /**     * Parse a notation type for an attribute.     * <pre>     * [58] NotationType ::= 'NOTATION' S '(' S? NameNtoks     *		(S? '|' S? name)* S? ')'     * </pre>     * <p>NOTE: the 'NOTATION' has already been read     */    private void parseNotationType ()    throws Exception    {	requireWhitespace ();	require ('(');	parseEnumeration (true);    }    /**     * Parse the default value for an attribute.     * <pre>     * [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED'     *		| (('#FIXED' S)? AttValue)     * </pre>     */    private void parseDefault (	String elementName,	String name,	String type,	String enum    ) throws Exception    {	int	valueType = ATTRIBUTE_DEFAULT_SPECIFIED;	String	value = null;	int	flags = LIT_ATTRIBUTE;	boolean	saved = expandPE;	String	defaultType = null;	// LIT_ATTRIBUTE forces '<' checks now (ASAP) and turns whitespace	// chars to spaces (doesn't matter when that's done if it doesn't	// interfere with char refs expanding to whitespace).	if (!skippedPE) {	    flags |= LIT_ENTITY_REF;	    if ("CDATA" != type)		flags |= LIT_NORMALIZE;	}	expandPE = false;	if (tryRead ('#')) {	    if (tryRead ("FIXED")) {		defaultType = "#FIXED";		valueType = ATTRIBUTE_DEFAULT_FIXED;		requireWhitespace ();		value = readLiteral (flags);	    } else if (tryRead ("REQUIRED")) {		defaultType = "#REQUIRED";		valueType = ATTRIBUTE_DEFAULT_REQUIRED;	    } else if (tryRead ("IMPLIED")) {		defaultType = "#IMPLIED";		valueType = ATTRIBUTE_DEFAULT_IMPLIED;	    } else {		error ("illegal keyword for attribute default value");	    }	} else	    value = readLiteral (flags);	expandPE = saved;	setAttribute (elementName, name, type, enum, value, valueType);	if ("ENUMERATION" == type)	    type = enum;	else if ("NOTATION" == type)	    type = "NOTATION " + enum;	if (!skippedPE) handler.getDeclHandler ()	    .attributeDecl (elementName, name, type, defaultType, value);    }    /**     * Parse a conditional section.     * <pre>     * [61] conditionalSect ::= includeSect || ignoreSect     * [62] includeSect ::= '&lt;![' S? 'INCLUDE' S? '['     *		extSubsetDecl ']]&gt;'     * [63] ignoreSect ::= '&lt;![' S? 'IGNORE' S? '['     *		ignoreSectContents* ']]&gt;'     * [64] ignoreSectContents ::= Ignore     *		('&lt;![' ignoreSectContents* ']]&gt;' Ignore )*     * [65] Ignore ::= Char* - (Char* ( '&lt;![' | ']]&gt;') Char* )     * </pre>     * <p> NOTE: the '&gt;![' has already been read.     */    private void parseConditionalSect (char saved [])    throws Exception    {	skipWhitespace ();	if (tryRead ("INCLUDE")) {	    skipWhitespace ();	    require ('[');	    // VC: Proper Conditional Section/PE Nesting	    if (readBuffer != saved)		handler.verror ("Illegal Conditional Section/PE nesting");	    skipWhitespace ();	    while (!tryRead ("]]>")) {		parseMarkupdecl ();		skipWhitespace ();	    }	} else if (tryRead ("IGNORE")) {	    skipWhitespace ();	    require ('[');	    // VC: Proper Conditional Section/PE Nesting	    if (readBuffer != saved)		handler.verror ("Illegal Conditional Section/PE nesting");	    int nesting = 1;	    char c;	    expandPE = false;	    for (int nest = 1; nest > 0;) {		c = readCh ();		switch (c) {		case '<':		    if (tryRead ("![")) {			nest++;		    }		case ']':		    if (tryRead ("]>")) {			nest--;		    }		}	    }	    expandPE = true;	} else {	    error ("conditional section must begin with INCLUDE or IGNORE");	}    }  private void parseCharRef ()    throws SAXException, IOException  {    parseCharRef (true /* do flushDataBuffer by default */);  }    /**     * Read and interpret a character reference.     * <pre>     * [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'     * </pre>     * <p>NOTE: the '&#' has already been read.     */    private void parseCharRef (boolean doFlush)    throws SAXException, IOException    {	int value = 0;	char c;	if (tryRead ('x')) {loop1:	    while (true) {		c = readCh ();		int n;		switch (c) {		case '0': case '1': case '2': case '3': case '4':		case '5': case '6': case '7': case '8': case '9':		    n = c - '0';		    break;		case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':		    n = (c - 'a') + 10;		    break;		case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':		    n = (c - 'A') + 10;		    break;		case ';':		    break loop1;		default:		    error ("illegal character in character reference", c, null);		    break loop1;		}		value *= 16;		value += n;	    }	} else {loop2:	    while (true) {		c = readCh ();		switch (c) {		case '0': case '1': case '2': case '3': case '4':		case '5': case '6': case '7': case '8': case '9':		    value *= 10;		    value += c - '0';		    break;		case ';':		    break loop2;		default:		    error ("illegal character in character reference", c, null);		    break loop2;		}	    }	}	// check for character refs being legal XML	if ((value < 0x0020		&& ! (value == '\n' || value == '\t' || value == '\r'))		|| (value >= 0xD800 && value <= 0xDFFF)		|| value == 0xFFFE || value == 0xFFFF		|| value > 0x0010ffff)	    error ("illegal XML character reference U+"		    + Integer.toHexString (value));	// Check for surrogates: 00000000 0000xxxx yyyyyyyy zzzzzzzz	//  (1101|10xx|xxyy|yyyy + 1101|11yy|zzzz|zzzz:	if (value <= 0x0000ffff) {	    // no surrogates needed	    dataBufferAppend ((char) value);	} else if (value <= 0x0010ffff) {	    value -= 0x10000;	    // > 16 bits, surrogate needed	    dataBufferAppend ((char) (0xd800 | (value >> 10)));	    dataBufferAppend ((char) (0xdc00 | (value & 0x0003ff)));	} else {	    // too big for surrogate	    error ("character reference " + value + " is too large for UTF-16",		   new Integer (value).toString (), null);	}  if (doFlush) dataBufferFlush ();    }    /**     * Parse and expand an entity reference.     * <pre>     * [68] EntityRef ::= '&' Name ';'     * </pre>     * <p>NOTE: the '&amp;' has already been read.     * @param externalAllowed External entities are allowed here.     */    private void parseEntityRef (boolean externalAllowed)    throws SAXException, IOException    {	String name;	name = readNmtoken (true);	require (';');	switch (getEntityType (name)) {	case ENTITY_UNDECLARED:	    // NOTE:  XML REC describes amazingly convoluted handling for	    // this case.  Nothing as meaningful as being a WFness error	    // unless the processor might _legitimately_ not have seen a	    // declaration ... which is what this implements.	    String	message;	    	    message = "reference to undeclared general entity " + name;	    if (skippedPE && !docIsStandalone) {		handler.verror (message);		// we don't know this entity, and it might be external...		if (externalAllowed)		    handler.skippedEntity (name);	    } else		error (message);	    break;	case ENTITY_INTERNAL:	    pushString (name, getEntityValue (name));	    break;	case ENTITY_TEXT:	    if (externalAllowed) {		pushURL (false, name, getEntityIds (name),			null, null, null, true);	    } else {		error ("reference to external entity in attribute value.",			name, null);	    }	    break;	case ENTITY_NDATA:	    if (externalAllowed) {		error ("unparsed entity reference in content", name, null);	    } else {		error ("reference to external entity in attribute value.",			name, null);	    }	    break;	default:	    throw new RuntimeException ();	}    }    /**     * Parse and expand a parameter entity reference.     * <pre>     * [69] PEReference ::= '%' Name ';'     * </pre>     * <p>NOTE: the '%' has already been read.     */    private void parsePEReference ()    throws SAXException, IOException    {	String name;	name = "%" + readNmtoken (true);	require (';');	switch (getEntityType (name)) {	case ENTITY_UNDECLARED:	    // VC: Entity Declared	    handler.verror ("reference to undeclared parameter entity " + name);	    // we should disable handling of all subsequent declarations	    // unless this is a standalone document (info discarded)	    break;	case ENTITY_INTERNAL:	    if (inLiteral)		pushString (name, getEntityValue (name));	    else		pushString (name, ' ' + getEntityValue (name) + ' ');	    break;	case ENTITY_TEXT:	    if (!inLiteral)		pushString (null, " ");	    pushURL (true, name, getEntityIds (name), null, null, null, true);	    if (!inLiteral)		pushString (null, " ");	    break;	}    }    /**     * Parse an entity declaration.     * <pre>     * [70] EntityDecl ::= GEDecl | PEDecl     * [71] GEDecl ::= '&lt;!ENTITY' S Name S EntityDef S? '&gt;'     * [72] PEDecl ::= '&lt;!ENTITY' S '%' S Name S PEDef S? '&gt;'     * [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)     * [74] PEDef ::= EntityValue | ExternalID     * [75] ExternalID ::= 'SYSTEM' S SystemLiteral     *		   | 'PUBLIC' S PubidLiteral S SystemLiteral     * [76] NDataDecl ::= S 'NDATA' S Name     * </pre>     * <p>NOTE: the '&lt;!ENTITY' has already been read.     */    private void parseEntityDecl ()    throws Exception    {	boolean peFlag = false;	int flags = LIT_DISABLE_CREF;	// Check for a parameter entity.	expandPE = false;	requireWhitespace ();	if (tryRead ('%')) {	    peFlag = true;	    requireWhitespace ();	}	expandPE = true;	// Read the entity name, and prepend	// '%' if necessary.	String name = readNmtoken (true);	if (peFlag) {	    name = "%" + name;	}	// Read the entity value.	requireWhitespace ();	char c = readCh ();	unread (c);	if (c == '"' || c == '\'') {	    // Internal entity ... replacement text has expanded refs	    // to characters and PEs, but not to general entities	    String value = readLiteral (flags);	    setInternalEntity (name, value);	} else {	    // Read the external IDs	    String ids [] = readExternalIds (false, false);	    // Check for NDATA declaration.	    boolean white = tryWhitespace ();	    if (!peFlag && tryRead ("NDATA")) {		if (!white)		    error ("whitespace required before NDATA");		requireWhitespace ();		String notationName = readNmtoken (true);		if (!skippedPE) {		    setExternalEntity (name, ENTITY_NDATA, ids, notationName);		    handler.unparsedEntityDecl (name, ids, notationName);		}	    } else if (!skippedPE) {		setExternalEntity (name, ENTITY_TEXT, ids, null);		handler.getDeclHandler ()		    .externalEntityDecl (name, ids [0],			    handler.resolveURIs ()	    				// FIXME: ASSUMES not skipped					// "false" forces error on bad URI				? handler.absolutize (ids [2], ids [1], false)				: ids [1]);	    }	}	// Finish the declaration.	skipWhitespace ();	require ('>');    }    /**     * Parse a notation declaration.     * <pre>     * [82] NotationDecl ::= '&lt;!NOTATION' S Name S     *		(ExternalID | PublicID) S? '&gt;'     * [83] PublicID ::= 'PUBLIC' S PubidLiteral     * </pre>     * <P>NOTE: the '&lt;!NOTATION' has already been read.     */    private void parseNotationDecl ()    throws Exception    {

⌨️ 快捷键说明

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