xmlparser.java
来自「RESIN 3.2 最新源码」· Java 代码 · 共 2,651 行 · 第 1/5 页
JAVA
2,651 行
if (ch == '[') ch = parseDoctypeDecl(_dtd); ch = skipWhitespace(ch); _inDtd = false; if (ch != '>') throw error(L.l("expected `>' in <!DOCTYPE at {0}", badChar(ch))); } /** * Parses the DTD. * * <pre> * dtd-item ::= <!ELEMENT ... | * <!ATTLIST ... | * <!NOTATION ... | * <!ENTITY ... | * <!-- comment | * <? pi | * %pe-ref; * </pre> * * @return the next character. */ private int parseDoctypeDecl(QDocumentType doctype) throws IOException, SAXException { _hasDoctype = true; int ch = 0; for (ch = skipWhitespace(read()); ch >= 0 && ch != ']'; ch = skipWhitespace(read())) { if (ch == '<') { if ((ch = read()) == '!') { if (XmlChar.isNameStart(ch = read())) { ch = _reader.parseName(_text, ch); String name = _text.toString(); if (name.equals("ELEMENT")) parseElementDecl(doctype); else if (name.equals("ATTLIST")) parseAttlistDecl(doctype); else if (name.equals("NOTATION")) parseNotationDecl(doctype); else if (name.equals("ENTITY")) parseEntityDecl(doctype); else throw error("unknown declaration `" + name + "'"); } else if (ch == '-') parseComment(); else if (ch == '[') { ch = _reader.parseName(_text, read()); String name = _text.toString(); if (name.equals("IGNORE")) { parseIgnore(); } else if (name.equals("INCLUDE")) { parseIgnore(); } else throw error("unknown declaration `" + name + "'"); } } else if (ch == '?') { parsePI(); } else throw error(L.l("expected markup at {0}", badChar(ch))); } else if (ch == '%') { ch = _reader.parseName(_buf, read()); if (ch != ';') throw error(L.l("`%{0};' expects `;' at {1}. Parameter entities have a `%name;' syntax.", _buf, badChar(ch))); addPEReference(_text, _buf.toString()); } else { throw error(L.l("expected '<' at {0}", badChar(ch))); } _text.clear(); } _text.clear(); return read(); } /** * Parses an element. * * @param ch the current character */ private void parseElement(int ch) throws IOException, SAXException { ch = _reader.parseName(_eltName, ch); NamespaceMap oldNamespace = _namespaceMap; if (ch != '>' && ch != '/') ch = parseAttributes(ch, true); else _attributes.clear(); QName qname = _policy.getName(_eltName); if (_isValidating && _dtd != null) { QElementDef elementDef = _dtd.getElement(qname.getName()); if (elementDef != null) elementDef.fillDefaults(_attributes); } if (ch == '/') { // empty tag: <foo/> if ((ch = _reader.read()) == '>') { addElement(qname, true, _attributes, oldNamespace); } // short tag: </foo/some text here/> else { addElement(qname, false, _attributes, oldNamespace); parseNode(ch, true); } } else if (ch == '>') { addElement(qname, false, _attributes, oldNamespace); } else throw error(L.l("unexpected character {0} while parsing `{1}' attributes. Expected an attribute name or `>' or `/>'. XML element syntax is:\n <name attr-1=\"value-1\" ... attr-n=\"value-n\">", badChar(ch), qname.getName())); } /** * Parses the attributes in an element. * * @param ch the next character to reader.read. * * @return the next character to read. */ private int parseAttributes(int ch, boolean isElement) throws IOException, SAXException { ch = skipWhitespace(ch); _attributes.clear(); _attrNames.clear(); _attrValues.clear(); boolean hasWhitespace = true; while (ch != -1) { if (! XmlChar.isNameStart(ch)) { if (! _isJsp || ch != '<') break; ch = parseJspAttribute(isElement); continue; } if (! hasWhitespace) throw error(L.l("attributes must be separated by whitespace")); hasWhitespace = false; ch = _reader.parseName(_text, ch); if (! _text.startsWith("xmlns")) { } else { QName name; if (_isNamespaceAware && _contentHandler instanceof DOMBuilder) name = _policy.getNamespaceName(_text); else name = new QName(_text.toString(), null); String prefix; if (_text.length() > 5) { prefix = _text.substring(6); if (prefix.equals("")) throw error(L.l("'{0}' is an illegal namespace declaration.", _text)); } else { prefix = ""; } _text.clear(); ch = skipWhitespace(ch); if (ch != '=') throw error(L.l("xmlns: needs value at {0}", badChar(ch))); ch = skipWhitespace(_reader.read()); ch = parseValue(_text, ch, true); hasWhitespace = isWhitespace(ch); ch = skipWhitespace(ch); // topNamespaceNode = element; String uri = _text.toString(); if (_isXmlnsPrefix) { _namespaceMap = new NamespaceMap(_namespaceMap, prefix, uri); _policy.setNamespace(_namespaceMap); _contentHandler.startPrefixMapping(prefix, uri); } // needed for xml/032e vs xml/00ke if (isElement && _isXmlnsAttribute && _contentHandler instanceof DOMBuilder) { _attributes.add(name, uri); } continue; } String attrName = _text.toString(); _attrNames.add(attrName); _text.clear(); ch = skipWhitespace(ch); String value = null; if (ch == '=') { ch = skipWhitespace(_reader.read()); ch = parseValue(_text, ch, true); hasWhitespace = isWhitespace(ch); ch = skipWhitespace(ch); value = _text.toString(); } else if (_strictAttributes) { throw error(L.l("attribute `{0}' expects value at {1}. XML requires attributes to have explicit values.", attrName, badChar(ch))); } else { value = attrName; // xxx: conflict xsl/0432 hasWhitespace = true; } _attrValues.add(value); } int len = _attrNames.size(); for (int i = 0; i < len; i++) { String attrName = _attrNames.get(i); String value = _attrValues.get(i); _text.clear(); _text.append(attrName); QName name; if (_contentHandler instanceof DOMBuilder) name = _policy.getAttributeName(_eltName, _text, true); else name = _policy.getAttributeName(_eltName, _text); _attributes.add(name, value); } return ch; } /** * Special parser to handle the use of <%= as an attribute in JSP * files. Covers cases like the following: * * <pre> * <options> * <option name="foo" <%= test.isSelected("foo") %>/> * </options> * </pre> * * @param element the parent element * * @return the next character to read. */ private int parseJspAttribute(boolean isElement) throws IOException, XmlParseException { int ch = _reader.read(); if (ch != '%') throw error(L.l("unexpected char `{0}' in element", "%")); ch = _reader.read(); if (ch != '=') throw error(L.l("unexpected char `{0}' in element", "=")); _text.clear(); ch = _reader.read(); while (ch >= 0) { if (ch == '%') { ch = _reader.read(); if (ch == '>') { ch = _reader.read(); break; } _text.append((char) ch); } else { _text.append((char) ch); ch = _reader.read(); } } String value = _text.toString(); if (isElement) _attributes.add(JSP_ATTRIBUTE_NAME, value); return ch; } /** * Handle processing at a close tag. For strict XML, this will normally * just change the current node to its parent, but HTML has a more * complicated policy. */ private void closeTag(String endTagName) throws IOException, SAXException { while (_activeNode != null && _activeNode != DOC_NAME) { switch (_policy.elementCloseAction(this, _activeNode, endTagName)) { case Policy.POP: //if (dbg.canWrite()) // dbg.println("</" + activeNode.getNodeName() + ">"); popNode(); return; case Policy.POP_AND_LOOP: //if (dbg.canWrite()) // dbg.println("</" + activeNode.getNodeName() + ">"); popNode(); break; case Policy.IGNORE: return; default: throw new RuntimeException(); } } if (! _extraForgiving && endTagName != null && ! endTagName.equals("")) throw error(L.l("Unexpected end tag `</{0}>' at top-level. All open tags have already been closed.", endTagName)); } /** * Handles processing of the resin:include tag. */ private void handleResinInclude() throws IOException, SAXException { String filename = _attributes.getValue("path"); if (filename == null || filename.equals("")) filename = _attributes.getValue("href"); if (filename.equals("")) throw error(L.l("<resin:include> expects a `path' attribute.")); pushInclude(filename); } /** * Handles processing of the resin:include tag. */ private void handleResinIncludeDirectory() throws IOException, SAXException { String filename = _attributes.getValue("path"); if (filename == null || filename.equals("")) filename = _attributes.getValue("href"); String extension = _attributes.getValue("extension"); if (filename.equals("")) throw error(L.l("<resin:include> expects a `path' attribute.")); Path pwd; if (_searchPath != null) pwd = _searchPath; else pwd = Vfs.lookup(_systemId).getParent(); Path dir = pwd.lookup(filename); if (! dir.isDirectory()) throw error(L.l("`{0}' is not a directory for resin:include-directory. The href for resin:include-directory must refer to a directory.", dir.getNativePath())); String []list = dir.list(); Arrays.sort(list); for (int i = list.length - 1; i >= 0; i--) { if (list[i].startsWith(".") || extension != null && ! list[i].endsWith(extension)) continue; pushInclude(dir.lookup(list[i]).getPath()); } } private int parseNameToken(CharBuffer name, int ch) throws IOException, SAXException { name.clear(); if (! XmlChar.isNameChar(ch)) throw error(L.l("expected name at {0}", badChar(ch))); for (; XmlChar.isNameChar(ch); ch = _reader.read()) name.append((char) ch); return ch; } /** * Pop the top-level node */ private void popNode() throws SAXException { QName node = _activeNode; if (_activeNode != DOC_NAME) { String uri = _activeNode.getNamespaceURI(); String localName = _activeNode.getLocalName(); if (uri == null) { uri = ""; if (_isNamespaceAware) localName = _activeNode.getName(); else localName = ""; } _contentHandler.endElement(uri, localName, _activeNode.getName()); } if (_elementTop > 0) { _elementTop--; NamespaceMap oldMap = _namespaces[_elementTop]; popNamespaces(oldMap); _activeNode = _elementNames[_elementTop]; } if (_elementTop == 0) _activeNode = DOC_NAME; } public void pushNamespace(String prefix, String uri) { _namespaceMap = new NamespaceMap(_namespaceMap, prefix, uri); _policy.setNamespace(_namespaceMap); } private void popNamespaces(NamespaceMap oldMap) throws SAXException { for (; _namespaceMap != null && _namespaceMap != oldMap; _namespaceMap = _namespaceMap.next) { _contentHandler.endPrefixMapping(_namespaceMap.prefix); } _namespaceMap = oldMap; _policy.setNamespace(_namespaceMap); } private void appendText(String s) { if (_text.length() == 0) { _textFilename = getFilename(); _textLine = getLine(); } _text.append(s); } /** * Parses an entity reference: * * <pre> * er ::= &#d+; * ::= &name; * </pre> */ private int parseEntityReference() throws IOException, SAXException { int ch; ch = _reader.read(); // character reference if (ch == '#') { addText((char) parseCharacterReference()); return _reader.read(); } // entity reference else if (XmlChar.isNameStart(ch)) { ch = _reader.parseName(_buf, ch); if (ch != ';' && _strictXml) throw error(L.l("`&{0};' expected `;' at {0}. Entity references have a `&name;' syntax.", _buf, badChar(ch))); else if (ch != ';') { addText('&'); addText(_buf.toString()); return ch; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?