📄 parser.java
字号:
} } } /** * Parses a notation declaration. * * This method parses the declaration up to the closing angle * bracket. * * @exception SAXException * @exception IOException */ private void dtdnot() throws SAXException, IOException { wsskip(); String name = name(false); wsskip(); Pair ids = pubsys('N'); mHand.notationDecl(name, ids.name, ids.value); del(ids); } /** * Parses an element. * * This recursive method is responsible for prefix scope control * (<code>mPref</code>). When the element is leaving the scope all * prefixes defined within the element are removed from the prefix * stack. * * @exception SAXException * @exception IOException */ private void elm() throws SAXException, IOException { // Save the current top of the prefix stack Pair pref = mPref; // Read an element name and put it on top of the element stack mElm = pair(mElm); mElm.chars = qname(mIsNSAware); mElm.name = mElm.local(); // Find the list of defined attributs of the current element Pair elm = find(mAttL, mElm.chars); // Read attributes till the end of the element tag mAttrIdx = 0; Pair att = pair(null); att.list = (elm != null)? elm.list: null; // attrs defined on this elm attr(att); del(att); // Read the element and it's content mBuffIdx = -1; char ch; for (short st = 0; st >= 0;) { ch = next(); switch (st) { case 0: // read the end of the element tag case 1: // read the end of the empty element switch (ch) { case '>': // Report the element if (mIsNSAware == true) { mElm.value = rslv(mElm.chars); mHand.startElement( mElm.value, mElm.name, "", mAttrs); } else { mHand.startElement( "", "", mElm.name, mAttrs); } mItems = null; st = (st == 0)? (short)2: (short)-1; break; case '/': if (st != 0) panic(FAULT); st = 1; break; default: panic(FAULT); } break; case 2: // skip white space between tags switch (chtyp(ch)) { case ' ': bappend(ch); break; case '<': // BUG: With additional info from DTD and xml:space attr // the following call can be supported: // mHand.ignorableWhitespace(mBuff, 0, (mBuffIdx + 1)); bflash(); default: back(); st = 3; break; } break; case 3: // read the text content of the element switch (ch) { case '&': ent('c'); break; case '<': bflash(); switch (next()) { case '/': // the end of the element content // Check element's open/close tags balance mBuffIdx = -1; bname(mIsNSAware); char[] chars = mElm.chars; if (chars.length == (mBuffIdx + 1)) { for (char i = 1; i <= mBuffIdx; i += 1) { if (chars[i] != mBuff[i]) panic(FAULT); } } else { panic(FAULT); } // Skip white spaces before '>' if (wsskip() != '>') panic(FAULT); ch = next(); st = -1; break; case '!': // a comment or a CDATA ch = next(); back(); switch (ch) { case '-': // must be a comment comm(); break; case '[': // must be a CDATA section cdat(); break; default: panic(FAULT); } break; case '?': // processing instruction pi(); break; default: // must be the first char of an xml name back(); elm(); // recursive call break; } mBuffIdx = -1; if (st != -1) st = 2; break; case '\r': // EOL processing [#2.11] if (next() != '\n') back(); bappend('\n'); break; default: bappend(ch); break; } break; default: panic(FAULT); } } // Report the end of element if (mIsNSAware == true) mHand.endElement(mElm.value, mElm.name, ""); else mHand.endElement("", "", mElm.name); // Remove the top element tag mElm = del(mElm); // Restore the top of the prefix stack while (mPref != pref) { mHand.endPrefixMapping(mPref.name); mPref = del(mPref); } } /** * Parses an attribute. * * This recursive method is responsible for prefix addition * (<code>mPref</code>) and prefix mapping reports on the way down. The * element's start tag end triggers the return process. The method then * on it's way back resolves prefixes and accumulates attributes.<br /> * Note that this method will not report namespace declaration attributes * (xmlns* attributes), the {@link Handler#mapStart mapStart} method is * invoked instead. * * @param att An object which reprecents current attribute. * @exception SAXException * @exception IOException */ private void attr(Pair att) throws SAXException, IOException { Pair next = null; char norm = 'c'; // CDATA-type normalization by default [#3.3.3] String val; String type; try { switch (wsskip()) { case '/': case '>': // Go through all defined attributes on current tag to // find defaults for (Pair def = att.list; def != null; def = def.next) { if (def.list != null) { // Attribut definition with default value Pair act = att.next; while (act != null) { if (act.eqname(def.chars) == true) break; act = act.next; } if (act == null) { // Add default attribute push(new Input(def.list.chars)); attr(att); return; } } } // Ensure the attribute string array capacity mAttrs.setLength(mAttrIdx); mItems = mAttrs.mItems; return; default: // Read the attribute name and value att.chars = qname(mIsNSAware); att.name = att.local(); type = "CDATA"; if (att.list != null) { Pair attr = find(att.list, att.chars); if (attr != null) { switch (attr.id) { case 'i': type = "ID"; norm = 'i'; break; case 'r': type = "IDREF"; norm = 'i'; break; case 'R': type = "IDREFS"; norm = 'i'; break; case 'n': type = "ENTITY"; norm = 'i'; break; case 'N': type = "ENTITIES"; norm = 'i'; break; case 't': type = "NMTOKEN"; norm = 'i'; break; case 'T': type = "NMTOKENS"; norm = 'i'; break; case 'u': type = "NMTOKEN"; norm = 'i'; break; case 'o': type = "NOTATION"; norm = 'i'; break; case 'c': norm = 'c'; break; default: panic(FAULT); break; } } } wsskip(); if (next() != '=') panic(FAULT); bqstr(norm); // read the value with normalization. val = new String(mBuff, 1, mBuffIdx); // Put a namespace declaration on top of the prefix stack if ((mIsNSAware == false) || (isdecl(att, val) == false)) { // An ordinary attribute mAttrIdx++; // Recursive call to parse the next attribute next = pair(att); next.list = att.list; attr(next); mAttrIdx--; // Add the attribute to the attributes string array char idx = (char)(mAttrIdx << 3); mItems[idx + 1] = att.qname(); // attr qname mItems[idx + 2] = att.name; // attr local name mItems[idx + 3] = val; // attr value mItems[idx + 4] = type; // attr type // Resolve the prefix if any and report the attribute // NOTE: The attribute does not accept the default namespace. mItems[idx + 0] = (att.chars[0] != 0)? rslv(att.chars): ""; } else { // A namespace declaration // Report a start of the new mapping mHand.startPrefixMapping(mPref.name, mPref.value); // Recursive call to parse the next attribute next = pair(att); next.list = att.list; attr(next); // NOTE: The namespace declaration is not reported. } break; } } finally { if (next != null) del(next); } } /** * Parses a comment. * * @exception org.xml.SAXException * @exception java.io.IOException */ private void comm() throws SAXException, IOException { if (mSt == 0) mSt = 1; // misc before DTD char ch; for (short st = 0; st >= 0;) { ch = next(); switch (st) { case 0: // first '-' of the comment open if (ch == '-') st = 1; else panic(FAULT); break; case 1: // secind '-' of the comment open if (ch == '-') st = 2; else panic(FAULT); break; case 2: // skip the comment body if (ch == '-') st = 3; break; case 3: // second '-' of the comment close st = (ch == '-')? (short)4: (short)2; break; case 4: // '>' of the comment close if (ch == '>') st = -1; else panic(FAULT); break; default: panic(FAULT); } } } /** * Parses a processing instruction. * * @exception SAXException * @exception IOException */ private void pi() throws SAXException, IOException { char ch; String str = null; mBuffIdx = -1; for (short st = 0; st >= 0;) { ch = next(); switch (st) { case 0: // read the PI name switch (chtyp(ch)) { case 'a': case 'A': case '_': case 'X': back(); str = name(false); st = 1; break; case ' ': str = ""; st = 2; break; default: panic(FAULT); } break; case 1: // skip spaces after the PI name if (chtyp(ch) != ' ') { back(); if (mXml.name.equals(str.toLowerCase()) == true) { // This is the xml text declaration panic(FAULT); } else { // This is processing instruction if (mSt == 0) // the begining of the document mSt = 1; // misc before DTD st = 2; } mBuffIdx = -1; } break; case 2: // accumulate the PI body if (ch == '?') st = 3; else bappend(ch); break; case 3: // end of the PI body if (ch == '>') { // PI has been read. mHand.processingInstruction( str, new String(mBuff, 0, mBuffIdx + 1)); st = -1; } else { bappend('?'); bappend(ch); st = 2; } break; default: panic(FAULT); } } } /** * Parses a character data. * * @exception SAXException * @exception IOException */ private void cdat() throws SAXException, IOException { char ch; mBuffIdx = -1; for (short st = 0; st >= 0;) { ch = next(); switch (st) { case 0: // the first '[' of the CDATA open if (ch == '[') st = 1; else panic(FAULT); break; case 1: // read "CDATA" if (chtyp(ch) == 'A') { bappend(ch); } else { if ("CDATA".equals( new String(mBuff, 0, mBuffIdx + 1)) != true) panic(FAULT); back(); st = 2; } break; case 2: // the second '[' of the CDATA open if (ch != '[') panic(FAULT); mBuffIdx = -1; st = 3; break; case 3: // read data before the first ']' if (ch != ']') bappend(ch); else st = 4; break; case 4: // read the second ']' or continue to read the data if (ch != ']') { bappend(']'); bappend(ch); st = 3; } else { st = 5; } break; case 5: // read '>' or continue to read the data if (ch != '>') { bappend(']'); bappend(']'); bappend(ch); st = 3; } else { bflash(); st = -1; } break; default: panic(FAULT); } } } /** * Reads a xml name. * * The xml name must conform "Namespaces in XML" specification. Therefore * the ':' character is not allowed in the name. This method should be * used for PI and entity names which may not have a namespace according * to the specification mentioned above. * * @param ns The true value turns namespace conformance on. * @return The name has been read. * @exception SAXException When incorrect character appear in the name. * @exception IOException */ private String name(boolean ns) throws SAXException, IOException { mBuffIdx = -1; bname(ns); return new String(mBuff, 1, mBuffIdx); } /** * Reads a qualified xml name. * * The characters of a qualified name is an array of characters. The * first (chars[0]) character is the index of the colon character which * separates the prefix from the local name. If the index is zero, the * name does not contain separator or the parser works in the namespace * unaware mode. The length of qualified name is the length of the array * minus one.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -