📄 xmlparser.java
字号:
else error ("conditional sections illegal in internal subset"); } else { error ("expected markup declaration"); } } /** * Parse an element, with its tags. * <pre> * [39] element ::= EmptyElementTag | STag content ETag * [40] STag ::= '<' Name (S Attribute)* S? '>' * [44] EmptyElementTag ::= '<' Name (S Attribute)* S? '/>' * </pre> * <p> (The '<' has already been read.) * <p>NOTE: this method actually chains onto parseContent (), if necessary, * and parseContent () will take care of calling parseETag (). */ private void parseElement () 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); // 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. Iterator atts = declaredAttributes (element); if (atts != null) { String aname;loop: while (atts.hasNext ()) { aname = (String) atts.next (); // See if it was specified. for (int i = 0; i < tagAttributePos; i++) { if (tagAttributes [i] == aname) { continue loop; } } // I guess not... handler.attribute (aname, getAttributeExpandedValue (gi, aname), 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; 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: case CONTENT_UNDECLARED: // this line added by MHK 24 May 2000 case CONTENT_EMPTY: // this line added by MHK 8 Sept 2000 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, null); return; } else if (tryRead ("ANY")) { setElement (name, CONTENT_ANY, null, null); return; } else { require ('('); dataBufferAppend ('('); skipWhitespace (); if (tryRead ("#PCDATA")) { dataBufferAppend ("#PCDATA"); parseMixed (); setElement (name, CONTENT_MIXED, dataBufferToString (), null); } else { parseElements (); setElement (name, CONTENT_ELEMENTS, dataBufferToString (), null); } } } /** * 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>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -