📄 xmlparser.java
字号:
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 { 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); } isDirtyCurrentElement = true; break; case '<': // Found "<" dataBufferFlush(); c = readCh(); switch (c) { case '!': // Found "<!" c = readCh(); switch (c) { case '-': // Found "<!-" require('-'); isDirtyCurrentElement = false; parseComment(); break; case '[': // Found "<![" isDirtyCurrentElement = false; 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 "<?" isDirtyCurrentElement = false; parsePI(); break; case '/': // Found "</" isDirtyCurrentElement = false; parseETag(); return; default: // Found "<" followed by something else isDirtyCurrentElement = false; unread(c); parseElement(false); 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 { // 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 ::= '<!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; String type; String enumer = null; // Read the attribute name. name = readNmtoken(true); // Read the attribute type. requireWhitespace(); type = readAttType(); // Get the string of enumerated values if necessary. if (handler.stringInterning) { if ("ENUMERATION" == type || "NOTATION" == type) { enumer = dataBufferToString(); } } else { if ("ENUMERATION".equals(type) || "NOTATION".equals(type)) { enumer = dataBufferToString(); } } // Read the default value. requireWhitespace(); parseDefault(elementName, name, type, enumer); } /** * 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 (handler.stringInterning) { if ("NOTATION" == typeString) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -