📄 xpath.java
字号:
/* * Copyright 2000-2002,2004,2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.sun.org.apache.xerces.internal.impl.xpath;import java.util.Vector;import com.sun.org.apache.xerces.internal.util.SymbolTable;import com.sun.org.apache.xerces.internal.util.XMLSymbols;import com.sun.org.apache.xerces.internal.util.XMLChar;import com.sun.org.apache.xerces.internal.xni.NamespaceContext;import com.sun.org.apache.xerces.internal.xni.QName;/** * Bare minimum XPath parser. * * @xerces.internal * * @author Andy Clark, IBM * @author Sunitha Reddy, Sun Microsystems * @version $Id: XPath.java,v 1.3 2005/09/26 13:02:31 sunithareddy Exp $ */public class XPath { // // Constants // private static final boolean DEBUG_ALL = false; private static final boolean DEBUG_XPATH_PARSE = DEBUG_ALL || false; private static final boolean DEBUG_ANY = DEBUG_XPATH_PARSE; // // Data // /** Expression. */ protected String fExpression; /** Symbol table. */ protected SymbolTable fSymbolTable; /** Location paths. */ protected LocationPath[] fLocationPaths; // // Constructors // /** Constructs an XPath object from the specified expression. */ public XPath(String xpath, SymbolTable symbolTable, NamespaceContext context) throws XPathException { fExpression = xpath; fSymbolTable = symbolTable; parseExpression(context); } // <init>(String,SymbolTable,NamespaceContext) // // Public methods // /** * Returns a representation of all location paths for this XPath. * XPath = locationPath ( '|' locationPath) */ public LocationPath[] getLocationPaths() { LocationPath[] ret=new LocationPath[fLocationPaths.length]; for (int i=0;i<fLocationPaths.length;i++){ ret[i]=(LocationPath)fLocationPaths[i].clone(); } return ret; } // getLocationPath(LocationPath) /** Returns a representation of the first location path for this XPath. */ public LocationPath getLocationPath() { return (LocationPath)fLocationPaths[0].clone(); } // getLocationPath(LocationPath) // // Object methods // /** Returns a string representation of this object. */ public String toString() { StringBuffer buf=new StringBuffer(); for (int i=0;i<fLocationPaths.length;i++){ if (i>0){ buf.append("|"); } buf.append(fLocationPaths[i].toString()); } return buf.toString(); } // toString():String // // Private methods // /** * Used by the {@link #parseExpression(NamespaceContext)} method * to verify the assumption. * * If <tt>b</tt> is false, this method throws XPathException * to report the error. */ private static void check( boolean b ) throws XPathException { if(!b) throw new XPathException("c-general-xpath"); } /** * Used by the {@link #parseExpression(NamespaceContext)} method * to build a {@link LocationPath} object from the accumulated * {@link Step}s. */ private LocationPath buildLocationPath( Vector stepsVector ) throws XPathException { int size = stepsVector.size(); check(size!=0); Step[] steps = new Step[size]; stepsVector.copyInto(steps); stepsVector.removeAllElements(); return new LocationPath(steps); } /** * This method is implemented by using the XPathExprScanner and * examining the list of tokens that it returns. */ private void parseExpression(final NamespaceContext context) throws XPathException { // tokens final XPath.Tokens xtokens = new XPath.Tokens(fSymbolTable); // scanner XPath.Scanner scanner = new XPath.Scanner(fSymbolTable) { protected void addToken(XPath.Tokens tokens, int token) throws XPathException { if ( token == XPath.Tokens.EXPRTOKEN_ATSIGN || token == XPath.Tokens.EXPRTOKEN_AXISNAME_ATTRIBUTE || token == XPath.Tokens.EXPRTOKEN_NAMETEST_QNAME || token == XPath.Tokens.EXPRTOKEN_OPERATOR_SLASH || token == XPath.Tokens.EXPRTOKEN_PERIOD || token == XPath.Tokens.EXPRTOKEN_NAMETEST_ANY || token == XPath.Tokens.EXPRTOKEN_NAMETEST_NAMESPACE || token == XPath.Tokens.EXPRTOKEN_OPERATOR_DOUBLE_SLASH || token == XPath.Tokens.EXPRTOKEN_OPERATOR_UNION || token == XPath.Tokens.EXPRTOKEN_AXISNAME_CHILD || token == XPath.Tokens.EXPRTOKEN_DOUBLE_COLON ) { super.addToken(tokens, token); return; } throw new XPathException("c-general-xpath"); } }; int length = fExpression.length(); boolean success = scanner.scanExpr(fSymbolTable, xtokens, fExpression, 0, length); if(!success) throw new XPathException("c-general-xpath"); //fTokens.dumpTokens(); Vector stepsVector = new Vector(); Vector locationPathsVector= new Vector(); // true when the next token should be 'Step' (as defined in // the production rule [3] of XML Schema P1 section 3.11.6 // if false, we are expecting either '|' or '/'. // // this is to make sure we can detect a token list like // 'abc' '/' '/' 'def' 'ghi' boolean expectingStep = true; boolean expectingDoubleColon = false; while(xtokens.hasMore()) { final int token = xtokens.nextToken(); switch (token) { case XPath.Tokens.EXPRTOKEN_OPERATOR_UNION :{ check(!expectingStep); locationPathsVector.addElement(buildLocationPath(stepsVector)); expectingStep=true; break; } case XPath.Tokens.EXPRTOKEN_ATSIGN: { check(expectingStep); Step step = new Step( new Axis(Axis.ATTRIBUTE), parseNodeTest(xtokens.nextToken(),xtokens,context)); stepsVector.addElement(step); expectingStep=false; break; } case XPath.Tokens.EXPRTOKEN_NAMETEST_ANY: case XPath.Tokens.EXPRTOKEN_NAMETEST_NAMESPACE: case XPath.Tokens.EXPRTOKEN_NAMETEST_QNAME: { check(expectingStep); Step step = new Step( new Axis(Axis.CHILD), parseNodeTest(token,xtokens,context)); stepsVector.addElement(step); expectingStep=false; break; } case XPath.Tokens.EXPRTOKEN_PERIOD: { check(expectingStep); expectingStep=false; // unless this is the first step in this location path, // there's really no reason to keep them in LocationPath. // This amounts to shorten "a/././b/./c" to "a/b/c". // Also, the matcher fails to work correctly if XPath // has those redundant dots. if (stepsVector.size()==0) { // build step Axis axis = new Axis(Axis.SELF); NodeTest nodeTest = new NodeTest(NodeTest.NODE); Step step = new Step(axis, nodeTest); stepsVector.addElement(step); if( xtokens.hasMore() && xtokens.peekToken() == XPath.Tokens.EXPRTOKEN_OPERATOR_DOUBLE_SLASH){ // consume '//' xtokens.nextToken(); // build step axis = new Axis(Axis.DESCENDANT); nodeTest = new NodeTest(NodeTest.NODE); step = new Step(axis, nodeTest); stepsVector.addElement(step); expectingStep=true; } } break; } case XPath.Tokens.EXPRTOKEN_OPERATOR_DOUBLE_SLASH:{ // this cannot appear in arbitrary position. // it is only allowed right after '.' when // '.' is the first token of a location path. throw new XPathException("c-general-xpath"); } case XPath.Tokens.EXPRTOKEN_OPERATOR_SLASH: { check(!expectingStep); expectingStep=true; break; } case XPath.Tokens.EXPRTOKEN_AXISNAME_ATTRIBUTE: { check(expectingStep); expectingDoubleColon = true; if (xtokens.nextToken() == XPath.Tokens.EXPRTOKEN_DOUBLE_COLON){ Step step = new Step( new Axis(Axis.ATTRIBUTE), parseNodeTest(xtokens.nextToken(),xtokens,context)); stepsVector.addElement(step); expectingStep=false; expectingDoubleColon = false; } break; } case XPath.Tokens.EXPRTOKEN_AXISNAME_CHILD:{ check(expectingStep); expectingDoubleColon = true; break; } case XPath.Tokens.EXPRTOKEN_DOUBLE_COLON :{ check(expectingStep); check(expectingDoubleColon); expectingDoubleColon = false; break; } default: // we should have covered all the tokens that we can possibly see. throw new XPathException("c-general-xpath"); } } check(!expectingStep); locationPathsVector.addElement(buildLocationPath(stepsVector)); // save location path fLocationPaths=new LocationPath[locationPathsVector.size()]; locationPathsVector.copyInto(fLocationPaths); if (DEBUG_XPATH_PARSE) { System.out.println(">>> "+fLocationPaths); } } // parseExpression(SymbolTable,NamespaceContext) /** * Used by {@link #parseExpression} to parse a node test * from the token list. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -