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 + -
显示快捷键?