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 ::= '<![' S? 'INCLUDE' S? '[' * extSubsetDecl ']]>' * [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' * ignoreSectContents* ']]>' * [64] ignoreSectContents ::= Ignore * ('<![' ignoreSectContents* ']]>' Ignore )* * [65] Ignore ::= Char* - (Char* ( '<![' | ']]>') Char* ) * </pre> * <p> NOTE: the '>![' 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 '&' 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 ::= '<!ENTITY' S Name S EntityDef S? '>' * [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>' * [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 '<!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 ::= '<!NOTATION' S Name S * (ExternalID | PublicID) S? '>' * [83] PublicID ::= 'PUBLIC' S PubidLiteral * </pre> * <P>NOTE: the '<!NOTATION' has already been read. */ private void parseNotationDecl () throws Exception {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?