📄 xmlparser.java
字号:
* @return true if whitespace characters were read, false otherwise */ private boolean tryWhitespace() throws IOException, XMLStreamException { boolean white; boolean ret = false; do { mark(1); int c = readCh(); while (c == -1 && inputStack.size() > 1) { popInput(); c = readCh(); } white = (c == 0x20 || c == 0x09 || c == 0x0a || c == 0x0d); if (white) ret = true; } while (white); reset(); return ret; } /** * Skip over any whitespace characters. */ private void skipWhitespace() throws IOException, XMLStreamException { boolean white; do { mark(1); int c = readCh(); while (c == -1 && inputStack.size() > 1) { popInput(); c = readCh(); } white = (c == 0x20 || c == 0x09 || c == 0x0a || c == 0x0d); } while (white); reset(); } /** * Try to read as many whitespace characters as are available. * @exception XMLStreamException if no whitespace characters were seen */ private void requireWhitespace() throws IOException, XMLStreamException { if (!tryWhitespace()) error("whitespace required"); } /** * Returns the current base URI for resolving external entities. */ String getXMLBase() { if (baseAware) { for (Iterator i = bases.iterator(); i.hasNext(); ) { String base = (String) i.next(); if (base != null) return base; } } return input.systemId; } /** * Push the specified text input source. */ private void pushInput(String name, String text, boolean report, boolean normalize) throws IOException, XMLStreamException { // Check for recursion if (name != null && !"".equals(name)) { for (Iterator i = inputStack.iterator(); i.hasNext(); ) { Input ctx = (Input) i.next(); if (name.equals(ctx.name)) error("entities may not be self-recursive", name); } } else report = false; pushInput(new Input(null, new StringReader(text), input.publicId, input.systemId, name, input.inputEncoding, report, normalize)); } /** * Push the specified external input source. */ private void pushInput(String name, ExternalIds ids, boolean report, boolean normalize) throws IOException, XMLStreamException { if (!externalEntities) return; String url = absolutize(input.systemId, ids.systemId); // Check for recursion for (Iterator i = inputStack.iterator(); i.hasNext(); ) { Input ctx = (Input) i.next(); if (url.equals(ctx.systemId)) error("entities may not be self-recursive", url); if (name != null && !"".equals(name) && name.equals(ctx.name)) error("entities may not be self-recursive", name); } if (name == null || "".equals(name)) report = false; InputStream in = null; if (resolver != null) { Object obj = resolver.resolveEntity(ids.publicId, url, getXMLBase(), null); if (obj instanceof InputStream) in = (InputStream) obj; } if (in == null) in = resolve(url); if (in == null) error("unable to resolve external entity", (ids.systemId != null) ? ids.systemId : ids.publicId); pushInput(new Input(in, null, ids.publicId, url, name, null, report, normalize)); input.init(); if (tryRead(TEST_XML_DECL)) readTextDecl(); input.finalizeEncoding(); } /** * Push the specified input source (general entity) onto the input stack. */ private void pushInput(Input input) { if (input.report) startEntityStack.addFirst(input.name); inputStack.addLast(input); if (this.input != null) input.xml11 = this.input.xml11; this.input = input; } /** * "Absolutize" a URL. This resolves a relative URL into an absolute one. * @param base the current base URL * @param href the (absolute or relative) URL to resolve */ public static String absolutize(String base, String href) throws MalformedURLException { if (href == null) return null; int ci = href.indexOf(':'); if (ci > 1 && isURLScheme(href.substring(0, ci))) { // href is absolute already return href; } if (base == null) base = ""; else { int i = base.lastIndexOf('/'); if (i != -1) base = base.substring(0, i + 1); else base = ""; } if ("".equals(base)) { // assume file URL relative to current directory base = System.getProperty("user.dir"); if (base.charAt(0) == '/') base = base.substring(1); base = "file:///" + base.replace(File.separatorChar, '/'); if (!base.endsWith("/")) base += "/"; } return new URL(new URL(base), href).toString(); } /** * Indicates whether the specified characters match the scheme portion of * a URL. * @see RFC 1738 section 2.1 */ private static boolean isURLScheme(String text) { int len = text.length(); for (int i = 0; i < len; i++) { char c = text.charAt(i); if (c == '+' || c == '.' || c == '-') continue; if (c < 65 || (c > 90 && c < 97) || c > 122) return false; } return true; } /** * Returns an input stream for the given URL. */ static InputStream resolve(String url) throws IOException { try { return new URL(url).openStream(); } catch (MalformedURLException e) { return null; } catch (IOException e) { IOException e2 = new IOException("error resolving " + url); e2.initCause(e); throw e2; } } /** * Pops the current input source (general entity) off the stack. */ private void popInput() { Input old = (Input) inputStack.removeLast(); if (old.report) endEntityStack.addFirst(old.name); input = (Input) inputStack.getLast(); } /** * Parse an entity text declaration. */ private void readTextDecl() throws IOException, XMLStreamException { final int flags = LIT_DISABLE_CREF | LIT_DISABLE_PE | LIT_DISABLE_EREF; requireWhitespace(); if (tryRead("version")) { readEq(); String v = readLiteral(flags, false); if ("1.0".equals(v)) input.xml11 = false; else if ("1.1".equals(v)) { Input i1 = (Input) inputStack.getFirst(); if (!i1.xml11) error("external entity specifies later version number"); input.xml11 = true; } else throw new XMLStreamException("illegal XML version: " + v); requireWhitespace(); } require("encoding"); readEq(); String enc = readLiteral(flags, false); skipWhitespace(); require("?>"); input.setInputEncoding(enc); } /** * Parse the XML declaration. */ private void readXMLDecl() throws IOException, XMLStreamException { final int flags = LIT_DISABLE_CREF | LIT_DISABLE_PE | LIT_DISABLE_EREF; requireWhitespace(); require("version"); readEq(); xmlVersion = readLiteral(flags, false); if ("1.0".equals(xmlVersion)) input.xml11 = false; else if ("1.1".equals(xmlVersion)) input.xml11 = true; else throw new XMLStreamException("illegal XML version: " + xmlVersion); boolean white = tryWhitespace(); if (tryRead("encoding")) { if (!white) error("whitespace required before 'encoding='"); readEq(); xmlEncoding = readLiteral(flags, false); white = tryWhitespace(); } if (tryRead("standalone")) { if (!white) error("whitespace required before 'standalone='"); readEq(); String standalone = readLiteral(flags, false); if ("yes".equals(standalone)) xmlStandalone = Boolean.TRUE; else if ("no".equals(standalone)) xmlStandalone = Boolean.FALSE; else error("standalone flag must be 'yes' or 'no'", standalone); } skipWhitespace(); require("?>"); if (xmlEncoding != null) input.setInputEncoding(xmlEncoding); } /** * Parse the DOCTYPE declaration. */ private void readDoctypeDecl() throws IOException, XMLStreamException { if (!supportDTD) error("parser was configured not to support DTDs"); requireWhitespace(); String rootName = readNmtoken(true); skipWhitespace(); ExternalIds ids = readExternalIds(false, true); doctype = this.new Doctype(rootName, ids.publicId, ids.systemId); // Parse internal subset first skipWhitespace(); if (tryRead('[')) { while (true) { expandPE = true; skipWhitespace(); expandPE = false; if (tryRead(']')) break; else readMarkupdecl(false); } } skipWhitespace(); require('>'); // Parse external subset if (ids.systemId != null && externalEntities) { pushInput("", ">", false, false); pushInput("[dtd]", ids, true, true); // loop until we get back to ">" while (true) { expandPE = true; skipWhitespace(); expandPE = false; mark(1); int c = readCh(); if (c == 0x3e) // '>' break; else if (c == -1) popInput(); else { reset(); expandPE = true; readMarkupdecl(true); expandPE = true; } } if (inputStack.size() != 2) error("external subset has unmatched '>'"); popInput(); } checkDoctype(); if (validating) validateDoctype(); // Make rootName available for reading buf.setLength(0); buf.append(rootName); } /** * Checks the well-formedness of the DTD. */ private void checkDoctype() throws XMLStreamException { // TODO check entity recursion } /** * Parse the markupdecl production. */ private void readMarkupdecl(boolean inExternalSubset) throws IOException, XMLStreamException { boolean saved = expandPE; mark(1); require('<'); reset(); expandPE = false; if (tryRead(TEST_ELEMENT_DECL)) { expandPE = saved; readElementDecl(); } else if (tryRead(TEST_ATTLIST_DECL)) { expandPE = saved; readAttlistDecl(); } else if (tryRead(TEST_ENTITY_DECL)) { expandPE = saved; readEntityDecl(inExternalSubset); } else if (tryRead(TEST_NOTATION_DECL)) { expandPE = saved; readNotationDecl(inExternalSubset); } else if (tryRead(TEST_PI)) { readPI(true); expandPE = saved; } else if (tryRead(TEST_COMMENT)) { readComment(true); expandPE = saved; } else if (tryRead("<![")) { // conditional section expandPE = saved; if (inputStack.size() < 2) error("conditional sections illegal in internal subset"); skipWhitespace(); if (tryRead("INCLUDE")) { skipWhitespace(); require('['); skipWhitespace(); while (!tryRead("]]>")) { readMarkupdecl(inExternalSubset);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -