📄 xmlparser.java
字号:
package org.kxml.parser;import java.io.*;import java.util.*;import org.kxml.*;import org.kxml.io.*;/** A simple, pull based "Common XML" parser. Attention: This class has been renamed from DefaultParser for consitency with the org.kxml.io package. */public class XmlParser extends AbstractXmlParser { static final String UNEXPECTED_EOF = "Unexpected EOF"; LookAheadReader reader; boolean relaxed; Vector qNames = new Vector (); boolean immediateClose = false; StartTag current; /** The next event. May be null at startup. */ protected ParseEvent next; /** creates a new Parser based on the give reader */ class DefaultParserException extends ParseException { DefaultParserException (String msg, Exception chained) { super (msg, chained, XmlParser.this.reader.getLineNumber (), XmlParser.this.reader.getColumnNumber ()); } } public XmlParser (Reader reader) throws IOException { this.reader = new LookAheadReader (reader); } public String resolveCharacterEntity (String name) throws IOException { throw new DefaultParserException ("Undefined: &"+name+";", null); } /* precondition: <!- consumed */ ParseEvent parseComment () throws IOException { StringBuffer buf = new StringBuffer (); if (reader.read () != '-') throw new DefaultParserException ("'-' expected", null); int cnt; int lst; while (true) { buf.append (reader.readTo ('-')); if (reader.read () == -1) throw new DefaultParserException (UNEXPECTED_EOF, null); cnt = 0; do { lst = reader.read (); cnt++; // adds one more, but first is not cnted } while (lst == '-'); if (lst == '>' && cnt >= 2) break; while (cnt-- > 0) buf.append ('-'); buf.append ((char) lst); } while (cnt-- > 2) buf.append ('-'); return new ParseEvent (Xml.COMMENT, buf.toString ()); } /* precondition: <! consumed */ ParseEvent parseDoctype () throws IOException { StringBuffer buf = new StringBuffer (); int nesting = 1; while (true) { int i = reader.read (); switch (i) { case -1: throw new DefaultParserException (UNEXPECTED_EOF, null); case '<': nesting++; break; case '>': if ((--nesting) == 0) return new ParseEvent (Xml.DOCTYPE, buf.toString ()); break; } buf.append ((char) i); } } ParseEvent parseCData () throws IOException { if (!reader.readTo ('[').equals ("CDATA")) throw new DefaultParserException ("Invalid CDATA start!", null); reader.read (); // skip '[' StringBuffer buf = new StringBuffer (); int c0 = reader.read (); int c1 = reader.read (); while (true) { int c2 = reader.read (); if (c2 == -1) throw new DefaultParserException (UNEXPECTED_EOF, null); if (c0 == ']' && c1 == ']' && c2 == '>') break; buf.append (c0); c0 = c1; c1 = c2; } return new ParseEvent (Xml.TEXT, buf.toString ()); } /* precondition: </ consumed */ ParseEvent parseEndTag () throws IOException { String name = reader.readTo ('>').trim (); if (reader.read () != '>') throw new DefaultParserException ("'</" + name + "' not terminated by '>'", null); int last = qNames.size (); while (true) { if (last == 0) { if (relaxed) return new ParseEvent (Xml.END_DOCUMENT, null); throw new DefaultParserException ("tagstack empty parsing </"+name+">", null); } String qName = (String) qNames.elementAt (--last); qNames.removeElementAt (last); if (qName.equals (name)) break; if (!relaxed) throw new DefaultParserException ("StartTag <"+qName +"> does not match end tag </" + name + ">", null); if (qName.toLowerCase ().equals (name.toLowerCase ())) break; current = current.parent; } Tag result = new Tag (Xml.END_TAG, current, current.namespace, current.name); current = current.parent; return result; } /** precondition: <? consumed */ ParseEvent parsePI () throws IOException { StringBuffer buf = new StringBuffer (reader.readTo ('?')); reader.read (); // ? while (reader.peek () != '>') { buf.append ('?'); int r = reader.read (); if (r == -1) throw new DefaultParserException (UNEXPECTED_EOF, null); buf.append ((char) r); buf.append (reader.readTo ('?')); reader.read (); } reader.read (); // consume > return new ParseEvent (Xml.PROCESSING_INSTRUCTION, buf.toString ()); } StartTag parseStartTag () throws IOException { //current = new StartTag (current, reader, relaxed); //prefixMap = parent == null ? new PrefixMap () : parent.prefixMap; String qname = reader.readTo ("/> \t\n\r"); //System.out.println ("name: ("+name+")"); Vector attributes = new Vector (); immediateClose = false; while (true) { reader.skipWhitespace (); int c = reader.peek (); if (c == '/') { immediateClose = true; reader.read (); reader.skipWhitespace (); if (reader.read () != '>') throw new ParseException ("illegal element termination", null, reader.getLineNumber (), reader.getColumnNumber ()); break; } if (c == '>') { reader.read (); break; } if (c == -1) throw new ParseException (UNEXPECTED_EOF, null, reader.getLineNumber (), reader.getColumnNumber ()); String attrName = reader.readTo ("=> "); while (attrName.length () > 0 && attrName.charAt (attrName.length () - 1) <= ' ') attrName = attrName.substring (0, attrName.length ()-1); if (attrName.length() == 0) throw new ParseException ("null attribute name found", null, reader.getLineNumber(), reader.getColumnNumber()); reader.skipWhitespace (); if (reader.read () != '=') throw new ParseException ("Attribute name "+attrName +"must be followed by '='!", null, reader.getLineNumber (), reader.getColumnNumber ()); reader.skipWhitespace (); int delimiter = reader.read (); if (delimiter != '\'' && delimiter != '"') { if (!relaxed) throw new ParseException ("<" + qname + ">: invalid delimiter: " + (char) delimiter, null, reader.getLineNumber (), reader.getColumnNumber ()); delimiter = ' '; } StringBuffer buf = new StringBuffer (); readText (buf, (char) delimiter); attributes.addElement (new Attribute (null, attrName, buf.toString ())); if (delimiter != ' ') reader.read (); // skip endquote } try { current = new StartTag (current, Xml.NO_NAMESPACE, qname, attributes, immediateClose, processNamespaces); } catch (Exception e) { throw new DefaultParserException (e.toString (), e); } //System.out.println ("tag: ("+next+")"); if (!immediateClose) qNames.addElement (qname); return current; } int readText (StringBuffer buf, char delimiter) throws IOException { int type = Xml.WHITESPACE; int nextChar; while (true) { nextChar = reader.peek (); if (nextChar == -1 || nextChar == delimiter || (delimiter == ' ' && (nextChar == '>' || nextChar < ' '))) break; reader.read (); if (nextChar == '&') { String code = reader.readTo (';'); reader.read (); if (code.charAt (0) == '#') { nextChar = (code.charAt (1) == 'x' ? Integer.parseInt (code.substring (2), 16) : Integer.parseInt (code.substring (1))); if (nextChar > ' ') type = Xml.TEXT; buf.append ((char) nextChar); } else { if (code.equals ("lt")) buf.append ('<'); else if (code.equals ("gt")) buf.append ('>'); else if (code.equals ("apos")) buf.append ('\''); else if (code.equals ("quot")) buf.append ('"'); else if (code.equals ("amp")) buf.append ('&'); else buf.append (resolveCharacterEntity (code)); type = Xml.TEXT; } } else { if (nextChar > ' ') type = Xml.TEXT; buf.append ((char) nextChar); } } return type; } /** precondition: < consumed */ ParseEvent parseSpecial () throws IOException { switch (reader.peek ()) { case -1: throw new DefaultParserException (UNEXPECTED_EOF, null); case '!': reader.read (); switch (reader.peek ()) { case '-': reader.read (); return parseComment (); case '[': reader.read (); return parseCData (); default: return parseDoctype (); } case '?': reader.read (); return parsePI (); case '/': reader.read (); return parseEndTag (); default: return parseStartTag (); } } public ParseEvent read () throws IOException{ if (next == null) peek (); ParseEvent result = next; next = null; return result; } public ParseEvent peek () throws IOException { if (next == null) { if (immediateClose) { next = new Tag (Xml.END_TAG, current, current.namespace, current.name); current = current.getParent (); immediateClose = false; } else { switch (reader.peek ()) { case '<': reader.read (); next = parseSpecial (); break; case -1: if (current != null && !relaxed) throw new DefaultParserException ("End tag missing for: "+current, null); next = new ParseEvent (Xml.END_DOCUMENT, null); break; default: { StringBuffer buf = new StringBuffer (); int type = readText (buf, '<'); next = new ParseEvent (type, buf.toString ()); } } } } return next; } /** default is false. Setting relaxed true allows CHTML parsing */ public void setRelaxed (boolean relaxed) { this.relaxed = relaxed; } public int getLineNumber () { return reader.getLineNumber (); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -