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 ::= &lt!ELEMENT ...  |   *              &lt!ATTLIST ...  |   *              &lt!NOTATION ... |   *              &lt!ENTITY ...   |   *              &lt!-- comment   |   *              &lt? 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 &lt;%= as an attribute in JSP   * files.  Covers cases like the following:   *   * <pre>   * &lt;options>   * &lt;option name="foo" &lt;%= test.isSelected("foo") %>/>   * &lt;/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 + -
显示快捷键?