xpathparser.java
来自「RESIN 3.2 最新源码」· Java 代码 · 共 1,355 行 · 第 1/3 页
JAVA
1,355 行
{ int ch = skipWhitespace(read()); ArrayList<Expr> args = new ArrayList<Expr>(); for (; ch >= 0 && ch != ')'; ch = skipWhitespace(read())) { if (ch != ',') unread(); Expr expr = parseExpr(parent, listParent); if (expr == null) throw error(L.l("null expression")); args.add(expr); } int code = exprFunctions.get(name); switch (code) { case Expr.TRUE: case Expr.FALSE: case Expr.NOT: case Expr.BOOLEAN: case Expr.STARTS_WITH: case Expr.CONTAINS: case Expr.LANG: case Expr.FUNCTION_AVAILABLE: return new BooleanExpr(code, args); case Expr.NUMBER: case Expr.FLOOR: case Expr.CEILING: case Expr.ROUND: case Expr.STRING_LENGTH: return new NumericExpr(code, args); case Expr.POSITION: case Expr.LAST: return new NumericExpr(code, listParent); case Expr.COUNT: case Expr.SUM: if (args.size() == 0) args.add(NodeSetExpr.create(new FromContext())); return new NumericExpr(code, ((Expr) args.get(0)).toNodeList()); case Expr.CONCAT: case Expr.SUBSTRING_BEFORE: case Expr.SUBSTRING: case Expr.SUBSTRING_AFTER: case Expr.TRANSLATE: case Expr.SYSTEM_PROPERTY: return new StringExpr(code, args); case Expr.STRING: case Expr.NORMALIZE: return new StringExpr(code, args); case Expr.LOCAL_PART: case Expr.NAMESPACE: case Expr.QNAME: case Expr.GENERATE_ID: if (args.size() == 0) args.add(NodeSetExpr.create(new FromContext())); return new StringExpr(code, args); case Expr.ID: if (args.size() == 0) { args.add(NodeSetExpr.create(parent)); return new IdExpr(args); } else return new IdExpr(args); case Expr.IF: if (args.size() != 3) throw error(L.l("`if' needs three args.")); return new ObjectExpr(code, args); case Expr.BASE_URI: if (args.size() != 1) throw error(L.l("`base-uri' needs one args.")); return new StringExpr(code, args.get(0)); case TEXT: if (fromChildren) parent = new FromChildren(parent); AbstractPattern pattern = NodeTypePattern.create(parent, Node.TEXT_NODE); return NodeSetExpr.create(pattern); case COMMENT: if (fromChildren) parent = new FromChildren(parent); pattern = NodeTypePattern.create(parent, Node.COMMENT_NODE); return NodeSetExpr.create(pattern); case ER: if (fromChildren) parent = new FromChildren(parent); pattern = NodeTypePattern.create(parent, Node.ENTITY_REFERENCE_NODE); return NodeSetExpr.create(pattern); case PI: if (fromChildren) parent = new FromChildren(parent); if (args.size() == 1) { Expr expr = (Expr) args.get(0); String value = null; if (expr instanceof StringExpr) value = ((StringExpr) expr).getValue(); if (value == null) throw error(L.l("processing-instruction expects string literal")); pattern = new NodePattern(parent, value, Node.PROCESSING_INSTRUCTION_NODE); } else pattern = NodeTypePattern.create(parent, Node.PROCESSING_INSTRUCTION_NODE); return NodeSetExpr.create(pattern); case NODE: if (fromChildren) parent = new FromChildren(parent); pattern = NodeTypePattern.create(parent, NodeTypePattern.NODE); return NodeSetExpr.create(pattern); case CURRENT: return NodeSetExpr.create(new CurrentPattern()); case CONTEXT: return NodeSetExpr.create(new FromContext()); default: Expr function = constructorFunction(name, args); if (function != null) return function; int p = name.lastIndexOf(':'); String prefix; if (p > 0) prefix = name.substring(0, p); else prefix = ""; String context = NamespaceContext.find(_namespace, prefix); if (context == null) { } else if (context.startsWith("java:")) name = context + "." + name.substring(p + 1); else if (context.indexOf(':') < 0) name = "java:" + context + "." + name.substring(p + 1); if (name.startsWith("java:")) { p = name.lastIndexOf('.'); if (p < 0) throw error(L.l("`{0}' is an illegal extension function. Java extension functions must look like java:mypkg.MyClass.mymethod.", name)); String className = name.substring(5, p); String methodName = name.substring(p + 1); Class cl; try { cl = CauchoSystem.loadClass(className); } catch (ClassNotFoundException e) { throw error(L.l("`{0}' is an unknown Java class. Java extension functions must use public classes.", className)); } if (methodName.equals("new")) { Constructor []constructors = cl.getConstructors(); for (int i = 0; i < constructors.length; i++) { if (constructors[i].getParameterTypes().length == args.size()) return new NewJavaExpr(constructors[i], args); } throw error(L.l("No matching public constructor in `{0}'", className)); } Method method = null; Method []methods = cl.getMethods(); if (args.size() > 0) { for (int i = 0; i < methods.length; i++) { if (methods[i].getName().equals(methodName) && methods[i].getParameterTypes().length == args.size() - 1 && ! Modifier.isStatic(methods[i].getModifiers())) { Expr objArg = (Expr) args.remove(0); return new ObjectJavaExpr(methods[i], objArg, args); } } } for (int i = 0; i < methods.length; i++) { if (methods[i].getName().equals(methodName) && methods[i].getParameterTypes().length == args.size()) { method = methods[i]; break; } } if (method == null) throw error(L.l("`{0}' does not match a public method in `{1}'", methodName, className)); if (! Modifier.isStatic(method.getModifiers())) throw error(L.l("`{0}' is not a static method in `{1}'", methodName, className)); return new StaticJavaExpr(method, args); } else if (name.equals("")) throw error(L.l("expected node-test at `{0}'", "(")); return new FunExpr(name, parent, args); } } private Expr constructorFunction(String name, ArrayList<Expr> args) throws XPathParseException { Constructor constructor = _exprFunctions.get(name); if (constructor == null) return null; Class []params = constructor.getParameterTypes(); if (params.length < args.size()) throw error(L.l("`{0}' needs {1} arguments", name, "" + params.length)); Object []values = new Object[params.length]; for (int i = 0; i < args.size(); i++) values[i] = args.get(i); try { return (Expr) constructor.newInstance(values); } catch (Throwable e) { throw new XPathParseException(e); } } private Expr parseNodeSetExpr(AbstractPattern parent, String name, int nodeType) throws XPathParseException { AbstractPattern top = parseAxis(parent, name, true, nodeType); top = parseFilter(top); return NodeSetExpr.create(parseUnion(parsePath(top), parent)); } /** * Scans the next token. * * @return token code, expressed as an Expr enumeration. */ private int scanToken() throws XPathParseException { if (peek >= 0) { int value = peek; peek = -1; return value; } int ch = skipWhitespace(read()); switch (ch) { case '+': return Expr.ADD; case '-': return Expr.SUB; case '*': return Expr.MUL; case '=': return Expr.EQ; case '!': ch = read(); if (ch == '=') return Expr.NEQ; else throw error(L.l("expected `{0}' at {1}", "=", badChar(ch))); case '<': ch = read(); if (ch == '=') return Expr.LE; else { unread(); return Expr.LT; } case '>': ch = read(); if (ch == '=') return Expr.GE; else { unread(); return Expr.GT; } default: if (XmlChar.isNameStart(ch)) { String name = readName(ch); if (name.equals("div")) return Expr.DIV; else if (name.equals("quo")) return Expr.QUO; else if (name.equals("mod")) return Expr.MOD; else if (name.equals("and")) return Expr.AND; else if (name.equals("or")) return Expr.OR; else throw error(L.l("expected binary operation at `{0}'", name)); } unread(); return -1; } } private String readName(int ch) { tag.clear(); for (; XmlChar.isNameChar(ch); ch = read()) tag.append((char) ch); if (ch == '*' && tag.endsWith(":")) tag.append((char) ch); else unread(); return tag.toString(); } private void undoToken(int token) { peek = token; } private int read() { if (index < _string.length()) { return _string.charAt(index++); } else { index++; return -1; } } private void unread() { index--; } private XPathParseException error(String message) { return new XPathParseException(message + " in " + _string); } private String badChar(int ch) { if (ch < 0) return L.l("end of file"); else if (ch == '\n') return L.l("end of line"); else return "`" + (char) ch + "'"; } private int skipWhitespace(int ch) throws XPathParseException { for (; ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'; ch = read()) { } return ch; } private static void addFunction(String name, Class cl) { Constructor []constructors = cl.getConstructors(); _exprFunctions.put(name, constructors[0]); } static { exprFunctions = new IntMap(); exprFunctions.put("id", Expr.ID); exprFunctions.put("true", Expr.TRUE); exprFunctions.put("false", Expr.FALSE); exprFunctions.put("not", Expr.NOT); exprFunctions.put("boolean", Expr.BOOLEAN); exprFunctions.put("starts-with", Expr.STARTS_WITH); exprFunctions.put("contains", Expr.CONTAINS); exprFunctions.put("lang", Expr.LANG); exprFunctions.put("number", Expr.NUMBER); exprFunctions.put("sum", Expr.SUM); exprFunctions.put("floor", Expr.FLOOR); exprFunctions.put("ceiling", Expr.CEILING); exprFunctions.put("round", Expr.ROUND); exprFunctions.put("position", Expr.POSITION); exprFunctions.put("count", Expr.COUNT); exprFunctions.put("last", Expr.LAST); exprFunctions.put("string-length", Expr.STRING_LENGTH); exprFunctions.put("string", Expr.STRING); exprFunctions.put("concat", Expr.CONCAT); exprFunctions.put("substring", Expr.SUBSTRING); exprFunctions.put("substring-before", Expr.SUBSTRING_BEFORE); exprFunctions.put("substring-after", Expr.SUBSTRING_AFTER); exprFunctions.put("normalize-space", Expr.NORMALIZE); exprFunctions.put("translate", Expr.TRANSLATE); exprFunctions.put("local-name", Expr.LOCAL_PART); exprFunctions.put("local-part", Expr.LOCAL_PART); exprFunctions.put("namespace-uri", Expr.NAMESPACE); exprFunctions.put("name", Expr.QNAME); exprFunctions.put("generate-id", Expr.GENERATE_ID); exprFunctions.put("if", Expr.IF); exprFunctions.put("text", TEXT); exprFunctions.put("comment", COMMENT); exprFunctions.put("er", ER); exprFunctions.put("entity-reference", ER); exprFunctions.put("pi", PI); exprFunctions.put("processing-instruction", PI); exprFunctions.put("node", NODE); exprFunctions.put("current", CURRENT); exprFunctions.put("context", CONTEXT); axisMap = new IntMap(); axisMap.put("ancestor", ANCESTOR_AXIS); axisMap.put("ancestor-or-self", ANCESTOR_OR_SELF_AXIS); axisMap.put("attribute", ATTRIBUTE_AXIS); axisMap.put("child", CHILD_AXIS); axisMap.put("descendant", DESCENDANT_AXIS); axisMap.put("descendant-or-self", DESCENDANT_OR_SELF_AXIS); axisMap.put("following", FOLLOWING_AXIS); axisMap.put("following-sibling", FOLLOWING_SIBLING_AXIS); axisMap.put("namespace", NAMESPACE_AXIS); axisMap.put("parent", PARENT_AXIS); axisMap.put("preceding", PRECEDING_AXIS); axisMap.put("preceding-sibling", PRECEDING_SIBLING_AXIS); axisMap.put("self", SELF_AXIS); _exprFunctions = new HashMap<String,Constructor>(); addFunction("fn:base-uri", BaseURI.class); addFunction("fn:resolve-uri", ResolveURI.class); addFunction("fn:trace", Trace.class); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?