📄 kxmlparser.java
字号:
/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */// Contributors: Paul Hackenberger (unterminated entity handling in relaxed mode)package org.kxml2.io;import java.io.*;import java.util.*;import org.xmlpull.v1.*;/** A simple, pull based XML parser. This classe replaces the kXML 1 XmlParser class and the corresponding event classes. */public class KXmlParser implements XmlPullParser { private Object location; static final private String UNEXPECTED_EOF = "Unexpected EOF"; static final private String ILLEGAL_TYPE = "Wrong event type"; static final private int LEGACY = 999; static final private int XML_DECL = 998; // general private String version; private Boolean standalone; private boolean processNsp; private boolean relaxed; private Hashtable entityMap; private int depth; private String[] elementStack = new String[16]; private String[] nspStack = new String[8]; private int[] nspCounts = new int[4]; // source private Reader reader; private String encoding; private char[] srcBuf; private int srcPos; private int srcCount; private int line; private int column; // txtbuffer private char[] txtBuf = new char[128]; private int txtPos; // Event-related private int type; //private String text; private boolean isWhitespace; private String namespace; private String prefix; private String name; private boolean degenerated; private int attributeCount; private String[] attributes = new String[16]; private int stackMismatch = 0; private String error; /** * A separate peek buffer seems simpler than managing * wrap around in the first level read buffer */ private int[] peek = new int[2]; private int peekCount; private boolean wasCR; private boolean unresolved; private boolean token; public KXmlParser() { srcBuf = new char[Runtime.getRuntime().freeMemory() >= 1048576 ? 8192 : 128]; } private final boolean isProp(String n1, boolean prop, String n2) { if (!n1.startsWith("http://xmlpull.org/v1/doc/")) return false; if (prop) return n1.substring(42).equals(n2); else return n1.substring(40).equals(n2); } private final boolean adjustNsp() throws XmlPullParserException { boolean any = false; for (int i = 0; i < attributeCount << 2; i += 4) { // * 4 - 4; i >= 0; i -= 4) { String attrName = attributes[i + 2]; int cut = attrName.indexOf(':'); String prefix; if (cut != -1) { prefix = attrName.substring(0, cut); attrName = attrName.substring(cut + 1); } else if (attrName.equals("xmlns")) { prefix = attrName; attrName = null; } else continue; if (!prefix.equals("xmlns")) { any = true; } else { int j = (nspCounts[depth]++) << 1; nspStack = ensureCapacity(nspStack, j + 2); nspStack[j] = attrName; nspStack[j + 1] = attributes[i + 3]; if (attrName != null && attributes[i + 3].equals("")) error("illegal empty namespace"); // prefixMap = new PrefixMap (prefixMap, attrName, attr.getValue ()); //System.out.println (prefixMap); System.arraycopy( attributes, i + 4, attributes, i, ((--attributeCount) << 2) - i); i -= 4; } } if (any) { for (int i = (attributeCount << 2) - 4; i >= 0; i -= 4) { String attrName = attributes[i + 2]; int cut = attrName.indexOf(':'); if (cut == 0 && !relaxed) throw new RuntimeException( "illegal attribute name: " + attrName + " at " + this); else if (cut != -1) { String attrPrefix = attrName.substring(0, cut); attrName = attrName.substring(cut + 1); String attrNs = getNamespace(attrPrefix); if (attrNs == null && !relaxed) throw new RuntimeException( "Undefined Prefix: " + attrPrefix + " in " + this); attributes[i] = attrNs; attributes[i + 1] = attrPrefix; attributes[i + 2] = attrName; /* if (!relaxed) { for (int j = (attributeCount << 2) - 4; j > i; j -= 4) if (attrName.equals(attributes[j + 2]) && attrNs.equals(attributes[j])) exception( "Duplicate Attribute: {" + attrNs + "}" + attrName); } */ } } } int cut = name.indexOf(':'); if (cut == 0) error("illegal tag name: " + name); if (cut != -1) { prefix = name.substring(0, cut); name = name.substring(cut + 1); } this.namespace = getNamespace(prefix); if (this.namespace == null) { if (prefix != null) error("undefined prefix: " + prefix); this.namespace = NO_NAMESPACE; } return any; } private final String[] ensureCapacity(String[] arr, int required) { if (arr.length >= required) return arr; String[] bigger = new String[required + 16]; System.arraycopy(arr, 0, bigger, 0, arr.length); return bigger; } private final void error(String desc) throws XmlPullParserException { if (relaxed) { if (error == null) error = "ERR: " + desc; } else exception(desc); } private final void exception(String desc) throws XmlPullParserException { throw new XmlPullParserException( desc.length() < 100 ? desc : desc.substring(0, 100) + "\n", this, null); } /** * common base for next and nextToken. Clears the state, except from * txtPos and whitespace. Does not set the type variable */ private final void nextImpl() throws IOException, XmlPullParserException { if (reader == null) exception("No Input specified"); if (type == END_TAG) depth--; while (true) { attributeCount = -1; // degenerated needs to be handled before error because of possible // processor expectations(!) if (degenerated) { degenerated = false; type = END_TAG; return; } if (error != null) { for (int i = 0; i < error.length(); i++) push(error.charAt(i)); // text = error; error = null; type = COMMENT; return; } if (relaxed && (stackMismatch > 0 || (peek(0) == -1 && depth > 0))) { int sp = (depth - 1) << 2; type = END_TAG; namespace = elementStack[sp]; prefix = elementStack[sp + 1]; name = elementStack[sp + 2]; if (stackMismatch != 1) error = "missing end tag /" + name + " inserted"; if (stackMismatch > 0) stackMismatch--; return; } prefix = null; name = null; namespace = null; // text = null; type = peekType(); switch (type) { case ENTITY_REF : pushEntity(); return; case START_TAG : parseStartTag(false); return; case END_TAG : parseEndTag(); return; case END_DOCUMENT : return; case TEXT : pushText('<', !token); if (depth == 0) { if (isWhitespace) type = IGNORABLE_WHITESPACE; // make exception switchable for instances.chg... !!!! // else // exception ("text '"+getText ()+"' not allowed outside root element"); } return; default : type = parseLegacy(token); if (type != XML_DECL) return; } } } private final int parseLegacy(boolean push) throws IOException, XmlPullParserException { String req = ""; int term; int result; int prev = 0; read(); // < int c = read(); if (c == '?') { if ((peek(0) == 'x' || peek(0) == 'X') && (peek(1) == 'm' || peek(1) == 'M')) { if (push) { push(peek(0)); push(peek(1)); } read(); read(); if ((peek(0) == 'l' || peek(0) == 'L') && peek(1) <= ' ') { if (line != 1 || column > 4) error("PI must not start with xml"); parseStartTag(true); if (attributeCount < 1 || !"version".equals(attributes[2])) error("version expected"); version = attributes[3]; int pos = 1; if (pos < attributeCount && "encoding".equals(attributes[2 + 4])) { encoding = attributes[3 + 4]; pos++; } if (pos < attributeCount && "standalone".equals(attributes[4 * pos + 2])) { String st = attributes[3 + 4 * pos]; if ("yes".equals(st)) standalone = new Boolean(true); else if ("no".equals(st)) standalone = new Boolean(false); else error("illegal standalone value: " + st); pos++; } if (pos != attributeCount) error("illegal xmldecl"); isWhitespace = true; txtPos = 0; return XML_DECL; } } /* int c0 = read (); int c1 = read (); int */ term = '?'; result = PROCESSING_INSTRUCTION; } else if (c == '!') { if (peek(0) == '-') { result = COMMENT; req = "--"; term = '-'; } else if (peek(0) == '[') { result = CDSECT; req = "[CDATA["; term = ']'; push = true; } else { result = DOCDECL; req = "DOCTYPE"; term = -1; } } else { error("illegal: <" + c); return COMMENT; } for (int i = 0; i < req.length(); i++) read(req.charAt(i)); if (result == DOCDECL) parseDoctype(push); else { while (true) { c = read(); if (c == -1){ error(UNEXPECTED_EOF); return COMMENT; } if (push) push(c); if ((term == '?' || c == term) && peek(0) == term && peek(1) == '>') break; prev = c; } if (term == '-' && prev == '-') error("illegal comment delimiter: --->"); read(); read(); if (push && term != '?') txtPos--; } return result; } /** precondition: <! consumed */ private final void parseDoctype(boolean push) throws IOException, XmlPullParserException { int nesting = 1; boolean quoted = false; // read();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -