diff --git a/src/main/java/org/jsoup/UncheckedIOException.java b/src/main/java/org/jsoup/UncheckedIOException.java
deleted file mode 100644
index a3b4fa31b6..0000000000
--- a/src/main/java/org/jsoup/UncheckedIOException.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.jsoup;
-
-import java.io.IOException;
-
-/**
- * @deprecated Use {@link java.io.UncheckedIOException} instead. This class acted as a compatibility shim for Java
- * versions prior to 1.8.
- */
-@Deprecated
-public class UncheckedIOException extends java.io.UncheckedIOException {
- public UncheckedIOException(IOException cause) {
- super(cause);
- }
-
- public UncheckedIOException(String message) {
- super(new IOException(message));
- }
-
- public IOException ioException() {
- return getCause();
- }
-}
diff --git a/src/main/java/org/jsoup/helper/HttpConnection.java b/src/main/java/org/jsoup/helper/HttpConnection.java
index a33bcd9110..501cce58bd 100644
--- a/src/main/java/org/jsoup/helper/HttpConnection.java
+++ b/src/main/java/org/jsoup/helper/HttpConnection.java
@@ -3,7 +3,6 @@
import org.jsoup.Connection;
import org.jsoup.HttpStatusException;
import org.jsoup.Progress;
-import org.jsoup.UncheckedIOException;
import org.jsoup.UnsupportedMimeTypeException;
import org.jsoup.internal.ControllableInputStream;
import org.jsoup.internal.Functions;
@@ -11,7 +10,6 @@
import org.jsoup.nodes.Document;
import org.jsoup.parser.Parser;
import org.jsoup.parser.StreamParser;
-import org.jsoup.parser.TokenQueue;
import org.jspecify.annotations.Nullable;
import javax.net.ssl.HttpsURLConnection;
@@ -25,6 +23,7 @@
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
+import java.io.UncheckedIOException;
import java.net.CookieManager;
import java.net.CookieStore;
import java.net.HttpURLConnection;
diff --git a/src/main/java/org/jsoup/nodes/Element.java b/src/main/java/org/jsoup/nodes/Element.java
index 1a1538edd6..1536cda431 100644
--- a/src/main/java/org/jsoup/nodes/Element.java
+++ b/src/main/java/org/jsoup/nodes/Element.java
@@ -23,6 +23,7 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@@ -44,7 +45,7 @@ An HTML Element consists of a tag name, attributes, and child nodes (including t
From an Element, you can extract data, traverse the node graph, and manipulate the HTML.
*/
-public class Element extends Node {
+public class Element extends Node implements Iterable {
private static final List EmptyChildren = Collections.emptyList();
private static final Pattern ClassSplit = Pattern.compile("\\s+");
private static final String BaseUriKey = Attributes.internalKey("baseUri");
@@ -1911,15 +1912,20 @@ public Element forEachNode(Consumer super Node> action) {
Perform the supplied action on this Element and each of its descendant Elements, during a depth-first traversal.
Elements may be inspected, changed, added, replaced, or removed.
@param action the function to perform on the element
- @return this Element, for chaining
@see Node#forEachNode(Consumer)
- @deprecated use {@link #stream()}.{@link Stream#forEach(Consumer) forEach(Consumer)} instead. (Removing this method
- so Element can implement Iterable, which this signature conflicts with due to the non-void return.)
*/
- @Deprecated
- public Element forEach(Consumer super Element> action) {
+ @Override
+ public void forEach(Consumer super Element> action) {
stream().forEach(action);
- return this;
+ }
+
+ /**
+ Returns an Iterator that iterates this Element and each of its descendant Elements, in document order.
+ @return an Iterator
+ */
+ @Override
+ public Iterator iterator() {
+ return new NodeIterator<>(this, Element.class);
}
@Override
diff --git a/src/main/java/org/jsoup/parser/CharacterReader.java b/src/main/java/org/jsoup/parser/CharacterReader.java
index 9c16d44da1..80359393c6 100644
--- a/src/main/java/org/jsoup/parser/CharacterReader.java
+++ b/src/main/java/org/jsoup/parser/CharacterReader.java
@@ -1,11 +1,11 @@
package org.jsoup.parser;
-import org.jsoup.UncheckedIOException;
import org.jsoup.helper.Validate;
import org.jsoup.internal.SoftPool;
import org.jspecify.annotations.Nullable;
import java.io.IOException;
+import java.io.UncheckedIOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
diff --git a/src/test/java/org/jsoup/nodes/ElementTest.java b/src/test/java/org/jsoup/nodes/ElementTest.java
index 2c2fd50d9b..b53444aeaa 100644
--- a/src/test/java/org/jsoup/nodes/ElementTest.java
+++ b/src/test/java/org/jsoup/nodes/ElementTest.java
@@ -18,6 +18,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@@ -26,6 +27,8 @@
import java.util.regex.Pattern;
import java.util.stream.Stream;
+import static org.jsoup.nodes.NodeIteratorTest.assertIterates;
+import static org.jsoup.nodes.NodeIteratorTest.trackSeen;
import static org.jsoup.select.SelectorTest.assertSelectedOwnText;
import static org.junit.jupiter.api.Assertions.*;
@@ -2992,4 +2995,22 @@ void prettySerializationRoundTrips(Document.OutputSettings settings) {
assertEquals("Hello world", div.text());
}
+
+ @Test void elementIsIterable() {
+ Document doc = Jsoup.parse("");
+ String expect = "div;a#1;a#2;b;b;a#3;"; // elements only, in doc order
+ Element div = doc.expectFirst("div");
+
+ // for each pattern
+ StringBuilder seen = new StringBuilder();
+ for (Element el: div) {
+ trackSeen(el, seen);
+ }
+ assertEquals(expect, seen.toString());
+
+ // iterator
+ seen = new StringBuilder();
+ Iterator iterator = div.iterator();
+ assertIterates(iterator, expect);
+ }
}
diff --git a/src/test/java/org/jsoup/nodes/NodeIteratorTest.java b/src/test/java/org/jsoup/nodes/NodeIteratorTest.java
index ab7e9345e5..b5b77fbc83 100644
--- a/src/test/java/org/jsoup/nodes/NodeIteratorTest.java
+++ b/src/test/java/org/jsoup/nodes/NodeIteratorTest.java
@@ -3,6 +3,7 @@
import org.jsoup.Jsoup;
import org.junit.jupiter.api.Test;
+import java.util.Iterator;
import java.util.NoSuchElementException;
import static org.junit.jupiter.api.Assertions.*;
@@ -230,7 +231,7 @@ class NodeIteratorTest {
assertContents(doc, "#root;html;head;body;div#1;p;One++;p;Two++;div#2;p;Three++;p;Four++;");
}
- static void assertIterates(NodeIterator it, String expected) {
+ static void assertIterates(Iterator it, String expected) {
Node previous = null;
StringBuilder actual = new StringBuilder();
while (it.hasNext()) {
@@ -263,4 +264,4 @@ else if (node instanceof TextNode)
actual.append(";");
}
-}
\ No newline at end of file
+}