aboutsummaryrefslogtreecommitdiffstats
path: root/server/src/org/jsoup/nodes/Element.java
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/org/jsoup/nodes/Element.java')
-rw-r--r--server/src/org/jsoup/nodes/Element.java790
1 files changed, 513 insertions, 277 deletions
diff --git a/server/src/org/jsoup/nodes/Element.java b/server/src/org/jsoup/nodes/Element.java
index 5c1894c934..ff9e68b962 100644
--- a/server/src/org/jsoup/nodes/Element.java
+++ b/server/src/org/jsoup/nodes/Element.java
@@ -1,5 +1,15 @@
package org.jsoup.nodes;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
import org.jsoup.helper.StringUtil;
import org.jsoup.helper.Validate;
import org.jsoup.parser.Parser;
@@ -9,44 +19,46 @@ import org.jsoup.select.Elements;
import org.jsoup.select.Evaluator;
import org.jsoup.select.Selector;
-import java.util.*;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-
/**
- * A HTML element consists of a tag name, attributes, and child nodes (including text nodes and
- * other elements).
+ * A HTML element consists of a tag name, attributes, and child nodes (including
+ * text nodes and other elements).
*
- * From an Element, you can extract data, traverse the node graph, and manipulate the HTML.
+ * From an Element, you can extract data, traverse the node graph, and
+ * manipulate the HTML.
*
* @author Jonathan Hedley, jonathan@hedley.net
*/
public class Element extends Node {
private Tag tag;
private Set<String> classNames;
-
+
/**
* Create a new, standalone Element. (Standalone in that is has no parent.)
*
- * @param tag tag of this element
- * @param baseUri the base URI
- * @param attributes initial attributes
+ * @param tag
+ * tag of this element
+ * @param baseUri
+ * the base URI
+ * @param attributes
+ * initial attributes
* @see #appendChild(Node)
* @see #appendElement(String)
*/
public Element(Tag tag, String baseUri, Attributes attributes) {
super(baseUri, attributes);
-
- Validate.notNull(tag);
+
+ Validate.notNull(tag);
this.tag = tag;
}
-
+
/**
* Create a new Element from a tag and a base URI.
*
- * @param tag element tag
- * @param baseUri the base URI of this element. It is acceptable for the base URI to be an empty
- * string, but not null.
+ * @param tag
+ * element tag
+ * @param baseUri
+ * the base URI of this element. It is acceptable for the base
+ * URI to be an empty string, but not null.
* @see Tag#valueOf(String)
*/
public Element(Tag tag, String baseUri) {
@@ -68,10 +80,11 @@ public class Element extends Node {
}
/**
- * Change the tag of this element. For example, convert a {@code <span>} to a {@code <div>} with
- * {@code el.tagName("div");}.
- *
- * @param tagName new tag name for this element
+ * Change the tag of this element. For example, convert a {@code <span>} to
+ * a {@code <div>} with {@code el.tagName("div");}.
+ *
+ * @param tagName
+ * new tag name for this element
* @return this element, for chaining
*/
public Element tagName(String tagName) {
@@ -88,10 +101,10 @@ public class Element extends Node {
public Tag tag() {
return tag;
}
-
+
/**
- * Test if this element is a block-level element. (E.g. {@code <div> == true} or an inline element
- * {@code <p> == false}).
+ * Test if this element is a block-level element. (E.g.
+ * {@code <div> == true} or an inline element {@code <p> == false}).
*
* @return true if block, false if not (and thus inline)
*/
@@ -110,27 +123,32 @@ public class Element extends Node {
}
/**
- * Set an attribute value on this element. If this element already has an attribute with the
- * key, its value is updated; otherwise, a new attribute is added.
+ * Set an attribute value on this element. If this element already has an
+ * attribute with the key, its value is updated; otherwise, a new attribute
+ * is added.
*
* @return this element
*/
+ @Override
public Element attr(String attributeKey, String attributeValue) {
super.attr(attributeKey, attributeValue);
return this;
}
/**
- * Get this element's HTML5 custom data attributes. Each attribute in the element that has a key
- * starting with "data-" is included the dataset.
+ * Get this element's HTML5 custom data attributes. Each attribute in the
+ * element that has a key starting with "data-" is included the dataset.
* <p>
- * E.g., the element {@code <div data-package="jsoup" data-language="Java" class="group">...} has the dataset
- * {@code package=jsoup, language=java}.
+ * E.g., the element
+ * {@code <div data-package="jsoup" data-language="Java" class="group">...}
+ * has the dataset {@code package=jsoup, language=java}.
* <p>
- * This map is a filtered view of the element's attribute map. Changes to one map (add, remove, update) are reflected
- * in the other map.
+ * This map is a filtered view of the element's attribute map. Changes to
+ * one map (add, remove, update) are reflected in the other map.
* <p>
- * You can find elements that have data attributes using the {@code [^data-]} attribute key prefix selector.
+ * You can find elements that have data attributes using the
+ * {@code [^data-]} attribute key prefix selector.
+ *
* @return a map of {@code key=value} custom data attributes.
*/
public Map<String, String> dataset() {
@@ -144,6 +162,7 @@ public class Element extends Node {
/**
* Get this element's parent and ancestors, up to the document root.
+ *
* @return this element's stack of parents, closest first.
*/
public Elements parents() {
@@ -163,10 +182,12 @@ public class Element extends Node {
/**
* Get a child element of this element, by its 0-based index number.
* <p/>
- * Note that an element can have both mixed Nodes and Elements as children. This method inspects
- * a filtered list of children that are elements, and the index is based on that filtered list.
+ * Note that an element can have both mixed Nodes and Elements as children.
+ * This method inspects a filtered list of children that are elements, and
+ * the index is based on that filtered list.
*
- * @param index the index number of the element to retrieve
+ * @param index
+ * the index number of the element to retrieve
* @return the child element, if it exists, or {@code null} if absent.
* @see #childNode(int)
*/
@@ -177,140 +198,165 @@ public class Element extends Node {
/**
* Get this element's child elements.
* <p/>
- * This is effectively a filter on {@link #childNodes()} to get Element nodes.
- * @return child elements. If this element has no children, returns an
- * empty list.
+ * This is effectively a filter on {@link #childNodes()} to get Element
+ * nodes.
+ *
+ * @return child elements. If this element has no children, returns an empty
+ * list.
* @see #childNodes()
*/
public Elements children() {
- // create on the fly rather than maintaining two lists. if gets slow, memoize, and mark dirty on change
+ // create on the fly rather than maintaining two lists. if gets slow,
+ // memoize, and mark dirty on change
List<Element> elements = new ArrayList<Element>();
for (Node node : childNodes) {
- if (node instanceof Element)
+ if (node instanceof Element) {
elements.add((Element) node);
+ }
}
return new Elements(elements);
}
/**
- * Get this element's child text nodes. The list is unmodifiable but the text nodes may be manipulated.
+ * Get this element's child text nodes. The list is unmodifiable but the
+ * text nodes may be manipulated.
* <p/>
* This is effectively a filter on {@link #childNodes()} to get Text nodes.
+ *
* @return child text nodes. If this element has no text nodes, returns an
- * empty list.
- * <p/>
- * For example, with the input HTML: {@code <p>One <span>Two</span> Three <br> Four</p>} with the {@code p} element selected:
- * <ul>
- * <li>{@code p.text()} = {@code "One Two Three Four"}</li>
- * <li>{@code p.ownText()} = {@code "One Three Four"}</li>
- * <li>{@code p.children()} = {@code Elements[<span>, <br>]}</li>
- * <li>{@code p.childNodes()} = {@code List<Node>["One ", <span>, " Three ", <br>, " Four"]}</li>
- * <li>{@code p.textNodes()} = {@code List<TextNode>["One ", " Three ", " Four"]}</li>
- * </ul>
+ * empty list.
+ * <p/>
+ * For example, with the input HTML:
+ * {@code <p>One <span>Two</span> Three <br> Four</p>} with the
+ * {@code p} element selected: <ul>
+ * <li>{@code p.text()} = {@code "One Two Three Four"}</li>
+ * <li>{@code p.ownText()} = {@code "One Three Four"}</li>
+ * <li>{@code p.children()} = {@code Elements[<span>, <br>
+ * ]}</li>
+ * <li>{@code p.childNodes()} = {@code List<Node>["One ", <span>, " Three ",
+ * <br>
+ * , " Four"]}</li>
+ * <li>{@code p.textNodes()} =
+ * {@code List<TextNode>["One ", " Three ", " Four"]}</li>
+ * </ul>
*/
public List<TextNode> textNodes() {
List<TextNode> textNodes = new ArrayList<TextNode>();
for (Node node : childNodes) {
- if (node instanceof TextNode)
+ if (node instanceof TextNode) {
textNodes.add((TextNode) node);
+ }
}
return Collections.unmodifiableList(textNodes);
}
/**
- * Get this element's child data nodes. The list is unmodifiable but the data nodes may be manipulated.
+ * Get this element's child data nodes. The list is unmodifiable but the
+ * data nodes may be manipulated.
* <p/>
* This is effectively a filter on {@link #childNodes()} to get Data nodes.
+ *
* @return child data nodes. If this element has no data nodes, returns an
- * empty list.
+ * empty list.
* @see #data()
*/
public List<DataNode> dataNodes() {
List<DataNode> dataNodes = new ArrayList<DataNode>();
for (Node node : childNodes) {
- if (node instanceof DataNode)
+ if (node instanceof DataNode) {
dataNodes.add((DataNode) node);
+ }
}
return Collections.unmodifiableList(dataNodes);
}
/**
- * Find elements that match the {@link Selector} CSS query, with this element as the starting context. Matched elements
- * may include this element, or any of its children.
+ * Find elements that match the {@link Selector} CSS query, with this
+ * element as the starting context. Matched elements may include this
+ * element, or any of its children.
* <p/>
- * This method is generally more powerful to use than the DOM-type {@code getElementBy*} methods, because
- * multiple filters can be combined, e.g.:
+ * This method is generally more powerful to use than the DOM-type
+ * {@code getElementBy*} methods, because multiple filters can be combined,
+ * e.g.:
* <ul>
- * <li>{@code el.select("a[href]")} - finds links ({@code a} tags with {@code href} attributes)
- * <li>{@code el.select("a[href*=example.com]")} - finds links pointing to example.com (loosely)
+ * <li>{@code el.select("a[href]")} - finds links ({@code a} tags with
+ * {@code href} attributes)
+ * <li>{@code el.select("a[href*=example.com]")} - finds links pointing to
+ * example.com (loosely)
* </ul>
* <p/>
* See the query syntax documentation in {@link org.jsoup.select.Selector}.
- *
- * @param cssQuery a {@link Selector} CSS-like query
+ *
+ * @param cssQuery
+ * a {@link Selector} CSS-like query
* @return elements that match the query (empty if none match)
* @see org.jsoup.select.Selector
*/
public Elements select(String cssQuery) {
return Selector.select(cssQuery, this);
}
-
+
/**
* Add a node child node to this element.
*
- * @param child node to add. Must not already have a parent.
+ * @param child
+ * node to add. Must not already have a parent.
* @return this element, so that you can add more child nodes or elements.
*/
public Element appendChild(Node child) {
Validate.notNull(child);
-
+
addChildren(child);
return this;
}
-
+
/**
* Add a node to the start of this element's children.
*
- * @param child node to add. Must not already have a parent.
+ * @param child
+ * node to add. Must not already have a parent.
* @return this element, so that you can add more child nodes or elements.
*/
public Element prependChild(Node child) {
Validate.notNull(child);
-
+
addChildren(0, child);
return this;
}
-
+
/**
* Create a new element by tag name, and add it as the last child.
*
- * @param tagName the name of the tag (e.g. {@code div}).
+ * @param tagName
+ * the name of the tag (e.g. {@code div}).
* @return the new element, to allow you to add content to it, e.g.:
- * {@code parent.appendElement("h1").attr("id", "header").text("Welcome");}
+ * {@code parent.appendElement("h1").attr("id", "header").text("Welcome");}
*/
public Element appendElement(String tagName) {
Element child = new Element(Tag.valueOf(tagName), baseUri());
appendChild(child);
return child;
}
-
+
/**
* Create a new element by tag name, and add it as the first child.
*
- * @param tagName the name of the tag (e.g. {@code div}).
+ * @param tagName
+ * the name of the tag (e.g. {@code div}).
* @return the new element, to allow you to add content to it, e.g.:
- * {@code parent.prependElement("h1").attr("id", "header").text("Welcome");}
+ * {@code parent.prependElement("h1").attr("id", "header").text("Welcome");}
*/
public Element prependElement(String tagName) {
Element child = new Element(Tag.valueOf(tagName), baseUri());
prependChild(child);
return child;
}
-
+
/**
* Create and append a new TextNode to this element.
*
- * @param text the unencoded text to add
+ * @param text
+ * the unencoded text to add
* @return this element
*/
public Element appendText(String text) {
@@ -318,11 +364,12 @@ public class Element extends Node {
appendChild(node);
return this;
}
-
+
/**
* Create and prepend a new TextNode to this element.
*
- * @param text the unencoded text to add
+ * @param text
+ * the unencoded text to add
* @return this element
*/
public Element prependText(String text) {
@@ -330,10 +377,13 @@ public class Element extends Node {
prependChild(node);
return this;
}
-
+
/**
- * Add inner HTML to this element. The supplied HTML will be parsed, and each node appended to the end of the children.
- * @param html HTML to add inside this element, after the existing HTML
+ * Add inner HTML to this element. The supplied HTML will be parsed, and
+ * each node appended to the end of the children.
+ *
+ * @param html
+ * HTML to add inside this element, after the existing HTML
* @return this element
* @see #html(String)
*/
@@ -344,25 +394,30 @@ public class Element extends Node {
addChildren(nodes.toArray(new Node[nodes.size()]));
return this;
}
-
+
/**
- * Add inner HTML into this element. The supplied HTML will be parsed, and each node prepended to the start of the element's children.
- * @param html HTML to add inside this element, before the existing HTML
+ * Add inner HTML into this element. The supplied HTML will be parsed, and
+ * each node prepended to the start of the element's children.
+ *
+ * @param html
+ * HTML to add inside this element, before the existing HTML
* @return this element
* @see #html(String)
*/
public Element prepend(String html) {
Validate.notNull(html);
-
+
List<Node> nodes = Parser.parseFragment(html, this, baseUri());
addChildren(0, nodes.toArray(new Node[nodes.size()]));
return this;
}
/**
- * Insert the specified HTML into the DOM before this element (i.e. as a preceding sibling).
- *
- * @param html HTML to add before this element
+ * Insert the specified HTML into the DOM before this element (i.e. as a
+ * preceding sibling).
+ *
+ * @param html
+ * HTML to add before this element
* @return this element, for chaining
* @see #after(String)
*/
@@ -372,8 +427,11 @@ public class Element extends Node {
}
/**
- * Insert the specified node into the DOM before this node (i.e. as a preceding sibling).
- * @param node to add before this element
+ * Insert the specified node into the DOM before this node (i.e. as a
+ * preceding sibling).
+ *
+ * @param node
+ * to add before this element
* @return this Element, for chaining
* @see #after(Node)
*/
@@ -383,9 +441,11 @@ public class Element extends Node {
}
/**
- * Insert the specified HTML into the DOM after this element (i.e. as a following sibling).
- *
- * @param html HTML to add after this element
+ * Insert the specified HTML into the DOM after this element (i.e. as a
+ * following sibling).
+ *
+ * @param html
+ * HTML to add after this element
* @return this element, for chaining
* @see #before(String)
*/
@@ -395,8 +455,11 @@ public class Element extends Node {
}
/**
- * Insert the specified node into the DOM after this node (i.e. as a following sibling).
- * @param node to add after this element
+ * Insert the specified node into the DOM after this node (i.e. as a
+ * following sibling).
+ *
+ * @param node
+ * to add after this element
* @return this element, for chaining
* @see #before(Node)
*/
@@ -407,6 +470,7 @@ public class Element extends Node {
/**
* Remove all of the element's child nodes. Any attributes are left as-is.
+ *
* @return this element
*/
public Element empty() {
@@ -416,8 +480,10 @@ public class Element extends Node {
/**
* Wrap the supplied HTML around this element.
- *
- * @param html HTML to wrap around this element, e.g. {@code <div class="head"></div>}. Can be arbitrarily deep.
+ *
+ * @param html
+ * HTML to wrap around this element, e.g.
+ * {@code <div class="head"></div>}. Can be arbitrarily deep.
* @return this element, for chaining.
*/
@Override
@@ -426,94 +492,118 @@ public class Element extends Node {
}
/**
- * Get sibling elements. If the element has no sibling elements, returns an empty list. An element is not a sibling
- * of itself, so will not be included in the returned list.
+ * Get sibling elements. If the element has no sibling elements, returns an
+ * empty list. An element is not a sibling of itself, so will not be
+ * included in the returned list.
+ *
* @return sibling elements
*/
public Elements siblingElements() {
- if (parentNode == null)
+ if (parentNode == null) {
return new Elements(0);
+ }
List<Element> elements = parent().children();
Elements siblings = new Elements(elements.size() - 1);
- for (Element el: elements)
- if (el != this)
+ for (Element el : elements) {
+ if (el != this) {
siblings.add(el);
+ }
+ }
return siblings;
}
/**
- * Gets the next sibling element of this element. E.g., if a {@code div} contains two {@code p}s,
- * the {@code nextElementSibling} of the first {@code p} is the second {@code p}.
+ * Gets the next sibling element of this element. E.g., if a {@code div}
+ * contains two {@code p}s, the {@code nextElementSibling} of the first
+ * {@code p} is the second {@code p}.
* <p/>
- * This is similar to {@link #nextSibling()}, but specifically finds only Elements
+ * This is similar to {@link #nextSibling()}, but specifically finds only
+ * Elements
+ *
* @return the next element, or null if there is no next element
* @see #previousElementSibling()
*/
public Element nextElementSibling() {
- if (parentNode == null) return null;
+ if (parentNode == null) {
+ return null;
+ }
List<Element> siblings = parent().children();
Integer index = indexInList(this, siblings);
Validate.notNull(index);
- if (siblings.size() > index+1)
- return siblings.get(index+1);
- else
+ if (siblings.size() > index + 1) {
+ return siblings.get(index + 1);
+ } else {
return null;
+ }
}
/**
* Gets the previous element sibling of this element.
+ *
* @return the previous element, or null if there is no previous element
* @see #nextElementSibling()
*/
public Element previousElementSibling() {
- if (parentNode == null) return null;
+ if (parentNode == null) {
+ return null;
+ }
List<Element> siblings = parent().children();
Integer index = indexInList(this, siblings);
Validate.notNull(index);
- if (index > 0)
- return siblings.get(index-1);
- else
+ if (index > 0) {
+ return siblings.get(index - 1);
+ } else {
return null;
+ }
}
/**
* Gets the first element sibling of this element.
- * @return the first sibling that is an element (aka the parent's first element child)
+ *
+ * @return the first sibling that is an element (aka the parent's first
+ * element child)
*/
public Element firstElementSibling() {
// todo: should firstSibling() exclude this?
List<Element> siblings = parent().children();
return siblings.size() > 1 ? siblings.get(0) : null;
}
-
+
/**
- * Get the list index of this element in its element sibling list. I.e. if this is the first element
- * sibling, returns 0.
+ * Get the list index of this element in its element sibling list. I.e. if
+ * this is the first element sibling, returns 0.
+ *
* @return position in element sibling list
*/
public Integer elementSiblingIndex() {
- if (parent() == null) return 0;
- return indexInList(this, parent().children());
+ if (parent() == null) {
+ return 0;
+ }
+ return indexInList(this, parent().children());
}
/**
* Gets the last element sibling of this element
- * @return the last sibling that is an element (aka the parent's last element child)
+ *
+ * @return the last sibling that is an element (aka the parent's last
+ * element child)
*/
public Element lastElementSibling() {
List<Element> siblings = parent().children();
return siblings.size() > 1 ? siblings.get(siblings.size() - 1) : null;
}
-
- private static <E extends Element> Integer indexInList(Element search, List<E> elements) {
+
+ private static <E extends Element> Integer indexInList(Element search,
+ List<E> elements) {
Validate.notNull(search);
Validate.notNull(elements);
for (int i = 0; i < elements.size(); i++) {
E element = elements.get(i);
- if (element.equals(search))
+ if (element.equals(search)) {
return i;
+ }
}
return null;
}
@@ -521,9 +611,13 @@ public class Element extends Node {
// DOM type methods
/**
- * Finds elements, including and recursively under this element, with the specified tag name.
- * @param tagName The tag name to search for (case insensitively).
- * @return a matching unmodifiable list of elements. Will be empty if this element and none of its children match.
+ * Finds elements, including and recursively under this element, with the
+ * specified tag name.
+ *
+ * @param tagName
+ * The tag name to search for (case insensitively).
+ * @return a matching unmodifiable list of elements. Will be empty if this
+ * element and none of its children match.
*/
public Elements getElementsByTag(String tagName) {
Validate.notEmpty(tagName);
@@ -535,29 +629,37 @@ public class Element extends Node {
/**
* Find an element by ID, including or under this element.
* <p>
- * Note that this finds the first matching ID, starting with this element. If you search down from a different
- * starting point, it is possible to find a different element by ID. For unique element by ID within a Document,
- * use {@link Document#getElementById(String)}
- * @param id The ID to search for.
- * @return The first matching element by ID, starting with this element, or null if none found.
+ * Note that this finds the first matching ID, starting with this element.
+ * If you search down from a different starting point, it is possible to
+ * find a different element by ID. For unique element by ID within a
+ * Document, use {@link Document#getElementById(String)}
+ *
+ * @param id
+ * The ID to search for.
+ * @return The first matching element by ID, starting with this element, or
+ * null if none found.
*/
public Element getElementById(String id) {
Validate.notEmpty(id);
-
+
Elements elements = Collector.collect(new Evaluator.Id(id), this);
- if (elements.size() > 0)
+ if (elements.size() > 0) {
return elements.get(0);
- else
+ } else {
return null;
+ }
}
/**
- * Find elements that have this class, including or under this element. Case insensitive.
+ * Find elements that have this class, including or under this element. Case
+ * insensitive.
* <p>
- * Elements can have multiple classes (e.g. {@code <div class="header round first">}. This method
- * checks each class, so you can find the above with {@code el.getElementsByClass("header");}.
+ * Elements can have multiple classes (e.g.
+ * {@code <div class="header round first">}. This method checks each class,
+ * so you can find the above with {@code el.getElementsByClass("header");}.
*
- * @param className the name of the class to search for.
+ * @param className
+ * the name of the class to search for.
* @return elements with the supplied class name, empty if none
* @see #hasClass(String)
* @see #classNames()
@@ -570,8 +672,9 @@ public class Element extends Node {
/**
* Find elements that have a named attribute set. Case insensitive.
- *
- * @param key name of the attribute, e.g. {@code href}
+ *
+ * @param key
+ * name of the attribute, e.g. {@code href}
* @return elements that have this attribute, empty if none
*/
public Elements getElementsByAttribute(String key) {
@@ -582,88 +685,129 @@ public class Element extends Node {
}
/**
- * Find elements that have an attribute name starting with the supplied prefix. Use {@code data-} to find elements
- * that have HTML5 datasets.
- * @param keyPrefix name prefix of the attribute e.g. {@code data-}
- * @return elements that have attribute names that start with with the prefix, empty if none.
+ * Find elements that have an attribute name starting with the supplied
+ * prefix. Use {@code data-} to find elements that have HTML5 datasets.
+ *
+ * @param keyPrefix
+ * name prefix of the attribute e.g. {@code data-}
+ * @return elements that have attribute names that start with with the
+ * prefix, empty if none.
*/
public Elements getElementsByAttributeStarting(String keyPrefix) {
Validate.notEmpty(keyPrefix);
keyPrefix = keyPrefix.trim().toLowerCase();
- return Collector.collect(new Evaluator.AttributeStarting(keyPrefix), this);
+ return Collector.collect(new Evaluator.AttributeStarting(keyPrefix),
+ this);
}
/**
- * Find elements that have an attribute with the specific value. Case insensitive.
+ * Find elements that have an attribute with the specific value. Case
+ * insensitive.
*
- * @param key name of the attribute
- * @param value value of the attribute
+ * @param key
+ * name of the attribute
+ * @param value
+ * value of the attribute
* @return elements that have this attribute with this value, empty if none
*/
public Elements getElementsByAttributeValue(String key, String value) {
- return Collector.collect(new Evaluator.AttributeWithValue(key, value), this);
+ return Collector.collect(new Evaluator.AttributeWithValue(key, value),
+ this);
}
/**
- * Find elements that either do not have this attribute, or have it with a different value. Case insensitive.
+ * Find elements that either do not have this attribute, or have it with a
+ * different value. Case insensitive.
*
- * @param key name of the attribute
- * @param value value of the attribute
+ * @param key
+ * name of the attribute
+ * @param value
+ * value of the attribute
* @return elements that do not have a matching attribute
*/
public Elements getElementsByAttributeValueNot(String key, String value) {
- return Collector.collect(new Evaluator.AttributeWithValueNot(key, value), this);
+ return Collector.collect(
+ new Evaluator.AttributeWithValueNot(key, value), this);
}
/**
- * Find elements that have attributes that start with the value prefix. Case insensitive.
+ * Find elements that have attributes that start with the value prefix. Case
+ * insensitive.
*
- * @param key name of the attribute
- * @param valuePrefix start of attribute value
+ * @param key
+ * name of the attribute
+ * @param valuePrefix
+ * start of attribute value
* @return elements that have attributes that start with the value prefix
*/
- public Elements getElementsByAttributeValueStarting(String key, String valuePrefix) {
- return Collector.collect(new Evaluator.AttributeWithValueStarting(key, valuePrefix), this);
+ public Elements getElementsByAttributeValueStarting(String key,
+ String valuePrefix) {
+ return Collector.collect(new Evaluator.AttributeWithValueStarting(key,
+ valuePrefix), this);
}
/**
- * Find elements that have attributes that end with the value suffix. Case insensitive.
+ * Find elements that have attributes that end with the value suffix. Case
+ * insensitive.
*
- * @param key name of the attribute
- * @param valueSuffix end of the attribute value
+ * @param key
+ * name of the attribute
+ * @param valueSuffix
+ * end of the attribute value
* @return elements that have attributes that end with the value suffix
*/
- public Elements getElementsByAttributeValueEnding(String key, String valueSuffix) {
- return Collector.collect(new Evaluator.AttributeWithValueEnding(key, valueSuffix), this);
+ public Elements getElementsByAttributeValueEnding(String key,
+ String valueSuffix) {
+ return Collector.collect(new Evaluator.AttributeWithValueEnding(key,
+ valueSuffix), this);
}
/**
- * Find elements that have attributes whose value contains the match string. Case insensitive.
+ * Find elements that have attributes whose value contains the match string.
+ * Case insensitive.
*
- * @param key name of the attribute
- * @param match substring of value to search for
+ * @param key
+ * name of the attribute
+ * @param match
+ * substring of value to search for
* @return elements that have attributes containing this text
*/
- public Elements getElementsByAttributeValueContaining(String key, String match) {
- return Collector.collect(new Evaluator.AttributeWithValueContaining(key, match), this);
+ public Elements getElementsByAttributeValueContaining(String key,
+ String match) {
+ return Collector.collect(new Evaluator.AttributeWithValueContaining(
+ key, match), this);
}
-
+
/**
- * Find elements that have attributes whose values match the supplied regular expression.
- * @param key name of the attribute
- * @param pattern compiled regular expression to match against attribute values
+ * Find elements that have attributes whose values match the supplied
+ * regular expression.
+ *
+ * @param key
+ * name of the attribute
+ * @param pattern
+ * compiled regular expression to match against attribute values
* @return elements that have attributes matching this regular expression
*/
- public Elements getElementsByAttributeValueMatching(String key, Pattern pattern) {
- return Collector.collect(new Evaluator.AttributeWithValueMatching(key, pattern), this);
-
+ public Elements getElementsByAttributeValueMatching(String key,
+ Pattern pattern) {
+ return Collector.collect(new Evaluator.AttributeWithValueMatching(key,
+ pattern), this);
+
}
-
+
/**
- * Find elements that have attributes whose values match the supplied regular expression.
- * @param key name of the attribute
- * @param regex regular expression to match against attribute values. You can use <a href="http://java.sun.com/docs/books/tutorial/essential/regex/pattern.html#embedded">embedded flags</a> (such as (?i) and (?m) to control regex options.
+ * Find elements that have attributes whose values match the supplied
+ * regular expression.
+ *
+ * @param key
+ * name of the attribute
+ * @param regex
+ * regular expression to match against attribute values. You can
+ * use <a href=
+ * "http://java.sun.com/docs/books/tutorial/essential/regex/pattern.html#embedded"
+ * >embedded flags</a> (such as (?i) and (?m) to control regex
+ * options.
* @return elements that have attributes matching this regular expression
*/
public Elements getElementsByAttributeValueMatching(String key, String regex) {
@@ -671,73 +815,94 @@ public class Element extends Node {
try {
pattern = Pattern.compile(regex);
} catch (PatternSyntaxException e) {
- throw new IllegalArgumentException("Pattern syntax error: " + regex, e);
+ throw new IllegalArgumentException(
+ "Pattern syntax error: " + regex, e);
}
return getElementsByAttributeValueMatching(key, pattern);
}
-
+
/**
* Find elements whose sibling index is less than the supplied index.
- * @param index 0-based index
+ *
+ * @param index
+ * 0-based index
* @return elements less than index
*/
public Elements getElementsByIndexLessThan(int index) {
return Collector.collect(new Evaluator.IndexLessThan(index), this);
}
-
+
/**
* Find elements whose sibling index is greater than the supplied index.
- * @param index 0-based index
+ *
+ * @param index
+ * 0-based index
* @return elements greater than index
*/
public Elements getElementsByIndexGreaterThan(int index) {
return Collector.collect(new Evaluator.IndexGreaterThan(index), this);
}
-
+
/**
* Find elements whose sibling index is equal to the supplied index.
- * @param index 0-based index
+ *
+ * @param index
+ * 0-based index
* @return elements equal to index
*/
public Elements getElementsByIndexEquals(int index) {
return Collector.collect(new Evaluator.IndexEquals(index), this);
}
-
+
/**
- * Find elements that contain the specified string. The search is case insensitive. The text may appear directly
- * in the element, or in any of its descendants.
- * @param searchText to look for in the element's text
+ * Find elements that contain the specified string. The search is case
+ * insensitive. The text may appear directly in the element, or in any of
+ * its descendants.
+ *
+ * @param searchText
+ * to look for in the element's text
* @return elements that contain the string, case insensitive.
* @see Element#text()
*/
public Elements getElementsContainingText(String searchText) {
return Collector.collect(new Evaluator.ContainsText(searchText), this);
}
-
+
/**
- * Find elements that directly contain the specified string. The search is case insensitive. The text must appear directly
- * in the element, not in any of its descendants.
- * @param searchText to look for in the element's own text
+ * Find elements that directly contain the specified string. The search is
+ * case insensitive. The text must appear directly in the element, not in
+ * any of its descendants.
+ *
+ * @param searchText
+ * to look for in the element's own text
* @return elements that contain the string, case insensitive.
* @see Element#ownText()
*/
public Elements getElementsContainingOwnText(String searchText) {
- return Collector.collect(new Evaluator.ContainsOwnText(searchText), this);
+ return Collector.collect(new Evaluator.ContainsOwnText(searchText),
+ this);
}
-
+
/**
* Find elements whose text matches the supplied regular expression.
- * @param pattern regular expression to match text against
+ *
+ * @param pattern
+ * regular expression to match text against
* @return elements matching the supplied regular expression.
* @see Element#text()
*/
public Elements getElementsMatchingText(Pattern pattern) {
return Collector.collect(new Evaluator.Matches(pattern), this);
}
-
+
/**
* Find elements whose text matches the supplied regular expression.
- * @param regex regular expression to match text against. You can use <a href="http://java.sun.com/docs/books/tutorial/essential/regex/pattern.html#embedded">embedded flags</a> (such as (?i) and (?m) to control regex options.
+ *
+ * @param regex
+ * regular expression to match text against. You can use <a href=
+ * "http://java.sun.com/docs/books/tutorial/essential/regex/pattern.html#embedded"
+ * >embedded flags</a> (such as (?i) and (?m) to control regex
+ * options.
* @return elements matching the supplied regular expression.
* @see Element#text()
*/
@@ -746,24 +911,32 @@ public class Element extends Node {
try {
pattern = Pattern.compile(regex);
} catch (PatternSyntaxException e) {
- throw new IllegalArgumentException("Pattern syntax error: " + regex, e);
+ throw new IllegalArgumentException(
+ "Pattern syntax error: " + regex, e);
}
return getElementsMatchingText(pattern);
}
-
+
/**
* Find elements whose own text matches the supplied regular expression.
- * @param pattern regular expression to match text against
+ *
+ * @param pattern
+ * regular expression to match text against
* @return elements matching the supplied regular expression.
* @see Element#ownText()
*/
public Elements getElementsMatchingOwnText(Pattern pattern) {
return Collector.collect(new Evaluator.MatchesOwn(pattern), this);
}
-
+
/**
* Find elements whose text matches the supplied regular expression.
- * @param regex regular expression to match text against. You can use <a href="http://java.sun.com/docs/books/tutorial/essential/regex/pattern.html#embedded">embedded flags</a> (such as (?i) and (?m) to control regex options.
+ *
+ * @param regex
+ * regular expression to match text against. You can use <a href=
+ * "http://java.sun.com/docs/books/tutorial/essential/regex/pattern.html#embedded"
+ * >embedded flags</a> (such as (?i) and (?m) to control regex
+ * options.
* @return elements matching the supplied regular expression.
* @see Element#ownText()
*/
@@ -772,13 +945,15 @@ public class Element extends Node {
try {
pattern = Pattern.compile(regex);
} catch (PatternSyntaxException e) {
- throw new IllegalArgumentException("Pattern syntax error: " + regex, e);
+ throw new IllegalArgumentException(
+ "Pattern syntax error: " + regex, e);
}
return getElementsMatchingOwnText(pattern);
}
-
+
/**
- * Find all elements under this element (including self, and children of children).
+ * Find all elements under this element (including self, and children of
+ * children).
*
* @return all elements
*/
@@ -789,8 +964,9 @@ public class Element extends Node {
/**
* Gets the combined text of this element and all its children.
* <p>
- * For example, given HTML {@code <p>Hello <b>there</b> now!</p>}, {@code p.text()} returns {@code "Hello there now!"}
- *
+ * For example, given HTML {@code <p>Hello <b>there</b> now!</p>},
+ * {@code p.text()} returns {@code "Hello there now!"}
+ *
* @return unencoded text, or empty string if none.
* @see #ownText()
* @see #textNodes()
@@ -803,27 +979,32 @@ public class Element extends Node {
private void text(StringBuilder accum) {
appendWhitespaceIfBr(this, accum);
-
+
for (Node child : childNodes) {
if (child instanceof TextNode) {
TextNode textNode = (TextNode) child;
appendNormalisedText(accum, textNode);
} else if (child instanceof Element) {
Element element = (Element) child;
- if (accum.length() > 0 && element.isBlock() && !TextNode.lastCharIsWhitespace(accum))
+ if (accum.length() > 0 && element.isBlock()
+ && !TextNode.lastCharIsWhitespace(accum)) {
accum.append(" ");
+ }
element.text(accum);
}
}
}
/**
- * Gets the text owned by this element only; does not get the combined text of all children.
+ * Gets the text owned by this element only; does not get the combined text
+ * of all children.
* <p>
- * For example, given HTML {@code <p>Hello <b>there</b> now!</p>}, {@code p.ownText()} returns {@code "Hello now!"},
- * whereas {@code p.text()} returns {@code "Hello there now!"}.
- * Note that the text within the {@code b} element is not returned, as it is not a direct child of the {@code p} element.
- *
+ * For example, given HTML {@code <p>Hello <b>there</b> now!</p>},
+ * {@code p.ownText()} returns {@code "Hello now!"}, whereas
+ * {@code p.text()} returns {@code "Hello there now!"}. Note that the text
+ * within the {@code b} element is not returned, as it is not a direct child
+ * of the {@code p} element.
+ *
* @return unencoded text, or empty string if none.
* @see #text()
* @see #textNodes()
@@ -850,24 +1031,32 @@ public class Element extends Node {
if (!preserveWhitespace()) {
text = TextNode.normaliseWhitespace(text);
- if (TextNode.lastCharIsWhitespace(accum))
+ if (TextNode.lastCharIsWhitespace(accum)) {
text = TextNode.stripLeadingWhitespace(text);
+ }
}
accum.append(text);
}
- private static void appendWhitespaceIfBr(Element element, StringBuilder accum) {
- if (element.tag.getName().equals("br") && !TextNode.lastCharIsWhitespace(accum))
+ private static void appendWhitespaceIfBr(Element element,
+ StringBuilder accum) {
+ if (element.tag.getName().equals("br")
+ && !TextNode.lastCharIsWhitespace(accum)) {
accum.append(" ");
+ }
}
boolean preserveWhitespace() {
- return tag.preserveWhitespace() || parent() != null && parent().preserveWhitespace();
+ return tag.preserveWhitespace() || parent() != null
+ && parent().preserveWhitespace();
}
/**
- * Set the text of this element. Any existing contents (text or elements) will be cleared
- * @param text unencoded text
+ * Set the text of this element. Any existing contents (text or elements)
+ * will be cleared
+ *
+ * @param text
+ * unencoded text
* @return this element
*/
public Element text(String text) {
@@ -881,28 +1070,33 @@ public class Element extends Node {
}
/**
- Test if this element has any text content (that is not just whitespace).
- @return true if element has non-blank text content.
+ * Test if this element has any text content (that is not just whitespace).
+ *
+ * @return true if element has non-blank text content.
*/
public boolean hasText() {
- for (Node child: childNodes) {
+ for (Node child : childNodes) {
if (child instanceof TextNode) {
TextNode textNode = (TextNode) child;
- if (!textNode.isBlank())
+ if (!textNode.isBlank()) {
return true;
+ }
} else if (child instanceof Element) {
Element el = (Element) child;
- if (el.hasText())
+ if (el.hasText()) {
return true;
+ }
}
}
return false;
}
/**
- * Get the combined data of this element. Data is e.g. the inside of a {@code script} tag.
+ * Get the combined data of this element. Data is e.g. the inside of a
+ * {@code script} tag.
+ *
* @return the data, or empty string if none
- *
+ *
* @see #dataNodes()
*/
public String data() {
@@ -919,21 +1113,28 @@ public class Element extends Node {
}
}
return sb.toString();
- }
+ }
/**
- * Gets the literal value of this element's "class" attribute, which may include multiple class names, space
- * separated. (E.g. on <code>&lt;div class="header gray"></code> returns, "<code>header gray</code>")
- * @return The literal class attribute, or <b>empty string</b> if no class attribute set.
+ * Gets the literal value of this element's "class" attribute, which may
+ * include multiple class names, space separated. (E.g. on
+ * <code>&lt;div class="header gray"></code> returns, "
+ * <code>header gray</code>")
+ *
+ * @return The literal class attribute, or <b>empty string</b> if no class
+ * attribute set.
*/
public String className() {
return attr("class");
}
/**
- * Get all of the element's class names. E.g. on element {@code <div class="header gray"}>},
- * returns a set of two elements {@code "header", "gray"}. Note that modifications to this set are not pushed to
- * the backing {@code class} attribute; use the {@link #classNames(java.util.Set)} method to persist them.
+ * Get all of the element's class names. E.g. on element
+ * {@code <div class="header gray"}>}, returns a set of two elements
+ * {@code "header", "gray"}. Note that modifications to this set are not
+ * pushed to the backing {@code class} attribute; use the
+ * {@link #classNames(java.util.Set)} method to persist them.
+ *
* @return set of classnames, empty if no class attribute
*/
public Set<String> classNames() {
@@ -945,9 +1146,11 @@ public class Element extends Node {
}
/**
- Set the element's {@code class} attribute to the supplied class names.
- @param classNames set of classes
- @return this element, for chaining
+ * Set the element's {@code class} attribute to the supplied class names.
+ *
+ * @param classNames
+ * set of classes
+ * @return this element, for chaining
*/
public Element classNames(Set<String> classNames) {
Validate.notNull(classNames);
@@ -957,22 +1160,27 @@ public class Element extends Node {
/**
* Tests if this element has a class. Case insensitive.
- * @param className name of class to check for
+ *
+ * @param className
+ * name of class to check for
* @return true if it does, false if not
*/
public boolean hasClass(String className) {
Set<String> classNames = classNames();
for (String name : classNames) {
- if (className.equalsIgnoreCase(name))
+ if (className.equalsIgnoreCase(name)) {
return true;
+ }
}
return false;
}
/**
- Add a class name to this element's {@code class} attribute.
- @param className class name to add
- @return this element
+ * Add a class name to this element's {@code class} attribute.
+ *
+ * @param className
+ * class name to add
+ * @return this element
*/
public Element addClass(String className) {
Validate.notNull(className);
@@ -985,9 +1193,11 @@ public class Element extends Node {
}
/**
- Remove a class name from this element's {@code class} attribute.
- @param className class name to remove
- @return this element
+ * Remove a class name from this element's {@code class} attribute.
+ *
+ * @param className
+ * class name to remove
+ * @return this element
*/
public Element removeClass(String className) {
Validate.notNull(className);
@@ -1000,90 +1210,114 @@ public class Element extends Node {
}
/**
- Toggle a class name on this element's {@code class} attribute: if present, remove it; otherwise add it.
- @param className class name to toggle
- @return this element
+ * Toggle a class name on this element's {@code class} attribute: if
+ * present, remove it; otherwise add it.
+ *
+ * @param className
+ * class name to toggle
+ * @return this element
*/
public Element toggleClass(String className) {
Validate.notNull(className);
Set<String> classes = classNames();
- if (classes.contains(className))
+ if (classes.contains(className)) {
classes.remove(className);
- else
+ } else {
classes.add(className);
+ }
classNames(classes);
return this;
}
-
+
/**
* Get the value of a form element (input, textarea, etc).
+ *
* @return the value of the form element, or empty string if not set.
*/
public String val() {
- if (tagName().equals("textarea"))
+ if (tagName().equals("textarea")) {
return text();
- else
+ } else {
return attr("value");
+ }
}
-
+
/**
* Set the value of a form element (input, textarea, etc).
- * @param value value to set
+ *
+ * @param value
+ * value to set
* @return this element (for chaining)
*/
public Element val(String value) {
- if (tagName().equals("textarea"))
+ if (tagName().equals("textarea")) {
text(value);
- else
+ } else {
attr("value", value);
+ }
return this;
}
- void outerHtmlHead(StringBuilder accum, int depth, Document.OutputSettings out) {
- if (accum.length() > 0 && out.prettyPrint() && (tag.formatAsBlock() || (parent() != null && parent().tag().formatAsBlock())))
+ @Override
+ void outerHtmlHead(StringBuilder accum, int depth,
+ Document.OutputSettings out) {
+ if (accum.length() > 0
+ && out.prettyPrint()
+ && (tag.formatAsBlock() || (parent() != null && parent().tag()
+ .formatAsBlock()))) {
indent(accum, depth, out);
- accum
- .append("<")
- .append(tagName());
+ }
+ accum.append("<").append(tagName());
attributes.html(accum, out);
- if (childNodes.isEmpty() && tag.isSelfClosing())
+ if (childNodes.isEmpty() && tag.isSelfClosing()) {
accum.append(" />");
- else
+ } else {
accum.append(">");
+ }
}
- void outerHtmlTail(StringBuilder accum, int depth, Document.OutputSettings out) {
+ @Override
+ void outerHtmlTail(StringBuilder accum, int depth,
+ Document.OutputSettings out) {
if (!(childNodes.isEmpty() && tag.isSelfClosing())) {
- if (out.prettyPrint() && !childNodes.isEmpty() && tag.formatAsBlock())
+ if (out.prettyPrint() && !childNodes.isEmpty()
+ && tag.formatAsBlock()) {
indent(accum, depth, out);
+ }
accum.append("</").append(tagName()).append(">");
}
}
/**
- * Retrieves the element's inner HTML. E.g. on a {@code <div>} with one empty {@code <p>}, would return
- * {@code <p></p>}. (Whereas {@link #outerHtml()} would return {@code <div><p></p></div>}.)
+ * Retrieves the element's inner HTML. E.g. on a {@code <div>} with one
+ * empty {@code <p>}, would return {@code <p></p>}. (Whereas
+ * {@link #outerHtml()} would return {@code <div>
+ * <p></p>
+ * </div>}.)
*
* @return String of HTML.
* @see #outerHtml()
*/
public String html() {
StringBuilder accum = new StringBuilder();
- html(accum);
+ html(accum);
return accum.toString().trim();
}
private void html(StringBuilder accum) {
- for (Node node : childNodes)
+ for (Node node : childNodes) {
node.outerHtml(accum);
+ }
}
-
+
/**
* Set this element's inner HTML. Clears the existing HTML first.
- * @param html HTML to parse and set into this element
+ *
+ * @param html
+ * HTML to parse and set into this element
* @return this element
* @see #append(String)
*/
@@ -1093,6 +1327,7 @@ public class Element extends Node {
return this;
}
+ @Override
public String toString() {
return outerHtml();
}
@@ -1113,7 +1348,8 @@ public class Element extends Node {
@Override
public Element clone() {
Element clone = (Element) super.clone();
- clone.classNames(); // creates linked set of class names from class attribute
+ clone.classNames(); // creates linked set of class names from class
+ // attribute
return clone;
}
}