📄 parser.java
字号:
* * @param ns The true value turns namespace conformance on. * @return The characters of a qualified name. * @exception SAXException When incorrect character appear in the name. * @exception IOException */ private char[] qname(boolean ns) throws SAXException, IOException { mBuffIdx = -1; bname(ns); char chars[] = new char[mBuffIdx + 1]; System.arraycopy(mBuff, 0, chars, 0, mBuffIdx + 1); return chars; } /** * Reads the public or/and system identifiers. * * @param inp The input object. * @exception SAXException * @exception IOException */ private void pubsys(Input inp) throws SAXException, IOException { Pair pair = pubsys(' '); inp.pubid = pair.name; inp.sysid = pair.value; del(pair); } /** * Reads the public or/and system identifiers. * * @param flag The 'N' allows public id be without system id. * @return The public or/and system identifiers pair. * @exception SAXException * @exception IOException */ private Pair pubsys(char flag) throws SAXException, IOException { Pair ids = pair(null); String str = name(false); if ("PUBLIC".equals(str) == true) { bqstr('i'); // non-CDATA normalization [#4.2.2] ids.name = new String(mBuff, 1, mBuffIdx); switch (wsskip()) { case '\"': case '\'': bqstr(' '); ids.value = new String(mBuff, 1, mBuffIdx); break; default: if (flag != 'N') // [#4.7] panic(FAULT); ids.value = null; break; } return ids; } else if ("SYSTEM".equals(str) == true) { ids.name = null; bqstr(' '); ids.value = new String(mBuff, 1, mBuffIdx); return ids; } panic(FAULT); return null; } /** * Reads an attribute value. * * The grammar which this method can read is:<br /> * <code>eqstr := S "=" qstr</code><br /> * <code>qstr := S ("'" string "'") | * ('"' string '"')</code><br /> * This method resolves entities inside a string unless the parser * parses DTD. * * @param flag The '=' character forces the method * to accept the '=' character before quoted string. * @return The name has been read. * @exception SAXException * @exception IOException */ private String eqstr(char flag) throws SAXException, IOException { if (flag == '=') { wsskip(); if (next() != '=') panic(FAULT); } bqstr(flag); return new String(mBuff, 1, mBuffIdx); } /** * Resoves an entity. * * This method resolves built-in and character entity references. It is * also reports external entities to the application. * * @param flag The 'c' character forces the method * to report a skipped entity. * @exception SAXException * @exception IOException */ private void ent(char flag) throws SAXException, IOException { char ch; short idx = (short)(mBuffIdx + 1); Input inp = null; String str = null; mESt = 0x100; // reset the built-in entity recognizer bappend('&'); for (short st = 0; st >= 0;) { ch = next(); switch (st) { case 0: // the first character of the entity name case 1: // read built-in entity name switch (chtyp(ch)) { case 'd': case '.': case '-': if (st != 1) panic(FAULT); case 'a': case 'A': case '_': case 'X': bappend(ch); eappend(ch); st = 1; break; case ':': if (mIsNSAware != false) panic(FAULT); bappend(ch); eappend(ch); st = 1; break; case ';': if (mESt < 0x100) { // The entity is a built-in entity mBuffIdx = (short)(idx - 1); bappend(mESt); st = -1; break; } else if (mSt == 2) { // In DTD entity declaration has to resolve character // entities and include "as is" others. [#4.4.7] bappend(';'); st = -1; break; } // Convert an entity name to a string str = new String(mBuff, idx + 1, mBuffIdx - idx); inp = (Input)mEnt.get(str); // Restore the buffer offset mBuffIdx = (short)(idx - 1); if (inp != null) { if (inp.chars == null) { // External entity InputSource is = mHand.resolveEntity(inp.pubid, inp.sysid); if (is != null) { push(new Input(BUFFSIZE_READER)); setinp(is); mInp.pubid = inp.pubid; mInp.sysid = inp.sysid; } else { // Unresolved external entity bflash(); if (flag != 'c') panic(FAULT); // unknown entity within marckup mHand.skippedEntity(str); } } else { // Internal entity push(inp); } } else { // Unknown or general unparsed entity bflash(); if (flag != 'c') panic(FAULT); // unknown entity within marckup mHand.skippedEntity(str); } st = -1; break; case '#': if (st != 0) panic(FAULT); st = 2; break; default: panic(FAULT); } break; case 2: // read character entity switch (chtyp(ch)) { case 'd': bappend(ch); break; case ';': // Convert the character entity to a character try { ch = (char)Short.parseShort( new String(mBuff, idx + 1, mBuffIdx - idx), 10); } catch (NumberFormatException nfe) { panic(FAULT); } // Restore the buffer offset mBuffIdx = (short)(idx - 1); bappend(ch); st = -1; break; case 'a': // If the entity buffer is empty and ch == 'x' if ((mBuffIdx == idx) && (ch == 'x')) { st = 3; break; } default: panic(FAULT); } break; case 3: // read hex character entity switch (chtyp(ch)) { case 'A': case 'a': case 'd': bappend(ch); break; case ';': // Convert the character entity to a character try { ch = (char)Short.parseShort( new String(mBuff, idx + 1, mBuffIdx - idx), 16); } catch (NumberFormatException nfe) { panic(FAULT); } // Restore the buffer offset mBuffIdx = (short)(idx - 1); bappend(ch); st = -1; break; default: panic(FAULT); } break; default: panic(FAULT); } } } /** * Resoves a parameter entity. * * This method resolves a parameter entity references. It is also reports * external entities to the application. * * @param flag The '-' instruct the method to do not set up surrounding * spaces [#4.4.8]. * @exception SAXException * @exception IOException */ private void pent(char flag) throws SAXException, IOException { char ch; short idx = (short)(mBuffIdx + 1); Input inp = null; String str = null; bappend('%'); if (mSt != 2) // the DTD internal subset return; // Not Recognized [#4.4.1] // Read entity name bname(false); str = new String(mBuff, idx + 2, mBuffIdx - idx - 1); if (next() != ';') panic(FAULT); inp = (Input)mPEnt.get(str); // Restore the buffer offset mBuffIdx = (short)(idx - 1); if (inp != null) { if (inp.chars == null) { // External parameter entity InputSource is = mHand.resolveEntity(inp.pubid, inp.sysid); if (is != null) { if (flag != '-') bappend(' '); // tail space push(new Input(BUFFSIZE_READER)); // BUG: there is no leading space! [#4.4.8] setinp(is); mInp.pubid = inp.pubid; mInp.sysid = inp.sysid; } else { // Unresolved external parameter entity mHand.skippedEntity("%" + str); } } else { // Internal parameter entity if (flag == '-') { // No surrounding spaces inp.chIdx = 1; } else { // Insert surrounding spaces bappend(' '); // tail space inp.chIdx = 0; } push(inp); } } else { // Unknown parameter entity mHand.skippedEntity("%" + str); } } /** * Recognizes and handles a namespace declaration. * * This method identifies a type of namespace declaration if any and * puts new mapping on top of prefix stack. * * @param name The attribute qualified name (<code>name.value</code> is a * <code>String</code> object which represents the attribute prefix). * @param value The attribute value. * @return <code>true</code> if a namespace declaration is recognized. */ private boolean isdecl(Pair name, String value) { if (name.chars[0] == 0) { if ("xmlns".equals(name.name) == true) { // New default namespace declaration mPref = pair(mPref); mPref.value = value; mPref.name = ""; mPref.chars = NONS; return true; } } else { if (name.eqpref(XMLNS) == true) { // New prefix declaration int len = name.name.length(); mPref = pair(mPref); mPref.value = value; mPref.name = name.name; mPref.chars = new char[len + 1]; mPref.chars[0] = (char)(len + 1); name.name.getChars(0, len, mPref.chars, 1); return true; } } return false; } /** * Resolves a prefix. * * @return The namespace assigned to the prefix. * @exception SAXException When mapping for specified prefix is not found. */ private String rslv(char[] qname) throws SAXException { for (Pair pref = mPref; pref != null; pref = pref.next) { if (pref.eqpref(qname) == true) return pref.value; } panic(FAULT); return null; } /** * Skips xml white space characters. * * This method skips white space characters (' ', '\t', '\n', '\r') and * looks ahead not white space character. * * @return The first not white space look ahead character. * @exception SAXException When End Of Stream character typed. * @exception IOException */ private char wsskip() throws SAXException, IOException { char ch; while (true) { ch = next(); switch (ch) { case ' ': case '\t': case '\r': case '\n': continue; case EOS: panic(FAULT); default: back(); return ch; } } } /** * Notifies the handler about fatal parsing error. * * @param msg The problem description message. */ private void panic(String msg) throws SAXException { mHand.fatalError(new SAXParseException(msg, this)); } /** * Reads a qualified xml name. * * This is low level routine which leaves a qName in the buffer. * 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. * * @param ns The true value turns namespace conformance on. * @exception SAXException When incorrect character appear in the name. * @exception IOException */ private void bname(boolean ns) throws SAXException, IOException { char ch; char pos = (char)(mBuffIdx + 1); char idx = pos; short st = (short)((ns == true)? 0: 2); bappend((char)0); // default offset to the colon char while (st >= 0) { ch = next(); switch (st) { case 0: // read the first char of the prefix case 2: // read the first char of the suffix switch (chtyp(ch)) { case 'a': case 'A': case '_': case 'X': bappend(ch); st++; // (st == 0)? 1: 3; break; case ':': back(); st++; // (st == 0)? 1: 3; break; default: panic(FAULT); } break; case 1: // read the prefix case 3: // read the suffix switch (chtyp(ch)) { case 'a': case 'A': case 'd': case '.': case '-': case '_': case 'X': bappend(ch); break; case ':': bappend(ch); if (ns == true) { if (idx != pos) panic(FAULT); // it must be only one colon idx = (char)mBuffIdx; if (st == 1) st = 2; } break; default: back(); mBuff[pos] = idx; return; } break; default: panic(FAULT); } } } /** * Reads a nmtoken. * * This is low level routine which leaves a nmtoken in the buffer. * * @exception SAXException When incorrect character appear in the name. * @exception IOException */ private void bntok() throws SAXException, IOException { char ch; mBuffIdx = -1; bappend((char)0); // default offset to the colon char while (true) { ch = next(); switch (chtyp(ch)) { case 'a': case 'A': case 'd': case '.': case ':': case '-': case '_': case 'X': bappend(ch); break; default: back(); return; } } } /** * Recognizes a keyword. * * This is low level routine which recognizes one of keywords in the buffer. * Keyword Id * ID - i * IDREF - r * IDREFS - R * ENTITY - n * ENTITIES - N * NMTOKEN - t * NMTOKENS - T * ELEMENT - e * ATTLIST - a * NOTATION - o * CDATA - c * REQUIRED - Q * IMPLIED - I * FIXED - F * * @return an id of a keyword or '?'. * @exception SAXException When incorrect character appear in the name. * @exception IOException */ private char bkeyword() throws SAXException, IOException { String str = new String(mBuff, 1, mBuffIdx); switch (str.length()) { case 2: // ID return ("ID".equals(str) == true)? 'i': '?'; case 5: // IDREF, CDATA, FIXED switch (mBuff[1]) { case 'I': return ("IDREF".equals(str) == true)? 'r': '?'; case 'C':
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -