xpathparser.java

来自「RESIN 3.2 最新源码」· Java 代码 · 共 1,355 行 · 第 1/3 页

JAVA
1,355
字号
/* * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT.  See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the *   Free SoftwareFoundation, Inc. *   59 Temple Place, Suite 330 *   Boston, MA 02111-1307  USA * * @author Scott Ferguson */package com.caucho.xpath;import com.caucho.log.Log;import com.caucho.server.util.CauchoSystem;import com.caucho.util.CharBuffer;import com.caucho.util.IntMap;import com.caucho.util.L10N;import com.caucho.xml.XmlChar;import com.caucho.xpath.expr.*;import com.caucho.xpath.functions.BaseURI;import com.caucho.xpath.functions.ResolveURI;import com.caucho.xpath.functions.Trace;import com.caucho.xpath.pattern.*;import org.w3c.dom.Node;import java.lang.reflect.Constructor;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import java.util.ArrayList;import java.util.HashMap;import java.util.logging.Logger;/** * Parses an XPath expression. */class XPathParser {  private static final Logger log = Log.open(XPathParser.class);  private static final L10N L = new L10N(XPathParser.class);  private final static int ANCESTOR_AXIS = 0;  private final static int ANCESTOR_OR_SELF_AXIS = ANCESTOR_AXIS + 1;  private final static int ATTRIBUTE_AXIS = ANCESTOR_OR_SELF_AXIS + 1;  private final static int CHILD_AXIS = ATTRIBUTE_AXIS + 1;  private final static int DESCENDANT_AXIS = CHILD_AXIS + 1;  private final static int DESCENDANT_OR_SELF_AXIS = DESCENDANT_AXIS + 1;  private final static int FOLLOWING_AXIS = DESCENDANT_OR_SELF_AXIS + 1;  private final static int FOLLOWING_SIBLING_AXIS = FOLLOWING_AXIS + 1;  private final static int NAMESPACE_AXIS = FOLLOWING_SIBLING_AXIS + 1;  private final static int PARENT_AXIS = NAMESPACE_AXIS + 1;  private final static int PRECEDING_AXIS = PARENT_AXIS + 1;  private final static int PRECEDING_SIBLING_AXIS = PRECEDING_AXIS + 1;  private final static int SELF_AXIS = PRECEDING_SIBLING_AXIS + 1;  private final static int TEXT = Expr.LAST_FUN + 1;  private final static int COMMENT = TEXT + 1;  private final static int ER = COMMENT + 1;  private final static int PI = ER + 1;  private final static int NODE = PI + 1;  private final static int CURRENT = NODE + 1;  private final static int NODE_TEXT = CURRENT + 1;  private final static int CONTEXT = NODE_TEXT + 1;  private static IntMap exprFunctions;  private static IntMap axisMap;  private static HashMap<String,Constructor> _exprFunctions;    private CharBuffer tag = new CharBuffer();  private String _string;  private int index;  private int peek;  private NamespaceContext _namespace;  XPathParser(String string, NamespaceContext namespace)  {    _string = string;    _namespace = namespace;  }  /**   * Parse a select pattern, i.e. a path rooted in a context.   */  AbstractPattern parseSelect()    throws XPathParseException  {    AbstractPattern top = new FromContext();    AbstractPattern pattern = parseUnion(parseTop(top), top);    if (index < _string.length())      throw error(L.l("unexpected character at `{0}'", badChar(read())));    return pattern;  }  /**   * Parse a match pattern, i.e. a path with no root.   */  AbstractPattern parseMatch()    throws XPathParseException  {    AbstractPattern root = new FromAny();    AbstractPattern pattern = parseUnion(parseTop(root), root);    if (index < _string.length())      throw error(L.l("unexpected character at `{0}'", badChar(read())));    return pattern;  }  /**   * Parse an expression.   */  Expr parseExpr()    throws XPathParseException  {    Expr expr = parseExpr(null, null);    if (index < _string.length())      throw error(L.l("unexpected character at `{0}'", badChar(read())));    return expr;  }  private AbstractPattern parseStep(AbstractPattern root)    throws XPathParseException  {    return parseUnion(parseTop(root), root);  }  private AbstractPattern parseUnion(AbstractPattern left, AbstractPattern root)    throws XPathParseException  {    int ch = skipWhitespace(read());    while (ch >= 0) {      if (ch == '|') {	AbstractPattern tail = parseUnion(parseTop(root), root);	left = new UnionPattern(left, tail);      } else	break;      for (ch = read(); XmlChar.isWhitespace(ch); ch = read()) {      }    }    unread();    return left;  }  /**   * Parses the top expression.   *   * <pre>   *  top ::= (expr)   *      ::= term   * </pre>   */  private AbstractPattern parseTop(AbstractPattern pattern)    throws XPathParseException  {    int ch = skipWhitespace(read());    unread();    if (ch == '(') {      Expr expr = parseTerm(pattern, pattern);      // If the expression is really a pattern and the iterator is      // ascending, then just unwrap it.      if (expr instanceof NodeSetExpr) {        AbstractPattern nodeSet = ((NodeSetExpr) expr).getPattern();        if (nodeSet.isAscending())          return nodeSet;      }      return new FromExpr(null, expr);    }    else      return parseTerm(pattern, pattern).toNodeList();  }  private AbstractPattern parseBasisTop(AbstractPattern pattern)    throws XPathParseException  {    int ch;    ch = skipWhitespace(read());    if (ch == '/') {      ch = read();      if (ch == '/') {        pattern = new FromRoot();        pattern = new FromDescendants(pattern, false);	pattern = parseBasis(pattern);	pattern = parseFilter(pattern);        pattern = parsePath(pattern);        return pattern;      }      pattern = new FromRoot();      ch = skipWhitespace(ch);      if (ch == -1)	return pattern;    }    unread();    if (pattern == null)      pattern = new FromContext();    pattern = parseBasis(pattern);    pattern = parseFilter(pattern);    return parsePath(pattern);  }  /**   * path ::= top ('/' filter)*   */  private AbstractPattern parsePath(AbstractPattern pattern)    throws XPathParseException  {    int ch = skipWhitespace(read());    while (ch == '/') {      ch = read();      if (ch == '/') {	pattern = new FromDescendants(pattern, false);	pattern = parseBasis(pattern);	pattern = parseFilter(pattern);      }      else {	unread();	pattern = parseBasis(pattern);	pattern = parseFilter(pattern);      }      ch = skipWhitespace(read());    }    unread();        return pattern;  }    /**   * filter ::= atom('[' expr ']')*   */  private AbstractPattern parseFilter(AbstractPattern pattern)    throws XPathParseException  {    int ch = skipWhitespace(read());    while (ch == '[') {      AbstractPattern context = new FromContext();      Expr expr = parseExpr(context, pattern);      pattern = new FilterPattern(pattern, expr);      ch = skipWhitespace(read());      if (ch !=  ']')	throw error(L.l("expected `{0}' at {1}", "]", badChar(ch)));      ch = skipWhitespace(read());    }    unread();    return pattern;  }  /**   * basis ::= name::node-test   *         | node-test   *         | @node-test   *         | .   *         | ..   *         ;   */  private AbstractPattern parseBasis(AbstractPattern pattern)    throws XPathParseException  {    boolean fromChildren = true;    int ch = skipWhitespace(read());    int nodeType = Node.ELEMENT_NODE;    String namespace = null;    tag.clear();    if (ch == '@') {      if (pattern instanceof FromDescendants)	pattern = NodeTypePattern.create(pattern, NodeTypePattern.NODE);            pattern = new FromAttributes(pattern);      nodeType = Node.ATTRIBUTE_NODE;      fromChildren = false;      ch = read();    }    else if (ch == '.') {      ch = read();      if (ch == '.')	return NodeTypePattern.create(new FromParent(pattern),                                      NodeTypePattern.NODE);      else {	unread();        if (pattern != null)          return pattern;        else          return NodeTypePattern.create(new FromSelf(pattern), NodeTypePattern.ANY);      }    }    else if (ch == '(') {      // XXX: not strictly correct for counting      Expr expr = parseExpr(null, null);      if ((ch = read()) != ')')	throw error(L.l("expected `{0}' at {1}", ")", badChar(ch)));      return new FromExpr(pattern, expr);    }    if (ch == '*') {      tag.append('*');    }    else if (XmlChar.isNameStart(ch)) {      for (; XmlChar.isNameChar(ch); ch = read())	tag.append((char) ch);      if (ch == '*' && tag.endsWith(":"))	tag.append('*');      else	unread();    }    else      unread();    String name = tag.toString();    if (name.equals(""))      throw error(L.l("expected name at {0}", badChar(ch)));    return parseAxis(pattern, name, fromChildren, nodeType);  }  private AbstractPattern parseAxis(AbstractPattern pattern, String name,                                    boolean fromChildren, int nodeType)    throws XPathParseException  {    String axis = "";    int axisIndex = name.indexOf("::");    if (axisIndex >= 0 && nodeType != Node.ATTRIBUTE_NODE) {      axis = name.substring(0, axisIndex);      name = name.substring(axisIndex + 2);    }    if (pattern instanceof FromDescendants)      return parseNodeTest(pattern, name, false, Node.ELEMENT_NODE);    switch (axisMap.get(axis)) {    case ANCESTOR_AXIS:      return parseNodeTest(new FromAncestors(pattern, false),			   name, false, Node.ELEMENT_NODE);    case ANCESTOR_OR_SELF_AXIS:      return parseNodeTest(new FromAncestors(pattern, true),			   name, false, Node.ELEMENT_NODE);    case ATTRIBUTE_AXIS:      return parseNodeTest(new FromAttributes(pattern),			   name, false, Node.ATTRIBUTE_NODE);    case CHILD_AXIS:      return parseNodeTest(new FromChildren(pattern),			   name, false, Node.ELEMENT_NODE);    case DESCENDANT_AXIS:      return parseNodeTest(new FromDescendants(pattern, false),			   name, false, Node.ELEMENT_NODE);    case DESCENDANT_OR_SELF_AXIS:      return parseNodeTest(new FromDescendants(pattern, true),			   name, false, Node.ELEMENT_NODE);    case FOLLOWING_AXIS:      return parseNodeTest(new FromNext(pattern),			   name, false, Node.ELEMENT_NODE);    case FOLLOWING_SIBLING_AXIS:      return parseNodeTest(new FromNextSibling(pattern),			   name, false, Node.ELEMENT_NODE);    case NAMESPACE_AXIS:      return parseNodeTest(new FromNamespace(pattern),			   name, false, Node.ATTRIBUTE_NODE);    case PARENT_AXIS:      return parseNodeTest(new FromParent(pattern),			   name, false, Node.ELEMENT_NODE);    case PRECEDING_AXIS:      return parseNodeTest(new FromPrevious(pattern),			   name, false, Node.ELEMENT_NODE);    case PRECEDING_SIBLING_AXIS:      return parseNodeTest(new FromPreviousSibling(pattern),			   name, false, Node.ELEMENT_NODE);    case SELF_AXIS:      return parseNodeTest(new FromSelf(pattern),			   name, false, Node.ELEMENT_NODE);    default:      return parseNodeTest(pattern, name, fromChildren, nodeType);    }  }  /**   * node-test ::= qname   *             | *:name   *             | *   *             | name '(' args ')'   *             ;   */  private AbstractPattern parseNodeTest(AbstractPattern pattern, String name,                                        boolean fromChildren, int nodeType)    throws XPathParseException  {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?