📄 xmlparser.java
字号:
* <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; int 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 == ATTRIBUTE_CDATA || type == ATTRIBUTE_UNDECLARED) { 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 * "</". */ 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 { String data; char c; while (true) { switch (currentElementContent) { case CONTENT_ANY: case CONTENT_MIXED: parseCharData (); break; case CONTENT_ELEMENTS: parseWhitespace (); break; } // 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 (); break; } } } } /** * Parse an element type declaration. * <pre> * [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>' * </pre> * <p> NOTE: the '<!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 { if (tryRead ("EMPTY")) { setElement (name, CONTENT_EMPTY, null); return; } else if (tryRead ("ANY")) { setElement (name, CONTENT_ANY, null); return; } else { require ('('); dataBufferAppend ('('); skipWhitespace (); if (tryRead ("#PCDATA")) { dataBufferAppend ("#PCDATA"); parseMixed (); setElement (name, CONTENT_MIXED, dataBufferToString ()); } else { parseElements (); setElement (name, CONTENT_ELEMENTS, dataBufferToString ()); } } } /** * 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. */ private void parseElements () 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 ')': 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 == ')') { 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 { char c; if (tryRead ('(')) { dataBufferAppend ('('); parseElements (); } else { dataBufferAppend (readNmtoken (true)); 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> */ private void parseMixed () throws Exception { char c; // Check for PCDATA alone. skipWhitespace (); if (tryRead (')')) { dataBufferAppend (")*"); tryRead ('*'); return; } // Parse mixed content. skipWhitespace (); while (!tryRead (")*")) { require ('|'); dataBufferAppend ('|'); skipWhitespace (); dataBufferAppend (readNmtoken (true)); skipWhitespace (); } dataBufferAppend (")*"); } /** * Parse an attribute list declaration. * <pre> * [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>' * </pre> * <p>NOTE: the '<!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> */ private void parseAttDef (String elementName) throws Exception { String name; int 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 (type == ATTRIBUTE_ENUMERATED || type == ATTRIBUTE_NOTATION) { 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 int readAttType () throws Exception { String typeString; Integer type; if (tryRead ('(')) { parseEnumeration (false); return ATTRIBUTE_ENUMERATED; } else { typeString = readNmtoken (true); if (typeString.equals ("NOTATION")) { parseNotationType (); } type = (Integer) attributeTypeHash.get (typeString); if (type == null) { error ("illegal attribute type", typeString, null); return ATTRIBUTE_UNDECLARED; } else { return type.intValue (); } } } /** * 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 { char c; 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, int type, String enum ) throws Exception
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -