📄 xpathreader.java
字号:
/* * $Header: /home/projects/jaxen/scm/jaxen/src/java/main/org/jaxen/saxpath/base/XPathReader.java,v 1.32 2006/04/07 23:47:37 elharo Exp $ * $Revision: 1.32 $ * $Date: 2006/04/07 23:47:37 $ * * ==================================================================== * * Copyright 2000-2002 bob mcwhirter & James Strachan. * All rights reserved. * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * 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. * * * Neither the name of the Jaxen Project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS 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 COPYRIGHT OWNER * OR 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 Jaxen Project and was originally * created by bob mcwhirter <bob@werken.com> and * James Strachan <jstrachan@apache.org>. For more information on the * Jaxen Project, please see <http://www.jaxen.org/>. * * $Id: XPathReader.java,v 1.32 2006/04/07 23:47:37 elharo Exp $ */package org.jaxen.saxpath.base;import java.util.ArrayList;import org.jaxen.saxpath.Axis;import org.jaxen.saxpath.Operator;import org.jaxen.saxpath.SAXPathException;import org.jaxen.saxpath.XPathHandler;import org.jaxen.saxpath.XPathSyntaxException;import org.jaxen.saxpath.helpers.DefaultXPathHandler;/** Implementation of SAXPath's <code>XPathReader</code> which * generates callbacks to an <code>XPathHandler</code>. * * @author bob mcwhirter (bob@werken.com) */public class XPathReader implements org.jaxen.saxpath.XPathReader{ private ArrayList tokens; private XPathLexer lexer; private XPathHandler handler; private static XPathHandler defaultHandler = new DefaultXPathHandler(); /** * Create a new <code>XPathReader</code> with a do-nothing * <code>XPathHandler</code>. */ public XPathReader() { setXPathHandler( defaultHandler ); } public void setXPathHandler(XPathHandler handler) { this.handler = handler; } public XPathHandler getXPathHandler() { return this.handler; } public void parse(String xpath) throws SAXPathException { setUpParse( xpath ); getXPathHandler().startXPath(); expr(); getXPathHandler().endXPath(); if ( LA(1) != TokenTypes.EOF ) { XPathSyntaxException ex = createSyntaxException( "Unexpected '" + LT(1).getTokenText() + "'" ); throw ex; } lexer = null; tokens = null; } void setUpParse(String xpath) { this.tokens = new ArrayList(); this.lexer = new XPathLexer( xpath ); } private void pathExpr() throws SAXPathException { getXPathHandler().startPathExpr(); switch ( LA(1) ) { case TokenTypes.DOUBLE: case TokenTypes.LITERAL: { filterExpr(); if ( LA(1) == TokenTypes.SLASH || LA(1) == TokenTypes.DOUBLE_SLASH ) { XPathSyntaxException ex = createSyntaxException("Node-set expected"); throw ex; } break; } case TokenTypes.LEFT_PAREN: case TokenTypes.DOLLAR: { filterExpr(); if ( LA(1) == TokenTypes.SLASH || LA(1) == TokenTypes.DOUBLE_SLASH) { locationPath( false ); } break; } case TokenTypes.IDENTIFIER: { if ( ( LA(2) == TokenTypes.LEFT_PAREN && ! isNodeTypeName( LT(1) ) ) || ( LA(2) == TokenTypes.COLON && LA(4) == TokenTypes.LEFT_PAREN) ) { filterExpr(); if ( LA(1) == TokenTypes.SLASH || LA(1) == TokenTypes.DOUBLE_SLASH) { locationPath( false ); } } else { locationPath( false ); } break; } case TokenTypes.DOT: case TokenTypes.DOT_DOT: case TokenTypes.STAR: case TokenTypes.AT: { locationPath( false ); break; } case TokenTypes.SLASH: case TokenTypes.DOUBLE_SLASH: { locationPath( true ); break; } default: { XPathSyntaxException ex = createSyntaxException( "Unexpected '" + LT(1).getTokenText() + "'" ); throw ex; } } getXPathHandler().endPathExpr(); } private void literal() throws SAXPathException { Token token = match( TokenTypes.LITERAL ); getXPathHandler().literal( token.getTokenText() ); } private void functionCall() throws SAXPathException { String prefix = null; String functionName = null; if ( LA(2) == TokenTypes.COLON ) { prefix = match( TokenTypes.IDENTIFIER ).getTokenText(); match( TokenTypes.COLON ); } else { prefix = ""; } functionName = match( TokenTypes.IDENTIFIER ).getTokenText(); getXPathHandler().startFunction( prefix, functionName ); match ( TokenTypes.LEFT_PAREN ); arguments(); match ( TokenTypes.RIGHT_PAREN ); getXPathHandler().endFunction(); } private void arguments() throws SAXPathException { while ( LA(1) != TokenTypes.RIGHT_PAREN ) { expr(); if ( LA(1) == TokenTypes.COMMA ) { match( TokenTypes.COMMA ); } else { break; } } } private void filterExpr() throws SAXPathException { getXPathHandler().startFilterExpr(); switch ( LA(1) ) { case TokenTypes.DOUBLE: { Token token = match( TokenTypes.DOUBLE ); getXPathHandler().number( Double.parseDouble( token.getTokenText() ) ); break; } case TokenTypes.LITERAL: { literal(); break; } case TokenTypes.LEFT_PAREN: { match( TokenTypes.LEFT_PAREN ); expr(); match( TokenTypes.RIGHT_PAREN ); break; } case TokenTypes.IDENTIFIER: { functionCall(); break; } case TokenTypes.DOLLAR: { variableReference(); break; } } predicates(); getXPathHandler().endFilterExpr(); } private void variableReference() throws SAXPathException { match( TokenTypes.DOLLAR ); String prefix = null; String variableName = null; if ( LA(2) == TokenTypes.COLON ) { prefix = match( TokenTypes.IDENTIFIER ).getTokenText(); match( TokenTypes.COLON ); } else { prefix = ""; } variableName = match( TokenTypes.IDENTIFIER ).getTokenText(); getXPathHandler().variableReference( prefix, variableName ); } void locationPath(boolean isAbsolute) throws SAXPathException { switch ( LA(1) ) { case TokenTypes.SLASH: case TokenTypes.DOUBLE_SLASH: { if ( isAbsolute ) { absoluteLocationPath(); } else { relativeLocationPath(); } break; } case TokenTypes.AT: case TokenTypes.IDENTIFIER: case TokenTypes.DOT: case TokenTypes.DOT_DOT: case TokenTypes.STAR: { relativeLocationPath(); break; } default: { XPathSyntaxException ex = createSyntaxException( "Unexpected '" + LT(1).getTokenText() + "'" ); throw ex; } } } private void absoluteLocationPath() throws SAXPathException { getXPathHandler().startAbsoluteLocationPath(); switch ( LA(1) ) { case TokenTypes.SLASH: { match( TokenTypes.SLASH ); switch ( LA(1) ) { case TokenTypes.DOT: case TokenTypes.DOT_DOT: case TokenTypes.AT: case TokenTypes.IDENTIFIER: case TokenTypes.STAR: { steps(); break; } } break; } case TokenTypes.DOUBLE_SLASH: { getXPathHandler().startAllNodeStep( Axis.DESCENDANT_OR_SELF ); getXPathHandler().endAllNodeStep(); match( TokenTypes.DOUBLE_SLASH ); switch ( LA(1) ) { case TokenTypes.DOT: case TokenTypes.DOT_DOT: case TokenTypes.AT: case TokenTypes.IDENTIFIER: case TokenTypes.STAR: { steps(); break; } default: XPathSyntaxException ex = this.createSyntaxException("Location path cannot end with //"); throw ex; } break; } } getXPathHandler().endAbsoluteLocationPath(); } private void relativeLocationPath() throws SAXPathException { getXPathHandler().startRelativeLocationPath(); switch ( LA(1) ) { case TokenTypes.SLASH: { match( TokenTypes.SLASH ); break; } case TokenTypes.DOUBLE_SLASH: { getXPathHandler().startAllNodeStep( Axis.DESCENDANT_OR_SELF ); getXPathHandler().endAllNodeStep(); match( TokenTypes.DOUBLE_SLASH ); break; } } steps(); getXPathHandler().endRelativeLocationPath(); } private void steps() throws SAXPathException { switch ( LA(1) ) { case TokenTypes.DOT: case TokenTypes.DOT_DOT: case TokenTypes.AT: case TokenTypes.IDENTIFIER: case TokenTypes.STAR: { step(); break; } case TokenTypes.EOF: { return; } default: { XPathSyntaxException ex = createSyntaxException( "Expected one of '.', '..', '@', '*', <QName>" ); throw ex; } } do { if ( ( LA(1) == TokenTypes.SLASH) || ( LA(1) == TokenTypes.DOUBLE_SLASH ) ) { switch ( LA(1) ) { case TokenTypes.SLASH: { match( TokenTypes.SLASH ); break; } case TokenTypes.DOUBLE_SLASH: { getXPathHandler().startAllNodeStep( Axis.DESCENDANT_OR_SELF ); getXPathHandler().endAllNodeStep(); match( TokenTypes.DOUBLE_SLASH ); break; } } } else { return; } switch ( LA(1) ) { case TokenTypes.DOT: case TokenTypes.DOT_DOT: case TokenTypes.AT: case TokenTypes.IDENTIFIER: case TokenTypes.STAR: { step(); break; } default: { XPathSyntaxException ex = createSyntaxException( "Expected one of '.', '..', '@', '*', <QName>" ); throw ex; } } } while ( true ); } void step() throws SAXPathException { int axis = 0; switch ( LA(1) ) { case TokenTypes.DOT: case TokenTypes.DOT_DOT: { abbrStep(); return; } case TokenTypes.AT: { axis = axisSpecifier(); break; } case TokenTypes.IDENTIFIER: { if ( LA(2) == TokenTypes.DOUBLE_COLON ) { axis = axisSpecifier(); } else { axis = Axis.CHILD; } break; } case TokenTypes.STAR: { axis = Axis.CHILD; break; } } nodeTest( axis ); } private int axisSpecifier() throws SAXPathException { int axis = 0; switch ( LA(1) ) { case TokenTypes.AT: {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -