All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hp.hpl.sparta.XPathVisitor Maven / Gradle / Ivy

Go to download

Support Chinese character (both Simplified and Tranditional) to most popular Pinyin systems, including Hanyu Pinyin, Tongyong Pinyin, Wade-Giles, MPS2, Yale and Gwoyeu Romatzyh. Support multiple pronounciations and customized output.

The newest version!
package com.hp.hpl.sparta;

import com.hp.hpl.sparta.xpath.*;

import java.io.IOException;
import java.util.*;

/**
 * Visitor that evaluates an xpath expression relative to a context
 * node by walking over the parse tree of the expression.

 
Copyright (C) 2002 Hewlett-Packard Company. This file is part of Sparta, an XML Parser, DOM, and XPath library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
@version $Date: 2003/08/11 18:48:39 $ $Revision: 1.9 $ @author Eamonn O'Brien-Strain * @stereotype visitor */ class XPathVisitor implements Visitor { /** Evaluate a relative xpath expression relative to a context * element by walking over the parse tree of th expression. */ private XPathVisitor(XPath xpath, Node context) throws XPathException { xpath_ = xpath; contextNode_ = context; nodelistFiltered_ = new Vector(1); nodelistFiltered_.addElement(contextNode_); for (Enumeration i = xpath.getSteps(); i.hasMoreElements();) { Step step = (Step) i.nextElement(); multiLevel_ = step.isMultiLevel(); nodesetIterator_ = null; step.getNodeTest().accept(this); nodesetIterator_ = nodelistRaw_.iterator(); nodelistFiltered_.removeAllElements(); BooleanExpr predicate = step.getPredicate(); while (nodesetIterator_.hasMoreElements()) { node_ = nodesetIterator_.nextElement(); predicate.accept(this); Boolean expr = exprStack_.pop(); if (expr.booleanValue()) nodelistFiltered_.addElement(node_); } } } /** Evaluate a relative xpath expression relative to a context * element by walking over the parse tree of th expression. */ public XPathVisitor(Element context, XPath xpath) throws XPathException { this(xpath, context); if (xpath.isAbsolute()) throw new XPathException(xpath, "Cannot use element as context node for absolute xpath"); } /** Evaluate an absolute xpath expression in a document by walking over the parse tree of th expression. */ public XPathVisitor(Document context, XPath xpath) throws XPathException { this(xpath, context); } public void visit(ThisNodeTest a) { nodelistRaw_.removeAllElements(); nodelistRaw_.add(contextNode_, 1); } /** @throws XPathException if ".." applied to node with no parent. */ public void visit(ParentNodeTest a) throws XPathException { nodelistRaw_.removeAllElements(); Node parent = contextNode_.getParentNode(); if (parent == null) throw new XPathException(xpath_, "Illegal attempt to apply \"..\" to node with no parent."); nodelistRaw_.add(parent, 1); } public void visit(AllElementTest a) { Vector oldNodeList = nodelistFiltered_; nodelistRaw_.removeAllElements(); for (Enumeration i = oldNodeList.elements(); i.hasMoreElements();) { Object node = i.nextElement(); if (node instanceof Element) accumulateElements((Element) node); else if (node instanceof Document) accumulateElements((Document) node); } } private void accumulateElements(Document doc) { Element child = doc.getDocumentElement(); nodelistRaw_.add(child, 1); if (multiLevel_) accumulateElements(child); //recursive call } private void accumulateElements(Element element) { int position = 0; for (Node n = element.getFirstChild(); n != null; n = n.getNextSibling()) { if (n instanceof Element) { nodelistRaw_.add(n, ++position); if (multiLevel_) accumulateElements((Element) n); //recursive call } } } public void visit(TextTest a) { Vector oldNodeList = nodelistFiltered_; nodelistRaw_.removeAllElements(); for (Enumeration i = oldNodeList.elements(); i.hasMoreElements();) { Object node = i.nextElement(); if (node instanceof Element) { Element element = (Element) node; for (Node n = element.getFirstChild(); n != null; n = n.getNextSibling()) if (n instanceof Text) nodelistRaw_.add(((Text) n).getData()); } } } public void visit(ElementTest test) { String tagName = test.getTagName(); Vector oldNodeList = nodelistFiltered_; int n = oldNodeList.size(); nodelistRaw_.removeAllElements(); for (int i = 0; i < n; ++i) { Object node = oldNodeList.elementAt(i); if (node instanceof Element) accumulateMatchingElements((Element) node, tagName); else if (node instanceof Document) accumulateMatchingElements((Document) node, tagName); } } private void accumulateMatchingElements(Document document, String tagName) { Element child = document.getDocumentElement(); if (child == null) return; //no document element if (child.getTagName() == tagName) //both strings interned nodelistRaw_.add(child, 1); if (multiLevel_) accumulateMatchingElements(child, tagName); //recursive call } private void accumulateMatchingElements(Element element, String tagName) { int position = 0; for (Node n = element.getFirstChild(); n != null; n = n.getNextSibling()) { if (n instanceof Element) { Element child = (Element) n; if (child.getTagName() == tagName) //both strings interned nodelistRaw_.add(child, ++position); if (multiLevel_) accumulateMatchingElements(child, tagName); //recursion } } } public void visit(AttrTest test) { Vector oldNodeList = nodelistFiltered_; nodelistRaw_.removeAllElements(); for (Enumeration i = oldNodeList.elements(); i.hasMoreElements();) { Node node = (Node) i.nextElement(); if (node instanceof Element) { Element element = (Element) node; String attr = element.getAttribute(test.getAttrName()); if (attr != null) nodelistRaw_.add(attr); } } } static private final Boolean TRUE = new Boolean(true); static private final Boolean FALSE = new Boolean(false); public void visit(TrueExpr a) { exprStack_.push(TRUE); } public void visit(AttrExistsExpr a) throws XPathException { if (!(node_ instanceof Element)) throw new XPathException(xpath_, "Cannot test attribute of document"); Element element = (Element) node_; String attrValue = element.getAttribute(a.getAttrName()); boolean result = attrValue != null && attrValue.length() > 0; exprStack_.push(result ? TRUE : FALSE); } public void visit(AttrEqualsExpr a) throws XPathException { if (!(node_ instanceof Element)) throw new XPathException(xpath_, "Cannot test attribute of document"); Element element = (Element) node_; String attrValue = element.getAttribute(a.getAttrName()); boolean result = a.getAttrValue().equals(attrValue); exprStack_.push(result ? TRUE : FALSE); } public void visit(AttrNotEqualsExpr a) throws XPathException { if (!(node_ instanceof Element)) throw new XPathException(xpath_, "Cannot test attribute of document"); Element element = (Element) node_; String attrValue = element.getAttribute(a.getAttrName()); boolean result = !a.getAttrValue().equals(attrValue); exprStack_.push(result ? TRUE : FALSE); } public void visit(AttrLessExpr a) throws XPathException { if (!(node_ instanceof Element)) throw new XPathException(xpath_, "Cannot test attribute of document"); Element element = (Element) node_; // Use jdk1.1 API to make the code work with PersonalJava. // double attrValue = Double.parseDouble( element.getAttribute( a.getAttrName() ) ); long attrValue = Long.parseLong(element.getAttribute(a.getAttrName())); boolean result = attrValue < a.getAttrValue(); exprStack_.push(result ? TRUE : FALSE); } public void visit(AttrGreaterExpr a) throws XPathException { if (!(node_ instanceof Element)) throw new XPathException(xpath_, "Cannot test attribute of document"); Element element = (Element) node_; // Use jdk1.1 API to make the code work with PersonalJava. // double attrValue = Double.parseDouble( element.getAttribute( a.getAttrName() ) ); long attrValue = Long.parseLong(element.getAttribute(a.getAttrName())); boolean result = attrValue > a.getAttrValue(); exprStack_.push(result ? TRUE : FALSE); } public void visit(TextExistsExpr a) throws XPathException { if (!(node_ instanceof Element)) throw new XPathException(xpath_, "Cannot test attribute of document"); Element element = (Element) node_; for (Node i = element.getFirstChild(); i != null; i = i.getNextSibling()) { if (i instanceof Text) { exprStack_.push(TRUE); return; } } exprStack_.push(FALSE); } public void visit(TextEqualsExpr a) throws XPathException { if (!(node_ instanceof Element)) throw new XPathException(xpath_, "Cannot test attribute of document"); Element element = (Element) node_; for (Node i = element.getFirstChild(); i != null; i = i.getNextSibling()) { if (i instanceof Text) { Text text = (Text) i; if (text.getData().equals(a.getValue())) { exprStack_.push(TRUE); return; } } } exprStack_.push(FALSE); } public void visit(TextNotEqualsExpr a) throws XPathException { if (!(node_ instanceof Element)) throw new XPathException(xpath_, "Cannot test attribute of document"); Element element = (Element) node_; for (Node i = element.getFirstChild(); i != null; i = i.getNextSibling()) { if (i instanceof Text) { Text text = (Text) i; if (!text.getData().equals(a.getValue())) { exprStack_.push(TRUE); return; } } } exprStack_.push(FALSE); } public void visit(PositionEqualsExpr a) throws XPathException { if (!(node_ instanceof Element)) throw new XPathException(xpath_, "Cannot test position of document"); Element element = (Element) node_; boolean result = (nodelistRaw_.position(element) == a.getPosition()); exprStack_.push(result ? TRUE : FALSE); } /** Get all the elements or strings that match the xpath expression. */ public Enumeration getResultEnumeration() { return nodelistFiltered_.elements(); } /** Get the first element that match the xpath expression, or null. */ public Element getFirstResultElement() { return nodelistFiltered_.size() == 0 ? null : (Element) nodelistFiltered_.elementAt(0); } /** Get the first string that match the xpath expression, or null. */ public String getFirstResultString() { return nodelistFiltered_.size() == 0 ? null : (String) nodelistFiltered_.elementAt(0) .toString(); } /* static private class BooleanStack extends LinkedList{ void push(Boolean b){ addLast(b); } Boolean pop(){ return (Boolean)removeLast(); } } */ /** Profiling found this to be very heavily used so do not use java.util.LinkedList */ static private class BooleanStack { private Item top_ = null; static private class Item { Item(Boolean b, Item p) { bool = b; prev = p; } final Boolean bool; final Item prev; } void push(Boolean b) { top_ = new Item(b, top_); } Boolean pop() { Boolean result = top_.bool; top_ = top_.prev; return result; } } /** @associates Node. */ private final NodeListWithPosition nodelistRaw_ = new NodeListWithPosition(); private Vector nodelistFiltered_ = new Vector(); private Enumeration nodesetIterator_ = null; private Object node_ = null; //String or Element private final BooleanStack exprStack_ = new BooleanStack(); /** * @label context */ private/*final (JDK11 problems)*/ Node contextNode_; private boolean multiLevel_; private/*final (JDK11 problems)*/ XPath xpath_; } /** A list of nodes, together with the positions in their context of each node. */ class NodeListWithPosition { Enumeration iterator() { return vector_.elements(); } void removeAllElements() { vector_.removeAllElements(); positions_.clear(); } void add(String string) { vector_.addElement(string); } static private final Integer ONE = new Integer(1); static private final Integer TWO = new Integer(2); static private final Integer THREE = new Integer(3); static private final Integer FOUR = new Integer(4); static private final Integer FIVE = new Integer(5); static private final Integer SIX = new Integer(6); static private final Integer SEVEN = new Integer(7); static private final Integer EIGHT = new Integer(8); static private final Integer NINE = new Integer(9); static private final Integer TEN = new Integer(10); static private Integer identity(Node node) { return new Integer(System.identityHashCode(node)); } void add(Node node, int position) { //Profiling shows thisto be the most heavily used method in Sparta so //optimize the crap out of it. vector_.addElement(node); //Avoid creating new integer objects for common cases Integer posn; switch (position) { case 1: posn = ONE; break; case 2: posn = TWO; break; case 3: posn = THREE; break; case 4: posn = FOUR; break; case 5: posn = FIVE; break; case 6: posn = SIX; break; case 7: posn = SEVEN; break; case 8: posn = EIGHT; break; case 9: posn = NINE; break; case 10: posn = TEN; break; default: posn = new Integer(position); break; } positions_.put(identity(node), posn); } int position(Node node) { return ((Integer) positions_.get(identity(node))).intValue(); } public String toString() { try { StringBuffer y = new StringBuffer("{ "); for (Enumeration i = vector_.elements(); i.hasMoreElements();) { Object e = i.nextElement(); if (e instanceof String) y.append("String(" + e + ") "); else { Node n = (Node) e; y.append("Node(" + n.toXml() + ")[" + positions_.get(identity(n)) + "] "); } } y.append("}"); return y.toString(); } catch (IOException e) { return e.toString(); } } private final Vector vector_ = new Vector(); private Hashtable positions_ = new Hashtable(); } // $Log: XPathVisitor.java,v $ // Revision 1.9 2003/08/11 18:48:39 eobrain // Fix bug in xpath tag[n] when identical elements. // // Revision 1.8 2003/07/17 23:58:40 eobrain // Make compatiblie with J2ME. For example do not use "new" // java.util classes. // // Revision 1.7 2003/05/12 20:06:14 eobrain // Performance improvements: optimize code in areas that profiling revealed to be bottlenecks. // // Revision 1.6 2003/01/27 23:30:58 yuhongx // Replaced Hashtable with HashMap. // // Revision 1.5 2003/01/09 01:10:50 yuhongx // Use JDK1.1 API to make the code work with PersonalJava. // // Revision 1.4 2002/12/05 04:35:39 eobrain // Add support for greater than and less than in predicates. // // Revision 1.3 2002/10/30 16:28:46 eobrain // Feature request [ 630127 ] Support /a/b[text()='foo'] // http://sourceforge.net/projects/sparta-xml/ // // Revision 1.2 2002/09/18 05:29:04 eobrain // Support xpath predicates of the form [1], [2], ... // // Revision 1.1.1.1 2002/08/19 05:03:53 eobrain // import from HP Labs internal CVS // // Revision 1.11 2002/08/18 04:47:47 eob // Make class package-private so as not to clutter up the javadoc. // // Revision 1.10 2002/06/21 00:28:33 eob // Make work with old JDK 1.1.* // // Revision 1.9 2002/06/14 19:34:50 eob // Add handling of "text()" in XPath expressions. // // Revision 1.8 2002/06/04 05:29:28 eob // Simplify use of visitor pattern to make code easier to understand. // Fix bug when predicate in middle of XPath. // // Revision 1.7 2002/05/23 21:18:52 eob // Better error reporting. // // Revision 1.6 2002/05/10 21:39:28 eob // Allow documents to take relative xpaths. // // Revision 1.5 2002/03/26 01:49:53 eob // Return different results depending on type. Return first result. // // Revision 1.4 2002/03/21 23:54:36 eob // Fix handling of .. when no parent. // // Revision 1.3 2002/02/14 02:21:45 eob // Handle attribute XPaths. // // Revision 1.2 2002/02/04 22:09:44 eob // add visit(AttrTest) // // Revision 1.1 2002/02/01 22:46:12 eob // initial




© 2015 - 2024 Weber Informatics LLC | Privacy Policy