summaryrefslogtreecommitdiffstats
path: root/server/src/org/jsoup/select
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/org/jsoup/select')
-rw-r--r--server/src/org/jsoup/select/Collector.java58
-rw-r--r--server/src/org/jsoup/select/CombiningEvaluator.java102
-rw-r--r--server/src/org/jsoup/select/Elements.java704
-rw-r--r--server/src/org/jsoup/select/Evaluator.java474
-rw-r--r--server/src/org/jsoup/select/NodeTraversor.java55
-rw-r--r--server/src/org/jsoup/select/NodeVisitor.java39
-rw-r--r--server/src/org/jsoup/select/QueryParser.java334
-rw-r--r--server/src/org/jsoup/select/Selector.java278
-rw-r--r--server/src/org/jsoup/select/StructuralEvaluator.java152
-rw-r--r--server/src/org/jsoup/select/package-info.java4
10 files changed, 0 insertions, 2200 deletions
diff --git a/server/src/org/jsoup/select/Collector.java b/server/src/org/jsoup/select/Collector.java
deleted file mode 100644
index 20554e8653..0000000000
--- a/server/src/org/jsoup/select/Collector.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package org.jsoup.select;
-
-import org.jsoup.nodes.Element;
-import org.jsoup.nodes.Node;
-
-/**
- * Collects a list of elements that match the supplied criteria.
- *
- * @author Jonathan Hedley
- */
-public class Collector {
-
- private Collector() {
- }
-
- /**
- * Build a list of elements, by visiting root and every descendant of root,
- * and testing it against the evaluator.
- *
- * @param eval
- * Evaluator to test elements against
- * @param root
- * root of tree to descend
- * @return list of matches; empty if none
- */
- public static Elements collect(Evaluator eval, Element root) {
- Elements elements = new Elements();
- new NodeTraversor(new Accumulator(root, elements, eval)).traverse(root);
- return elements;
- }
-
- private static class Accumulator implements NodeVisitor {
- private final Element root;
- private final Elements elements;
- private final Evaluator eval;
-
- Accumulator(Element root, Elements elements, Evaluator eval) {
- this.root = root;
- this.elements = elements;
- this.eval = eval;
- }
-
- @Override
- public void head(Node node, int depth) {
- if (node instanceof Element) {
- Element el = (Element) node;
- if (eval.matches(root, el)) {
- elements.add(el);
- }
- }
- }
-
- @Override
- public void tail(Node node, int depth) {
- // void
- }
- }
-}
diff --git a/server/src/org/jsoup/select/CombiningEvaluator.java b/server/src/org/jsoup/select/CombiningEvaluator.java
deleted file mode 100644
index c3f9a8af2e..0000000000
--- a/server/src/org/jsoup/select/CombiningEvaluator.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package org.jsoup.select;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
-import org.jsoup.helper.StringUtil;
-import org.jsoup.nodes.Element;
-
-/**
- * Base combining (and, or) evaluator.
- */
-abstract class CombiningEvaluator extends Evaluator {
- final List<Evaluator> evaluators;
-
- CombiningEvaluator() {
- super();
- evaluators = new ArrayList<Evaluator>();
- }
-
- CombiningEvaluator(Collection<Evaluator> evaluators) {
- this();
- this.evaluators.addAll(evaluators);
- }
-
- Evaluator rightMostEvaluator() {
- return evaluators.size() > 0 ? evaluators.get(evaluators.size() - 1)
- : null;
- }
-
- void replaceRightMostEvaluator(Evaluator replacement) {
- evaluators.set(evaluators.size() - 1, replacement);
- }
-
- static final class And extends CombiningEvaluator {
- And(Collection<Evaluator> evaluators) {
- super(evaluators);
- }
-
- And(Evaluator... evaluators) {
- this(Arrays.asList(evaluators));
- }
-
- @Override
- public boolean matches(Element root, Element node) {
- for (Evaluator s : evaluators) {
- if (!s.matches(root, node)) {
- return false;
- }
- }
- return true;
- }
-
- @Override
- public String toString() {
- return StringUtil.join(evaluators, " ");
- }
- }
-
- static final class Or extends CombiningEvaluator {
- /**
- * Create a new Or evaluator. The initial evaluators are ANDed together
- * and used as the first clause of the OR.
- *
- * @param evaluators
- * initial OR clause (these are wrapped into an AND
- * evaluator).
- */
- Or(Collection<Evaluator> evaluators) {
- super();
- if (evaluators.size() > 1) {
- this.evaluators.add(new And(evaluators));
- } else {
- this.evaluators.addAll(evaluators);
- }
- }
-
- Or() {
- super();
- }
-
- public void add(Evaluator e) {
- evaluators.add(e);
- }
-
- @Override
- public boolean matches(Element root, Element node) {
- for (Evaluator s : evaluators) {
- if (s.matches(root, node)) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public String toString() {
- return String.format(":or%s", evaluators);
- }
- }
-}
diff --git a/server/src/org/jsoup/select/Elements.java b/server/src/org/jsoup/select/Elements.java
deleted file mode 100644
index cddea67d96..0000000000
--- a/server/src/org/jsoup/select/Elements.java
+++ /dev/null
@@ -1,704 +0,0 @@
-package org.jsoup.select;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.ListIterator;
-
-import org.jsoup.helper.Validate;
-import org.jsoup.nodes.Element;
-import org.jsoup.nodes.Node;
-
-/**
- * A list of {@link Element Elements}, with methods that act on every element in
- * the list.
- * <p/>
- * To get an Elements object, use the {@link Element#select(String)} method.
- *
- * @author Jonathan Hedley, jonathan@hedley.net
- */
-public class Elements implements List<Element>, Cloneable {
- private List<Element> contents;
-
- public Elements() {
- contents = new ArrayList<Element>();
- }
-
- public Elements(int initialCapacity) {
- contents = new ArrayList<Element>(initialCapacity);
- }
-
- public Elements(Collection<Element> elements) {
- contents = new ArrayList<Element>(elements);
- }
-
- public Elements(List<Element> elements) {
- contents = elements;
- }
-
- public Elements(Element... elements) {
- this(Arrays.asList(elements));
- }
-
- @Override
- public Elements clone() {
- List<Element> elements = new ArrayList<Element>();
-
- for (Element e : contents) {
- elements.add(e.clone());
- }
-
- return new Elements(elements);
- }
-
- // attribute methods
- /**
- * Get an attribute value from the first matched element that has the
- * attribute.
- *
- * @param attributeKey
- * The attribute key.
- * @return The attribute value from the first matched element that has the
- * attribute.. If no elements were matched (isEmpty() == true), or
- * if the no elements have the attribute, returns empty string.
- * @see #hasAttr(String)
- */
- public String attr(String attributeKey) {
- for (Element element : contents) {
- if (element.hasAttr(attributeKey)) {
- return element.attr(attributeKey);
- }
- }
- return "";
- }
-
- /**
- * Checks if any of the matched elements have this attribute set.
- *
- * @param attributeKey
- * attribute key
- * @return true if any of the elements have the attribute; false if none do.
- */
- public boolean hasAttr(String attributeKey) {
- for (Element element : contents) {
- if (element.hasAttr(attributeKey)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Set an attribute on all matched elements.
- *
- * @param attributeKey
- * attribute key
- * @param attributeValue
- * attribute value
- * @return this
- */
- public Elements attr(String attributeKey, String attributeValue) {
- for (Element element : contents) {
- element.attr(attributeKey, attributeValue);
- }
- return this;
- }
-
- /**
- * Remove an attribute from every matched element.
- *
- * @param attributeKey
- * The attribute to remove.
- * @return this (for chaining)
- */
- public Elements removeAttr(String attributeKey) {
- for (Element element : contents) {
- element.removeAttr(attributeKey);
- }
- return this;
- }
-
- /**
- * Add the class name to every matched element's {@code class} attribute.
- *
- * @param className
- * class name to add
- * @return this
- */
- public Elements addClass(String className) {
- for (Element element : contents) {
- element.addClass(className);
- }
- return this;
- }
-
- /**
- * Remove the class name from every matched element's {@code class}
- * attribute, if present.
- *
- * @param className
- * class name to remove
- * @return this
- */
- public Elements removeClass(String className) {
- for (Element element : contents) {
- element.removeClass(className);
- }
- return this;
- }
-
- /**
- * Toggle the class name on every matched element's {@code class} attribute.
- *
- * @param className
- * class name to add if missing, or remove if present, from every
- * element.
- * @return this
- */
- public Elements toggleClass(String className) {
- for (Element element : contents) {
- element.toggleClass(className);
- }
- return this;
- }
-
- /**
- * Determine if any of the matched elements have this class name set in
- * their {@code class} attribute.
- *
- * @param className
- * class name to check for
- * @return true if any do, false if none do
- */
- public boolean hasClass(String className) {
- for (Element element : contents) {
- if (element.hasClass(className)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Get the form element's value of the first matched element.
- *
- * @return The form element's value, or empty if not set.
- * @see Element#val()
- */
- public String val() {
- if (size() > 0) {
- return first().val();
- } else {
- return "";
- }
- }
-
- /**
- * Set the form element's value in each of the matched elements.
- *
- * @param value
- * The value to set into each matched element
- * @return this (for chaining)
- */
- public Elements val(String value) {
- for (Element element : contents) {
- element.val(value);
- }
- return this;
- }
-
- /**
- * Get the combined text of all the matched elements.
- * <p>
- * Note that it is possible to get repeats if the matched elements contain
- * both parent elements and their own children, as the Element.text() method
- * returns the combined text of a parent and all its children.
- *
- * @return string of all text: unescaped and no HTML.
- * @see Element#text()
- */
- public String text() {
- StringBuilder sb = new StringBuilder();
- for (Element element : contents) {
- if (sb.length() != 0) {
- sb.append(" ");
- }
- sb.append(element.text());
- }
- return sb.toString();
- }
-
- public boolean hasText() {
- for (Element element : contents) {
- if (element.hasText()) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Get the combined inner HTML of all matched elements.
- *
- * @return string of all element's inner HTML.
- * @see #text()
- * @see #outerHtml()
- */
- public String html() {
- StringBuilder sb = new StringBuilder();
- for (Element element : contents) {
- if (sb.length() != 0) {
- sb.append("\n");
- }
- sb.append(element.html());
- }
- return sb.toString();
- }
-
- /**
- * Get the combined outer HTML of all matched elements.
- *
- * @return string of all element's outer HTML.
- * @see #text()
- * @see #html()
- */
- public String outerHtml() {
- StringBuilder sb = new StringBuilder();
- for (Element element : contents) {
- if (sb.length() != 0) {
- sb.append("\n");
- }
- sb.append(element.outerHtml());
- }
- return sb.toString();
- }
-
- /**
- * Get the combined outer HTML of all matched elements. Alias of
- * {@link #outerHtml()}.
- *
- * @return string of all element's outer HTML.
- * @see #text()
- * @see #html()
- */
- @Override
- public String toString() {
- return outerHtml();
- }
-
- /**
- * Update the tag name of each matched element. For example, to change each
- * {@code <i>} to a {@code <em>}, do {@code doc.select("i").tagName("em");}
- *
- * @param tagName
- * the new tag name
- * @return this, for chaining
- * @see Element#tagName(String)
- */
- public Elements tagName(String tagName) {
- for (Element element : contents) {
- element.tagName(tagName);
- }
- return this;
- }
-
- /**
- * Set the inner HTML of each matched element.
- *
- * @param html
- * HTML to parse and set into each matched element.
- * @return this, for chaining
- * @see Element#html(String)
- */
- public Elements html(String html) {
- for (Element element : contents) {
- element.html(html);
- }
- return this;
- }
-
- /**
- * Add the supplied HTML to the start of each matched element's inner HTML.
- *
- * @param html
- * HTML to add inside each element, before the existing HTML
- * @return this, for chaining
- * @see Element#prepend(String)
- */
- public Elements prepend(String html) {
- for (Element element : contents) {
- element.prepend(html);
- }
- return this;
- }
-
- /**
- * Add the supplied HTML to the end of each matched element's inner HTML.
- *
- * @param html
- * HTML to add inside each element, after the existing HTML
- * @return this, for chaining
- * @see Element#append(String)
- */
- public Elements append(String html) {
- for (Element element : contents) {
- element.append(html);
- }
- return this;
- }
-
- /**
- * Insert the supplied HTML before each matched element's outer HTML.
- *
- * @param html
- * HTML to insert before each element
- * @return this, for chaining
- * @see Element#before(String)
- */
- public Elements before(String html) {
- for (Element element : contents) {
- element.before(html);
- }
- return this;
- }
-
- /**
- * Insert the supplied HTML after each matched element's outer HTML.
- *
- * @param html
- * HTML to insert after each element
- * @return this, for chaining
- * @see Element#after(String)
- */
- public Elements after(String html) {
- for (Element element : contents) {
- element.after(html);
- }
- return this;
- }
-
- /**
- * Wrap the supplied HTML around each matched elements. For example, with
- * HTML {@code <p><b>This</b> is <b>Jsoup</b></p>},
- * <code>doc.select("b").wrap("&lt;i&gt;&lt;/i&gt;");</code> becomes
- * {@code <p><i><b>This</b></i> is <i><b>jsoup</b></i></p>}
- *
- * @param html
- * HTML to wrap around each element, e.g.
- * {@code <div class="head"></div>}. Can be arbitrarily deep.
- * @return this (for chaining)
- * @see Element#wrap
- */
- public Elements wrap(String html) {
- Validate.notEmpty(html);
- for (Element element : contents) {
- element.wrap(html);
- }
- return this;
- }
-
- /**
- * Removes the matched elements from the DOM, and moves their children up
- * into their parents. This has the effect of dropping the elements but
- * keeping their children.
- * <p/>
- * This is useful for e.g removing unwanted formatting elements but keeping
- * their contents.
- * <p/>
- * E.g. with HTML:
- * {@code <div><font>One</font> <font><a href="/">Two</a></font></div>}<br/>
- * {@code doc.select("font").unwrap();}<br/>
- * HTML = {@code <div>One <a href="/">Two</a></div>}
- *
- * @return this (for chaining)
- * @see Node#unwrap
- */
- public Elements unwrap() {
- for (Element element : contents) {
- element.unwrap();
- }
- return this;
- }
-
- /**
- * Empty (remove all child nodes from) each matched element. This is similar
- * to setting the inner HTML of each element to nothing.
- * <p>
- * E.g. HTML: {@code <div><p>Hello <b>there</b></p> <p>now</p></div>}<br>
- * <code>doc.select("p").empty();</code><br>
- * HTML = {@code <div>
- * <p></p>
- * <p></p>
- * </div>}
- *
- * @return this, for chaining
- * @see Element#empty()
- * @see #remove()
- */
- public Elements empty() {
- for (Element element : contents) {
- element.empty();
- }
- return this;
- }
-
- /**
- * Remove each matched element from the DOM. This is similar to setting the
- * outer HTML of each element to nothing.
- * <p>
- * E.g. HTML: {@code <div><p>Hello</p> <p>there</p> <img /></div>}<br>
- * <code>doc.select("p").remove();</code><br>
- * HTML = {@code <div> <img /></div>}
- * <p>
- * Note that this method should not be used to clean user-submitted HTML;
- * rather, use {@link org.jsoup.safety.Cleaner} to clean HTML.
- *
- * @return this, for chaining
- * @see Element#empty()
- * @see #empty()
- */
- public Elements remove() {
- for (Element element : contents) {
- element.remove();
- }
- return this;
- }
-
- // filters
-
- /**
- * Find matching elements within this element list.
- *
- * @param query
- * A {@link Selector} query
- * @return the filtered list of elements, or an empty list if none match.
- */
- public Elements select(String query) {
- return Selector.select(query, this);
- }
-
- /**
- * Remove elements from this list that match the {@link Selector} query.
- * <p>
- * E.g. HTML: {@code <div class=logo>One</div> <div>Two</div>}<br>
- * <code>Elements divs = doc.select("div").not("#logo");</code><br>
- * Result: {@code divs: [<div>Two</div>]}
- * <p>
- *
- * @param query
- * the selector query whose results should be removed from these
- * elements
- * @return a new elements list that contains only the filtered results
- */
- public Elements not(String query) {
- Elements out = Selector.select(query, this);
- return Selector.filterOut(this, out);
- }
-
- /**
- * Get the <i>nth</i> matched element as an Elements object.
- * <p>
- * See also {@link #get(int)} to retrieve an Element.
- *
- * @param index
- * the (zero-based) index of the element in the list to retain
- * @return Elements containing only the specified element, or, if that
- * element did not exist, an empty list.
- */
- public Elements eq(int index) {
- return contents.size() > index ? new Elements(get(index))
- : new Elements();
- }
-
- /**
- * Test if any of the matched elements match the supplied query.
- *
- * @param query
- * A selector
- * @return true if at least one element in the list matches the query.
- */
- public boolean is(String query) {
- Elements children = select(query);
- return !children.isEmpty();
- }
-
- /**
- * Get all of the parents and ancestor elements of the matched elements.
- *
- * @return all of the parents and ancestor elements of the matched elements
- */
- public Elements parents() {
- HashSet<Element> combo = new LinkedHashSet<Element>();
- for (Element e : contents) {
- combo.addAll(e.parents());
- }
- return new Elements(combo);
- }
-
- // list-like methods
- /**
- * Get the first matched element.
- *
- * @return The first matched element, or <code>null</code> if contents is
- * empty;
- */
- public Element first() {
- return contents.isEmpty() ? null : contents.get(0);
- }
-
- /**
- * Get the last matched element.
- *
- * @return The last matched element, or <code>null</code> if contents is
- * empty.
- */
- public Element last() {
- return contents.isEmpty() ? null : contents.get(contents.size() - 1);
- }
-
- /**
- * Perform a depth-first traversal on each of the selected elements.
- *
- * @param nodeVisitor
- * the visitor callbacks to perform on each node
- * @return this, for chaining
- */
- public Elements traverse(NodeVisitor nodeVisitor) {
- Validate.notNull(nodeVisitor);
- NodeTraversor traversor = new NodeTraversor(nodeVisitor);
- for (Element el : contents) {
- traversor.traverse(el);
- }
- return this;
- }
-
- // implements List<Element> delegates:
- @Override
- public int size() {
- return contents.size();
- }
-
- @Override
- public boolean isEmpty() {
- return contents.isEmpty();
- }
-
- @Override
- public boolean contains(Object o) {
- return contents.contains(o);
- }
-
- @Override
- public Iterator<Element> iterator() {
- return contents.iterator();
- }
-
- @Override
- public Object[] toArray() {
- return contents.toArray();
- }
-
- @Override
- public <T> T[] toArray(T[] a) {
- return contents.toArray(a);
- }
-
- @Override
- public boolean add(Element element) {
- return contents.add(element);
- }
-
- @Override
- public boolean remove(Object o) {
- return contents.remove(o);
- }
-
- @Override
- public boolean containsAll(Collection<?> c) {
- return contents.containsAll(c);
- }
-
- @Override
- public boolean addAll(Collection<? extends Element> c) {
- return contents.addAll(c);
- }
-
- @Override
- public boolean addAll(int index, Collection<? extends Element> c) {
- return contents.addAll(index, c);
- }
-
- @Override
- public boolean removeAll(Collection<?> c) {
- return contents.removeAll(c);
- }
-
- @Override
- public boolean retainAll(Collection<?> c) {
- return contents.retainAll(c);
- }
-
- @Override
- public void clear() {
- contents.clear();
- }
-
- @Override
- public boolean equals(Object o) {
- return contents.equals(o);
- }
-
- @Override
- public int hashCode() {
- return contents.hashCode();
- }
-
- @Override
- public Element get(int index) {
- return contents.get(index);
- }
-
- @Override
- public Element set(int index, Element element) {
- return contents.set(index, element);
- }
-
- @Override
- public void add(int index, Element element) {
- contents.add(index, element);
- }
-
- @Override
- public Element remove(int index) {
- return contents.remove(index);
- }
-
- @Override
- public int indexOf(Object o) {
- return contents.indexOf(o);
- }
-
- @Override
- public int lastIndexOf(Object o) {
- return contents.lastIndexOf(o);
- }
-
- @Override
- public ListIterator<Element> listIterator() {
- return contents.listIterator();
- }
-
- @Override
- public ListIterator<Element> listIterator(int index) {
- return contents.listIterator(index);
- }
-
- @Override
- public List<Element> subList(int fromIndex, int toIndex) {
- return contents.subList(fromIndex, toIndex);
- }
-}
diff --git a/server/src/org/jsoup/select/Evaluator.java b/server/src/org/jsoup/select/Evaluator.java
deleted file mode 100644
index 5dd4c91616..0000000000
--- a/server/src/org/jsoup/select/Evaluator.java
+++ /dev/null
@@ -1,474 +0,0 @@
-package org.jsoup.select;
-
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.jsoup.helper.Validate;
-import org.jsoup.nodes.Element;
-
-/**
- * Evaluates that an element matches the selector.
- */
-public abstract class Evaluator {
- protected Evaluator() {
- }
-
- /**
- * Test if the element meets the evaluator's requirements.
- *
- * @param root
- * UI of the matching subtree
- * @param element
- * tested element
- */
- public abstract boolean matches(Element root, Element element);
-
- /**
- * Evaluator for tag name
- */
- public static final class Tag extends Evaluator {
- private String tagName;
-
- public Tag(String tagName) {
- this.tagName = tagName;
- }
-
- @Override
- public boolean matches(Element root, Element element) {
- return (element.tagName().equals(tagName));
- }
-
- @Override
- public String toString() {
- return String.format("%s", tagName);
- }
- }
-
- /**
- * Evaluator for element id
- */
- public static final class Id extends Evaluator {
- private String id;
-
- public Id(String id) {
- this.id = id;
- }
-
- @Override
- public boolean matches(Element root, Element element) {
- return (id.equals(element.id()));
- }
-
- @Override
- public String toString() {
- return String.format("#%s", id);
- }
-
- }
-
- /**
- * Evaluator for element class
- */
- public static final class Class extends Evaluator {
- private String className;
-
- public Class(String className) {
- this.className = className;
- }
-
- @Override
- public boolean matches(Element root, Element element) {
- return (element.hasClass(className));
- }
-
- @Override
- public String toString() {
- return String.format(".%s", className);
- }
-
- }
-
- /**
- * Evaluator for attribute name matching
- */
- public static final class Attribute extends Evaluator {
- private String key;
-
- public Attribute(String key) {
- this.key = key;
- }
-
- @Override
- public boolean matches(Element root, Element element) {
- return element.hasAttr(key);
- }
-
- @Override
- public String toString() {
- return String.format("[%s]", key);
- }
-
- }
-
- /**
- * Evaluator for attribute name prefix matching
- */
- public static final class AttributeStarting extends Evaluator {
- private String keyPrefix;
-
- public AttributeStarting(String keyPrefix) {
- this.keyPrefix = keyPrefix;
- }
-
- @Override
- public boolean matches(Element root, Element element) {
- List<org.jsoup.nodes.Attribute> values = element.attributes()
- .asList();
- for (org.jsoup.nodes.Attribute attribute : values) {
- if (attribute.getKey().startsWith(keyPrefix)) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public String toString() {
- return String.format("[^%s]", keyPrefix);
- }
-
- }
-
- /**
- * Evaluator for attribute name/value matching
- */
- public static final class AttributeWithValue extends AttributeKeyPair {
- public AttributeWithValue(String key, String value) {
- super(key, value);
- }
-
- @Override
- public boolean matches(Element root, Element element) {
- return element.hasAttr(key)
- && value.equalsIgnoreCase(element.attr(key));
- }
-
- @Override
- public String toString() {
- return String.format("[%s=%s]", key, value);
- }
-
- }
-
- /**
- * Evaluator for attribute name != value matching
- */
- public static final class AttributeWithValueNot extends AttributeKeyPair {
- public AttributeWithValueNot(String key, String value) {
- super(key, value);
- }
-
- @Override
- public boolean matches(Element root, Element element) {
- return !value.equalsIgnoreCase(element.attr(key));
- }
-
- @Override
- public String toString() {
- return String.format("[%s!=%s]", key, value);
- }
-
- }
-
- /**
- * Evaluator for attribute name/value matching (value prefix)
- */
- public static final class AttributeWithValueStarting extends
- AttributeKeyPair {
- public AttributeWithValueStarting(String key, String value) {
- super(key, value);
- }
-
- @Override
- public boolean matches(Element root, Element element) {
- return element.hasAttr(key)
- && element.attr(key).toLowerCase().startsWith(value); // value
- // is
- // lower
- // case
- // already
- }
-
- @Override
- public String toString() {
- return String.format("[%s^=%s]", key, value);
- }
-
- }
-
- /**
- * Evaluator for attribute name/value matching (value ending)
- */
- public static final class AttributeWithValueEnding extends AttributeKeyPair {
- public AttributeWithValueEnding(String key, String value) {
- super(key, value);
- }
-
- @Override
- public boolean matches(Element root, Element element) {
- return element.hasAttr(key)
- && element.attr(key).toLowerCase().endsWith(value); // value
- // is
- // lower
- // case
- }
-
- @Override
- public String toString() {
- return String.format("[%s$=%s]", key, value);
- }
-
- }
-
- /**
- * Evaluator for attribute name/value matching (value containing)
- */
- public static final class AttributeWithValueContaining extends
- AttributeKeyPair {
- public AttributeWithValueContaining(String key, String value) {
- super(key, value);
- }
-
- @Override
- public boolean matches(Element root, Element element) {
- return element.hasAttr(key)
- && element.attr(key).toLowerCase().contains(value); // value
- // is
- // lower
- // case
- }
-
- @Override
- public String toString() {
- return String.format("[%s*=%s]", key, value);
- }
-
- }
-
- /**
- * Evaluator for attribute name/value matching (value regex matching)
- */
- public static final class AttributeWithValueMatching extends Evaluator {
- String key;
- Pattern pattern;
-
- public AttributeWithValueMatching(String key, Pattern pattern) {
- this.key = key.trim().toLowerCase();
- this.pattern = pattern;
- }
-
- @Override
- public boolean matches(Element root, Element element) {
- return element.hasAttr(key)
- && pattern.matcher(element.attr(key)).find();
- }
-
- @Override
- public String toString() {
- return String.format("[%s~=%s]", key, pattern.toString());
- }
-
- }
-
- /**
- * Abstract evaluator for attribute name/value matching
- */
- public abstract static class AttributeKeyPair extends Evaluator {
- String key;
- String value;
-
- public AttributeKeyPair(String key, String value) {
- Validate.notEmpty(key);
- Validate.notEmpty(value);
-
- this.key = key.trim().toLowerCase();
- this.value = value.trim().toLowerCase();
- }
- }
-
- /**
- * Evaluator for any / all element matching
- */
- public static final class AllElements extends Evaluator {
-
- @Override
- public boolean matches(Element root, Element element) {
- return true;
- }
-
- @Override
- public String toString() {
- return "*";
- }
- }
-
- /**
- * Evaluator for matching by sibling index number (e < idx)
- */
- public static final class IndexLessThan extends IndexEvaluator {
- public IndexLessThan(int index) {
- super(index);
- }
-
- @Override
- public boolean matches(Element root, Element element) {
- return element.elementSiblingIndex() < index;
- }
-
- @Override
- public String toString() {
- return String.format(":lt(%d)", index);
- }
-
- }
-
- /**
- * Evaluator for matching by sibling index number (e > idx)
- */
- public static final class IndexGreaterThan extends IndexEvaluator {
- public IndexGreaterThan(int index) {
- super(index);
- }
-
- @Override
- public boolean matches(Element root, Element element) {
- return element.elementSiblingIndex() > index;
- }
-
- @Override
- public String toString() {
- return String.format(":gt(%d)", index);
- }
-
- }
-
- /**
- * Evaluator for matching by sibling index number (e = idx)
- */
- public static final class IndexEquals extends IndexEvaluator {
- public IndexEquals(int index) {
- super(index);
- }
-
- @Override
- public boolean matches(Element root, Element element) {
- return element.elementSiblingIndex() == index;
- }
-
- @Override
- public String toString() {
- return String.format(":eq(%d)", index);
- }
-
- }
-
- /**
- * Abstract evaluator for sibling index matching
- *
- * @author ant
- */
- public abstract static class IndexEvaluator extends Evaluator {
- int index;
-
- public IndexEvaluator(int index) {
- this.index = index;
- }
- }
-
- /**
- * Evaluator for matching Element (and its descendants) text
- */
- public static final class ContainsText extends Evaluator {
- private String searchText;
-
- public ContainsText(String searchText) {
- this.searchText = searchText.toLowerCase();
- }
-
- @Override
- public boolean matches(Element root, Element element) {
- return (element.text().toLowerCase().contains(searchText));
- }
-
- @Override
- public String toString() {
- return String.format(":contains(%s", searchText);
- }
- }
-
- /**
- * Evaluator for matching Element's own text
- */
- public static final class ContainsOwnText extends Evaluator {
- private String searchText;
-
- public ContainsOwnText(String searchText) {
- this.searchText = searchText.toLowerCase();
- }
-
- @Override
- public boolean matches(Element root, Element element) {
- return (element.ownText().toLowerCase().contains(searchText));
- }
-
- @Override
- public String toString() {
- return String.format(":containsOwn(%s", searchText);
- }
- }
-
- /**
- * Evaluator for matching Element (and its descendants) text with regex
- */
- public static final class Matches extends Evaluator {
- private Pattern pattern;
-
- public Matches(Pattern pattern) {
- this.pattern = pattern;
- }
-
- @Override
- public boolean matches(Element root, Element element) {
- Matcher m = pattern.matcher(element.text());
- return m.find();
- }
-
- @Override
- public String toString() {
- return String.format(":matches(%s", pattern);
- }
- }
-
- /**
- * Evaluator for matching Element's own text with regex
- */
- public static final class MatchesOwn extends Evaluator {
- private Pattern pattern;
-
- public MatchesOwn(Pattern pattern) {
- this.pattern = pattern;
- }
-
- @Override
- public boolean matches(Element root, Element element) {
- Matcher m = pattern.matcher(element.ownText());
- return m.find();
- }
-
- @Override
- public String toString() {
- return String.format(":matchesOwn(%s", pattern);
- }
- }
-}
diff --git a/server/src/org/jsoup/select/NodeTraversor.java b/server/src/org/jsoup/select/NodeTraversor.java
deleted file mode 100644
index f94a7762fc..0000000000
--- a/server/src/org/jsoup/select/NodeTraversor.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package org.jsoup.select;
-
-import org.jsoup.nodes.Node;
-
-/**
- * Depth-first node traversor. Use to iterate through all nodes under and
- * including the specified root node.
- * <p/>
- * This implementation does not use recursion, so a deep DOM does not risk
- * blowing the stack.
- */
-public class NodeTraversor {
- private NodeVisitor visitor;
-
- /**
- * Create a new traversor.
- *
- * @param visitor
- * a class implementing the {@link NodeVisitor} interface, to be
- * called when visiting each node.
- */
- public NodeTraversor(NodeVisitor visitor) {
- this.visitor = visitor;
- }
-
- /**
- * Start a depth-first traverse of the root and all of its descendants.
- *
- * @param root
- * the root node point to traverse.
- */
- public void traverse(Node root) {
- Node node = root;
- int depth = 0;
-
- while (node != null) {
- visitor.head(node, depth);
- if (node.childNodes().size() > 0) {
- node = node.childNode(0);
- depth++;
- } else {
- while (node.nextSibling() == null && depth > 0) {
- visitor.tail(node, depth);
- node = node.parent();
- depth--;
- }
- visitor.tail(node, depth);
- if (node == root) {
- break;
- }
- node = node.nextSibling();
- }
- }
- }
-}
diff --git a/server/src/org/jsoup/select/NodeVisitor.java b/server/src/org/jsoup/select/NodeVisitor.java
deleted file mode 100644
index 9e827d6c55..0000000000
--- a/server/src/org/jsoup/select/NodeVisitor.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.jsoup.select;
-
-import org.jsoup.nodes.Node;
-
-/**
- * Node visitor interface. Provide an implementing class to
- * {@link NodeTraversor} to iterate through nodes.
- * <p/>
- * This interface provides two methods, {@code head} and {@code tail}. The head
- * method is called when the node is first seen, and the tail method when all of
- * the node's children have been visited. As an example, head can be used to
- * create a start tag for a node, and tail to create the end tag.
- */
-public interface NodeVisitor {
- /**
- * Callback for when a node is first visited.
- *
- * @param node
- * the node being visited.
- * @param depth
- * the depth of the node, relative to the root node. E.g., the
- * root node has depth 0, and a child node of that will have
- * depth 1.
- */
- public void head(Node node, int depth);
-
- /**
- * Callback for when a node is last visited, after all of its descendants
- * have been visited.
- *
- * @param node
- * the node being visited.
- * @param depth
- * the depth of the node, relative to the root node. E.g., the
- * root node has depth 0, and a child node of that will have
- * depth 1.
- */
- public void tail(Node node, int depth);
-}
diff --git a/server/src/org/jsoup/select/QueryParser.java b/server/src/org/jsoup/select/QueryParser.java
deleted file mode 100644
index 7a04899d82..0000000000
--- a/server/src/org/jsoup/select/QueryParser.java
+++ /dev/null
@@ -1,334 +0,0 @@
-package org.jsoup.select;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Pattern;
-
-import org.jsoup.helper.StringUtil;
-import org.jsoup.helper.Validate;
-import org.jsoup.parser.TokenQueue;
-
-/**
- * Parses a CSS selector into an Evaluator tree.
- */
-class QueryParser {
- private final static String[] combinators = { ",", ">", "+", "~", " " };
-
- private TokenQueue tq;
- private String query;
- private List<Evaluator> evals = new ArrayList<Evaluator>();
-
- /**
- * Create a new QueryParser.
- *
- * @param query
- * CSS query
- */
- private QueryParser(String query) {
- this.query = query;
- tq = new TokenQueue(query);
- }
-
- /**
- * Parse a CSS query into an Evaluator.
- *
- * @param query
- * CSS query
- * @return Evaluator
- */
- public static Evaluator parse(String query) {
- QueryParser p = new QueryParser(query);
- return p.parse();
- }
-
- /**
- * Parse the query
- *
- * @return Evaluator
- */
- Evaluator parse() {
- tq.consumeWhitespace();
-
- if (tq.matchesAny(combinators)) { // if starts with a combinator, use
- // root as elements
- evals.add(new StructuralEvaluator.Root());
- combinator(tq.consume());
- } else {
- findElements();
- }
-
- while (!tq.isEmpty()) {
- // hierarchy and extras
- boolean seenWhite = tq.consumeWhitespace();
-
- if (tq.matchesAny(combinators)) {
- combinator(tq.consume());
- } else if (seenWhite) {
- combinator(' ');
- } else { // E.class, E#id, E[attr] etc. AND
- findElements(); // take next el, #. etc off queue
- }
- }
-
- if (evals.size() == 1) {
- return evals.get(0);
- }
-
- return new CombiningEvaluator.And(evals);
- }
-
- private void combinator(char combinator) {
- tq.consumeWhitespace();
- String subQuery = consumeSubQuery(); // support multi > childs
-
- Evaluator rootEval; // the new topmost evaluator
- Evaluator currentEval; // the evaluator the new eval will be combined
- // to. could be root, or rightmost or.
- Evaluator newEval = parse(subQuery); // the evaluator to add into target
- // evaluator
- boolean replaceRightMost = false;
-
- if (evals.size() == 1) {
- rootEval = currentEval = evals.get(0);
- // make sure OR (,) has precedence:
- if (rootEval instanceof CombiningEvaluator.Or && combinator != ',') {
- currentEval = ((CombiningEvaluator.Or) currentEval)
- .rightMostEvaluator();
- replaceRightMost = true;
- }
- } else {
- rootEval = currentEval = new CombiningEvaluator.And(evals);
- }
- evals.clear();
-
- // for most combinators: change the current eval into an AND of the
- // current eval and the new eval
- if (combinator == '>') {
- currentEval = new CombiningEvaluator.And(newEval,
- new StructuralEvaluator.ImmediateParent(currentEval));
- } else if (combinator == ' ') {
- currentEval = new CombiningEvaluator.And(newEval,
- new StructuralEvaluator.Parent(currentEval));
- } else if (combinator == '+') {
- currentEval = new CombiningEvaluator.And(newEval,
- new StructuralEvaluator.ImmediatePreviousSibling(
- currentEval));
- } else if (combinator == '~') {
- currentEval = new CombiningEvaluator.And(newEval,
- new StructuralEvaluator.PreviousSibling(currentEval));
- } else if (combinator == ',') { // group or.
- CombiningEvaluator.Or or;
- if (currentEval instanceof CombiningEvaluator.Or) {
- or = (CombiningEvaluator.Or) currentEval;
- or.add(newEval);
- } else {
- or = new CombiningEvaluator.Or();
- or.add(currentEval);
- or.add(newEval);
- }
- currentEval = or;
- } else {
- throw new Selector.SelectorParseException("Unknown combinator: "
- + combinator);
- }
-
- if (replaceRightMost) {
- ((CombiningEvaluator.Or) rootEval)
- .replaceRightMostEvaluator(currentEval);
- } else {
- rootEval = currentEval;
- }
- evals.add(rootEval);
- }
-
- private String consumeSubQuery() {
- StringBuilder sq = new StringBuilder();
- while (!tq.isEmpty()) {
- if (tq.matches("(")) {
- sq.append("(").append(tq.chompBalanced('(', ')')).append(")");
- } else if (tq.matches("[")) {
- sq.append("[").append(tq.chompBalanced('[', ']')).append("]");
- } else if (tq.matchesAny(combinators)) {
- break;
- } else {
- sq.append(tq.consume());
- }
- }
- return sq.toString();
- }
-
- private void findElements() {
- if (tq.matchChomp("#")) {
- byId();
- } else if (tq.matchChomp(".")) {
- byClass();
- } else if (tq.matchesWord()) {
- byTag();
- } else if (tq.matches("[")) {
- byAttribute();
- } else if (tq.matchChomp("*")) {
- allElements();
- } else if (tq.matchChomp(":lt(")) {
- indexLessThan();
- } else if (tq.matchChomp(":gt(")) {
- indexGreaterThan();
- } else if (tq.matchChomp(":eq(")) {
- indexEquals();
- } else if (tq.matches(":has(")) {
- has();
- } else if (tq.matches(":contains(")) {
- contains(false);
- } else if (tq.matches(":containsOwn(")) {
- contains(true);
- } else if (tq.matches(":matches(")) {
- matches(false);
- } else if (tq.matches(":matchesOwn(")) {
- matches(true);
- } else if (tq.matches(":not(")) {
- not();
- } else {
- throw new Selector.SelectorParseException(
- "Could not parse query '%s': unexpected token at '%s'",
- query, tq.remainder());
- }
-
- }
-
- private void byId() {
- String id = tq.consumeCssIdentifier();
- Validate.notEmpty(id);
- evals.add(new Evaluator.Id(id));
- }
-
- private void byClass() {
- String className = tq.consumeCssIdentifier();
- Validate.notEmpty(className);
- evals.add(new Evaluator.Class(className.trim().toLowerCase()));
- }
-
- private void byTag() {
- String tagName = tq.consumeElementSelector();
- Validate.notEmpty(tagName);
-
- // namespaces: if element name is "abc:def", selector must be "abc|def",
- // so flip:
- if (tagName.contains("|")) {
- tagName = tagName.replace("|", ":");
- }
-
- evals.add(new Evaluator.Tag(tagName.trim().toLowerCase()));
- }
-
- private void byAttribute() {
- TokenQueue cq = new TokenQueue(tq.chompBalanced('[', ']')); // content
- // queue
- String key = cq.consumeToAny("=", "!=", "^=", "$=", "*=", "~="); // eq,
- // not,
- // start,
- // end,
- // contain,
- // match,
- // (no
- // val)
- Validate.notEmpty(key);
- cq.consumeWhitespace();
-
- if (cq.isEmpty()) {
- if (key.startsWith("^")) {
- evals.add(new Evaluator.AttributeStarting(key.substring(1)));
- } else {
- evals.add(new Evaluator.Attribute(key));
- }
- } else {
- if (cq.matchChomp("=")) {
- evals.add(new Evaluator.AttributeWithValue(key, cq.remainder()));
- } else if (cq.matchChomp("!=")) {
- evals.add(new Evaluator.AttributeWithValueNot(key, cq
- .remainder()));
- } else if (cq.matchChomp("^=")) {
- evals.add(new Evaluator.AttributeWithValueStarting(key, cq
- .remainder()));
- } else if (cq.matchChomp("$=")) {
- evals.add(new Evaluator.AttributeWithValueEnding(key, cq
- .remainder()));
- } else if (cq.matchChomp("*=")) {
- evals.add(new Evaluator.AttributeWithValueContaining(key, cq
- .remainder()));
- } else if (cq.matchChomp("~=")) {
- evals.add(new Evaluator.AttributeWithValueMatching(key, Pattern
- .compile(cq.remainder())));
- } else {
- throw new Selector.SelectorParseException(
- "Could not parse attribute query '%s': unexpected token at '%s'",
- query, cq.remainder());
- }
- }
- }
-
- private void allElements() {
- evals.add(new Evaluator.AllElements());
- }
-
- // pseudo selectors :lt, :gt, :eq
- private void indexLessThan() {
- evals.add(new Evaluator.IndexLessThan(consumeIndex()));
- }
-
- private void indexGreaterThan() {
- evals.add(new Evaluator.IndexGreaterThan(consumeIndex()));
- }
-
- private void indexEquals() {
- evals.add(new Evaluator.IndexEquals(consumeIndex()));
- }
-
- private int consumeIndex() {
- String indexS = tq.chompTo(")").trim();
- Validate.isTrue(StringUtil.isNumeric(indexS), "Index must be numeric");
- return Integer.parseInt(indexS);
- }
-
- // pseudo selector :has(el)
- private void has() {
- tq.consume(":has");
- String subQuery = tq.chompBalanced('(', ')');
- Validate.notEmpty(subQuery, ":has(el) subselect must not be empty");
- evals.add(new StructuralEvaluator.Has(parse(subQuery)));
- }
-
- // pseudo selector :contains(text), containsOwn(text)
- private void contains(boolean own) {
- tq.consume(own ? ":containsOwn" : ":contains");
- String searchText = TokenQueue.unescape(tq.chompBalanced('(', ')'));
- Validate.notEmpty(searchText, ":contains(text) query must not be empty");
- if (own) {
- evals.add(new Evaluator.ContainsOwnText(searchText));
- } else {
- evals.add(new Evaluator.ContainsText(searchText));
- }
- }
-
- // :matches(regex), matchesOwn(regex)
- private void matches(boolean own) {
- tq.consume(own ? ":matchesOwn" : ":matches");
- String regex = tq.chompBalanced('(', ')'); // don't unescape, as regex
- // bits will be escaped
- Validate.notEmpty(regex, ":matches(regex) query must not be empty");
-
- if (own) {
- evals.add(new Evaluator.MatchesOwn(Pattern.compile(regex)));
- } else {
- evals.add(new Evaluator.Matches(Pattern.compile(regex)));
- }
- }
-
- // :not(selector)
- private void not() {
- tq.consume(":not");
- String subQuery = tq.chompBalanced('(', ')');
- Validate.notEmpty(subQuery,
- ":not(selector) subselect must not be empty");
-
- evals.add(new StructuralEvaluator.Not(parse(subQuery)));
- }
-}
diff --git a/server/src/org/jsoup/select/Selector.java b/server/src/org/jsoup/select/Selector.java
deleted file mode 100644
index d5ea6f2dc9..0000000000
--- a/server/src/org/jsoup/select/Selector.java
+++ /dev/null
@@ -1,278 +0,0 @@
-package org.jsoup.select;
-
-import java.util.Collection;
-import java.util.LinkedHashSet;
-
-import org.jsoup.helper.Validate;
-import org.jsoup.nodes.Element;
-
-/**
- * CSS-like element selector, that finds elements matching a query.
- * <p/>
- * <h2>Selector syntax</h2>
- * A selector is a chain of simple selectors, separated by combinators.
- * Selectors are case insensitive (including against elements, attributes, and
- * attribute values).
- * <p/>
- * The universal selector (*) is implicit when no element selector is supplied
- * (i.e. {@code *.header} and {@code .header} is equivalent).
- * <p/>
- * <table>
- * <tr>
- * <th>Pattern</th>
- * <th>Matches</th>
- * <th>Example</th>
- * </tr>
- * <tr>
- * <td><code>*</code></td>
- * <td>any element</td>
- * <td><code>*</code></td>
- * </tr>
- * <tr>
- * <td><code>tag</code></td>
- * <td>elements with the given tag name</td>
- * <td><code>div</code></td>
- * </tr>
- * <tr>
- * <td><code>ns|E</code></td>
- * <td>elements of type E in the namespace <i>ns</i></td>
- * <td><code>fb|name</code> finds <code>&lt;fb:name></code> elements</td>
- * </tr>
- * <tr>
- * <td><code>#id</code></td>
- * <td>elements with attribute ID of "id"</td>
- * <td><code>div#wrap</code>, <code>#logo</code></td>
- * </tr>
- * <tr>
- * <td><code>.class</code></td>
- * <td>elements with a class name of "class"</td>
- * <td><code>div.left</code>, <code>.result</code></td>
- * </tr>
- * <tr>
- * <td><code>[attr]</code></td>
- * <td>elements with an attribute named "attr" (with any value)</td>
- * <td><code>a[href]</code>, <code>[title]</code></td>
- * </tr>
- * <tr>
- * <td><code>[^attrPrefix]</code></td>
- * <td>elements with an attribute name starting with "attrPrefix". Use to find
- * elements with HTML5 datasets</td>
- * <td><code>[^data-]</code>, <code>div[^data-]</code></td>
- * </tr>
- * <tr>
- * <td><code>[attr=val]</code></td>
- * <td>elements with an attribute named "attr", and value equal to "val"</td>
- * <td><code>img[width=500]</code>, <code>a[rel=nofollow]</code></td>
- * </tr>
- * <tr>
- * <td><code>[attr^=valPrefix]</code></td>
- * <td>elements with an attribute named "attr", and value starting with
- * "valPrefix"</td>
- * <td><code>a[href^=http:]</code></code></td>
- * </tr>
- * <tr>
- * <td><code>[attr$=valSuffix]</code></td>
- * <td>elements with an attribute named "attr", and value ending with
- * "valSuffix"</td>
- * <td><code>img[src$=.png]</code></td>
- * </tr>
- * <tr>
- * <td><code>[attr*=valContaining]</code></td>
- * <td>elements with an attribute named "attr", and value containing
- * "valContaining"</td>
- * <td><code>a[href*=/search/]</code></td>
- * </tr>
- * <tr>
- * <td><code>[attr~=<em>regex</em>]</code></td>
- * <td>elements with an attribute named "attr", and value matching the regular
- * expression</td>
- * <td><code>img[src~=(?i)\\.(png|jpe?g)]</code></td>
- * </tr>
- * <tr>
- * <td></td>
- * <td>The above may be combined in any order</td>
- * <td><code>div.header[title]</code></td>
- * </tr>
- * <tr>
- * <td>
- * <td colspan="3">
- * <h3>Combinators</h3></td>
- * </tr>
- * <tr>
- * <td><code>E F</code></td>
- * <td>an F element descended from an E element</td>
- * <td><code>div a</code>, <code>.logo h1</code></td>
- * </tr>
- * <tr>
- * <td><code>E > F</code></td>
- * <td>an F direct child of E</td>
- * <td><code>ol > li</code></td>
- * </tr>
- * <tr>
- * <td><code>E + F</code></td>
- * <td>an F element immediately preceded by sibling E</td>
- * <td><code>li + li</code>, <code>div.head + div</code></td>
- * </tr>
- * <tr>
- * <td><code>E ~ F</code></td>
- * <td>an F element preceded by sibling E</td>
- * <td><code>h1 ~ p</code></td>
- * </tr>
- * <tr>
- * <td><code>E, F, G</code></td>
- * <td>all matching elements E, F, or G</td>
- * <td><code>a[href], div, h3</code></td>
- * </tr>
- * <tr>
- * <td>
- * <td colspan="3">
- * <h3>Pseudo selectors</h3></td>
- * </tr>
- * <tr>
- * <td><code>:lt(<em>n</em>)</code></td>
- * <td>elements whose sibling index is less than <em>n</em></td>
- * <td><code>td:lt(3)</code> finds the first 2 cells of each row</td>
- * </tr>
- * <tr>
- * <td><code>:gt(<em>n</em>)</code></td>
- * <td>elements whose sibling index is greater than <em>n</em></td>
- * <td><code>td:gt(1)</code> finds cells after skipping the first two</td>
- * </tr>
- * <tr>
- * <td><code>:eq(<em>n</em>)</code></td>
- * <td>elements whose sibling index is equal to <em>n</em></td>
- * <td><code>td:eq(0)</code> finds the first cell of each row</td>
- * </tr>
- * <tr>
- * <td><code>:has(<em>selector</em>)</code></td>
- * <td>elements that contains at least one element matching the
- * <em>selector</em></td>
- * <td><code>div:has(p)</code> finds divs that contain p elements</td>
- * </tr>
- * <tr>
- * <td><code>:not(<em>selector</em>)</code></td>
- * <td>elements that do not match the <em>selector</em>. See also
- * {@link Elements#not(String)}</td>
- * <td><code>div:not(.logo)</code> finds all divs that do not have the "logo"
- * class.<br />
- * <code>div:not(:has(div))</code> finds divs that do not contain divs.</code></td>
- * </tr>
- * <tr>
- * <td><code>:contains(<em>text</em>)</code></td>
- * <td>elements that contains the specified text. The search is case
- * insensitive. The text may appear in the found element, or any of its
- * descendants.</td>
- * <td><code>p:contains(jsoup)</code> finds p elements containing the text
- * "jsoup".</td>
- * </tr>
- * <tr>
- * <td><code>:matches(<em>regex</em>)</code></td>
- * <td>elements whose text matches the specified regular expression. The text
- * may appear in the found element, or any of its descendants.</td>
- * <td><code>td:matches(\\d+)</code> finds table cells containing digits.
- * <code>div:matches((?i)login)</code> finds divs containing the text, case
- * insensitively.</td>
- * </tr>
- * <tr>
- * <td><code>:containsOwn(<em>text</em>)</code></td>
- * <td>elements that directly contains the specified text. The search is case
- * insensitive. The text must appear in the found element, not any of its
- * descendants.</td>
- * <td><code>p:containsOwn(jsoup)</code> finds p elements with own text "jsoup".
- * </td>
- * </tr>
- * <tr>
- * <td><code>:matchesOwn(<em>regex</em>)</code></td>
- * <td>elements whose own text matches the specified regular expression. The
- * text must appear in the found element, not any of its descendants.</td>
- * <td><code>td:matchesOwn(\\d+)</code> finds table cells directly containing
- * digits. <code>div:matchesOwn((?i)login)</code> finds divs containing the
- * text, case insensitively.</td>
- * </tr>
- * <tr>
- * <td></td>
- * <td>The above may be combined in any order and with other selectors</td>
- * <td><code>.light:contains(name):eq(0)</code></td>
- * </tr>
- * </table>
- *
- * @author Jonathan Hedley, jonathan@hedley.net
- * @see Element#select(String)
- */
-public class Selector {
- private final Evaluator evaluator;
- private final Element root;
-
- private Selector(String query, Element root) {
- Validate.notNull(query);
- query = query.trim();
- Validate.notEmpty(query);
- Validate.notNull(root);
-
- evaluator = QueryParser.parse(query);
-
- this.root = root;
- }
-
- /**
- * Find elements matching selector.
- *
- * @param query
- * CSS selector
- * @param root
- * root element to descend into
- * @return matching elements, empty if not
- */
- public static Elements select(String query, Element root) {
- return new Selector(query, root).select();
- }
-
- /**
- * Find elements matching selector.
- *
- * @param query
- * CSS selector
- * @param roots
- * root elements to descend into
- * @return matching elements, empty if not
- */
- public static Elements select(String query, Iterable<Element> roots) {
- Validate.notEmpty(query);
- Validate.notNull(roots);
- LinkedHashSet<Element> elements = new LinkedHashSet<Element>();
-
- for (Element root : roots) {
- elements.addAll(select(query, root));
- }
- return new Elements(elements);
- }
-
- private Elements select() {
- return Collector.collect(evaluator, root);
- }
-
- // exclude set. package open so that Elements can implement .not() selector.
- static Elements filterOut(Collection<Element> elements,
- Collection<Element> outs) {
- Elements output = new Elements();
- for (Element el : elements) {
- boolean found = false;
- for (Element out : outs) {
- if (el.equals(out)) {
- found = true;
- break;
- }
- }
- if (!found) {
- output.add(el);
- }
- }
- return output;
- }
-
- public static class SelectorParseException extends IllegalStateException {
- public SelectorParseException(String msg, Object... params) {
- super(String.format(msg, params));
- }
- }
-}
diff --git a/server/src/org/jsoup/select/StructuralEvaluator.java b/server/src/org/jsoup/select/StructuralEvaluator.java
deleted file mode 100644
index dea2413fb8..0000000000
--- a/server/src/org/jsoup/select/StructuralEvaluator.java
+++ /dev/null
@@ -1,152 +0,0 @@
-package org.jsoup.select;
-
-import org.jsoup.nodes.Element;
-
-/**
- * Base structural evaluator.
- */
-abstract class StructuralEvaluator extends Evaluator {
- Evaluator evaluator;
-
- static class Root extends Evaluator {
- @Override
- public boolean matches(Element root, Element element) {
- return root == element;
- }
- }
-
- static class Has extends StructuralEvaluator {
- public Has(Evaluator evaluator) {
- this.evaluator = evaluator;
- }
-
- @Override
- public boolean matches(Element root, Element element) {
- for (Element e : element.getAllElements()) {
- if (e != element && evaluator.matches(root, e)) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public String toString() {
- return String.format(":has(%s)", evaluator);
- }
- }
-
- static class Not extends StructuralEvaluator {
- public Not(Evaluator evaluator) {
- this.evaluator = evaluator;
- }
-
- @Override
- public boolean matches(Element root, Element node) {
- return !evaluator.matches(root, node);
- }
-
- @Override
- public String toString() {
- return String.format(":not%s", evaluator);
- }
- }
-
- static class Parent extends StructuralEvaluator {
- public Parent(Evaluator evaluator) {
- this.evaluator = evaluator;
- }
-
- @Override
- public boolean matches(Element root, Element element) {
- if (root == element) {
- return false;
- }
-
- Element parent = element.parent();
- while (parent != root) {
- if (evaluator.matches(root, parent)) {
- return true;
- }
- parent = parent.parent();
- }
- return false;
- }
-
- @Override
- public String toString() {
- return String.format(":parent%s", evaluator);
- }
- }
-
- static class ImmediateParent extends StructuralEvaluator {
- public ImmediateParent(Evaluator evaluator) {
- this.evaluator = evaluator;
- }
-
- @Override
- public boolean matches(Element root, Element element) {
- if (root == element) {
- return false;
- }
-
- Element parent = element.parent();
- return parent != null && evaluator.matches(root, parent);
- }
-
- @Override
- public String toString() {
- return String.format(":ImmediateParent%s", evaluator);
- }
- }
-
- static class PreviousSibling extends StructuralEvaluator {
- public PreviousSibling(Evaluator evaluator) {
- this.evaluator = evaluator;
- }
-
- @Override
- public boolean matches(Element root, Element element) {
- if (root == element) {
- return false;
- }
-
- Element prev = element.previousElementSibling();
-
- while (prev != null) {
- if (evaluator.matches(root, prev)) {
- return true;
- }
-
- prev = prev.previousElementSibling();
- }
- return false;
- }
-
- @Override
- public String toString() {
- return String.format(":prev*%s", evaluator);
- }
- }
-
- static class ImmediatePreviousSibling extends StructuralEvaluator {
- public ImmediatePreviousSibling(Evaluator evaluator) {
- this.evaluator = evaluator;
- }
-
- @Override
- public boolean matches(Element root, Element element) {
- if (root == element) {
- return false;
- }
-
- Element prev = element.previousElementSibling();
- return prev != null && evaluator.matches(root, prev);
- }
-
- @Override
- public String toString() {
- return String.format(":prev%s", evaluator);
- }
- }
-}
diff --git a/server/src/org/jsoup/select/package-info.java b/server/src/org/jsoup/select/package-info.java
deleted file mode 100644
index a6e6a2fa0f..0000000000
--- a/server/src/org/jsoup/select/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- Packages to support the CSS-style element selector.
- */
-package org.jsoup.select; \ No newline at end of file