xpath.java
来自「JAVA的一些源码 JAVA2 STANDARD EDITION DEVELO」· Java 代码 · 共 1,582 行 · 第 1/5 页
JAVA
1,582 行
/* * The Apache Software License, Version 1.1 * * * Copyright (c) 2000-2002 The Apache Software Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Xerces" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation and was * originally based on software copyright (c) 1999, International * Business Machines, Inc., http://www.apache.org. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */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. * * @author Andy Clark, IBM * @version $Id: XPath.java,v 1.13 2004/02/09 22:50:01 kohsuke 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_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 // ) { 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; 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; } default: // we should have covered all the tokens that we can possibly see. throw new InternalError(); } } check(!expectingStep); locationPathsVector.addElement(buildLocationPath(stepsVector)); // save location path fLocationPaths=new LocationPath[locationPathsVector.size()]; locationPathsVector.copyInto(fLocationPaths);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?