kiss
XML
A class for parsing, traversing, and manipulating XML and HTML documents with a jQuery-like fluent API.
This class wraps the standard org.w3c.dom
API to provide a more
convenient way to work with XML structures. It includes a CSS selector engine
(which converts CSS selectors to XPath) for finding elements and a lenient
HTML parser.
XML
instance (or instances sharing the same Document
)
is accessed by multiple threads without external synchronization.
Traversal and read operations are generally safe if the DOM is not being modified.
accept
(XML
parent
)
void
XML
parent
)XML parent |
A parent |
Inserts this XML as a child element for the specified parent element.
This method implements the Consumer
interface, allowing an XML
object to be used in functional contexts, for example, with streams or
methods that accept a Consumer
.
append
(Object
xml
)
XML
Object
xml
)Object xml |
An element set, XML string, |
XML |
This |
Insert content, specified by the parameter, to the end of each element in the set of matched elements.
The content can be an XML string, another XML
object, a Node
,
or a NodeList
. If multiple elements are in the current set, the content
is cloned for each append operation except for the last one to ensure that
the same node instance is not inserted multiple times if it's part of the same document.
prepend
(Object
xml
)
XML
Object
xml
)Object xml |
An element set, XML string, |
XML |
This |
Insert content, specified by the parameter, to the beginning of each element in the set of matched elements.
The content can be an XML string, another XML
object, a Node
,
or a NodeList
. If multiple elements are in the current set, the content
is cloned for each prepend operation except for the last one.
before
(Object
xml
)
XML
Object
xml
)Object xml |
An element set, XML string, |
XML |
This |
Insert content, specified by the parameter, before each element in the set of matched elements.
The content can be an XML string, another XML
object, a Node
,
or a NodeList
. If multiple elements are in the current set, the content
is cloned for each insertion operation except for the last one.
The parent node of the current elements must exist.
after
(Object
xml
)
XML
Object
xml
)Object xml |
An element set, XML string, |
XML |
This |
Insert content, specified by the parameter, after each element in the set of matched elements.
The content can be an XML string, another XML
object, a Node
,
or a NodeList
. If multiple elements are in the current set, the content
is cloned for each insertion operation except for the last one.
The parent node of the current elements must exist.
empty
()
XML
XML |
This |
Remove all child nodes of the set of matched elements from the DOM.
This method does not remove the matched elements themselves, only their children.
remove
()
XML
XML |
This |
Remove the set of matched elements from the DOM.
Similar to #empty()
, the #remove()
method takes elements out of the DOM. Use
#remove()
when you want to remove the element itself, as well as everything inside
it. The parent node of the current elements must exist.
wrap
(Object
xml
)
XML
Object
xml
)Object xml |
An XML string, |
XML |
This |
Wrap an XML or HTML structure around each element in the set of matched elements.
The xml
parameter, which specifies the wrapping structure, is cloned for
each element in the current set. The current element is then moved inside this
cloned structure.
wrapAll
(Object
xml
)
XML
Object
xml
)Object xml |
An XML string, |
XML |
This |
Wrap an XML or HTML structure around all elements in the set of matched elements.
This method takes the first element in the current set, inserts the wrapping structure after it, and then moves all elements from the original set (including the first one) inside the newly inserted wrapping structure.
clone
()
XML
XML |
A new |
Create a deep copy of the set of matched elements.
The .clone()
method performs a deep copy of the set of matched elements, meaning that
it copies the matched elements as well as all of their descendant elements and text nodes.
When used in conjunction with one of the insertion methods, .clone()
is a convenient
way to duplicate elements on a page. The cloned nodes are not part of any document until
inserted.
text
()
String
String |
A |
Get the combined text contents of each element in the set of matched elements, including their descendants.
For multiple matched elements, their text contents are concatenated together in the order
they appear in the nodes
list.
text
(String
text
)
XML
String
text
)String text |
A text to set. If |
XML |
This |
Set the content of each element in the set of matched elements to the specified text.
Any existing child nodes of the matched elements will be removed and replaced by a single text node containing the specified text.
name
()
String
String |
An element name as a |
Get the element name (tag name) for the first element in the set of matched elements.
attr
(String
name
)
String
String
name
)String name |
An attribute name. |
String |
The attribute value as a |
Get the value of an attribute for the first element in the set of matched elements.
attr
(String
name
, Object
value
)
XML
String
name
, Object
value
)String name |
An attribute name. If |
Object value |
An attribute value. If |
XML |
This |
Set one or more attributes for the set of matched elements.
If value
is null
, the attribute is removed.
Handles namespace attributes (e.g., attributes starting with "xmlns:") correctly
by using setAttributeNS
or removeAttributeNS
.
addClass
(String
names
)
XML
String
names
)String names |
One or more space-separated class names to add. |
XML |
This |
Adds the specified class(es) to each of the set of matched elements.
It's important to note that this method does not replace a class. It simply adds the class, appending it to any which may already be assigned to the elements. More than one class may be added at a time, separated by a space, to the set of matched elements. If a class to be added already exists, it is not added again.
removeClass
(String
names
)
XML
String
names
)String names |
Space-separated class name list(s) to remove. If empty, all classes are removed. |
XML |
This |
Remove a single class, multiple classes, or all classes from each element in the set of matched elements.
If a class name is included as a parameter, then only that class will be removed from the set of matched elements. If no class names are specified in the parameter (i.e., an empty array or no arguments), all classes will be removed (by setting the class attribute to an empty string). More than one class may be removed at a time, specified as separate strings or space-separated within a single string.
toggleClass
(String
name
)
XML
String
name
)String name |
A single class name to toggle. |
XML |
This |
Add or remove one or more classes from each element in the set of matched elements, depending on either the class's presence or the value of the switch argument (if provided). This implementation currently only supports toggling a single class name.
hasClass
(String
name
)
boolean
String
name
)String name |
A class name to search for. |
boolean |
true if at least one element in the set has the specified class,
false otherwise. |
Determine whether any of the matched elements are assigned the given class.
first
()
XML
XML |
A new |
Reduce the set of matched elements to the first in the set.
If the current set is empty, an XML
object representing an
empty set is returned.
public void first() {
String text = """
<root>
<child1 class='a'/>
<child2 class='a'/>
<child3 class='a'/>
</root>
""";
XML found = I.xml(text).find(".a");
assert found.size() == 3;
// traverse to first matched element
XML first = found.first();
assert first.size() == 1;
assert first.name().equals("child1");
}
public void first() {
XML xml = I.xml("""
<root>
<child1 class='a'/>
<child2 class='a'/>
<child3 class='a'/>
</root>
""");
XML found = xml.find(".a");
assert found.size() == 3;
XML first = found.first();
assert first.size() == 1;
assert first.name().equals("child1");
}
last
()
XML
XML |
A new |
Reduce the set of matched elements to the final one in the set.
If the current set is empty, an XML
object representing an
empty set is returned.
public void last() {
String text = """
<root>
<child1 class='a'/>
<child2 class='a'/>
<child3 class='a'/>
</root>
""";
XML found = I.xml(text).find(".a");
assert found.size() == 3;
// traverse to last matched element
XML last = found.last();
assert last.size() == 1;
assert last.name().equals("child3");
}
void last() {
XML xml = I.xml("""
<root>
<child1 class='a'/>
<child2 class='a'/>
<child3 class='a'/>
</root>
""");
XML found = xml.find(".a");
assert found.size() == 3;
XML last = found.last();
assert last.size() == 1;
assert last.name().equals("child3");
}
child
(String
name
)
XML
String
name
)String name |
A child element name. |
XML |
A new |
Append a new child element with the specified name to each element in the current set,
and then return a new XML
object representing these newly created child elements.
child
(String
name
, ConsumerXML
child
)
XML
String
name
, ConsumerXML
child
)String name |
A child element name. |
Consumer child |
A |
XML |
A new |
Append a new child element with the specified name to each element in the current set,
apply a Consumer
function to the new XML
object representing these children,
and then return this new XML
object.
This is useful for creating and immediately configuring child elements in a fluent manner.
children
()
XML
XML |
A new |
Get the children of each element in the current set of matched elements.
This is equivalent to find(">*")
. Only element nodes are returned.
public void children() {
// traverse to child elements
XML root = I.xml("""
<root>
<first/>
<center/>
<last/>
</root>
""");
assert root.children().size() == 3;
// skip text node
root = I.xml("""
<root>
text<first/>is
<child>
<center/>
</child>
ignored<last/>!!
</root>
""");
assert root.children().size() == 3;
// can't traverse
root = I.xml("<root/>");
assert root.children().size() == 0;
}
public void children() {
XML root1 = I.xml("""
<root>
<first/>
<center/>
<last/>
</root>
""");
assert root1.children().size() == 3;
XML root2 = I.xml("""
<root>
text<first/>is
<child>
<center/>
</child>
ignored<last/>!!
</root>
""");
assert root2.children().size() == 3;
XML root3 = I.xml("<root/>");
assert root3.children().size() == 0;
}
element
(String
name
)
XML
String
name
)String name |
The tag name of the elements to retrieve. A value of "*" retrieves all descendant elements. |
XML |
A new |
Retrieves all descendant elements with the specified tag name from each element in the current set of matched elements.
public void elementFromSingleParent() {
String text = """
<root>
<child1/>
<child2/>
<child3/>
</root>
""";
XML root = I.xml(text);
XML c2 = root.element("child2");
assert c2.size() == 1;
assert c2.name().equals("child2");
}
firstChild
()
XML
XML |
A new |
Get the first child element of each element in the current set of matched elements.
This is equivalent to find(">*:first-child")
.
If an element in the set has no child elements, it contributes nothing to the result.
public void firstChild() {
// traverse to first child element
XML root = I.xml("""
<root>
<first/>
<center/>
<last/>
</root>
""");
assert root.firstChild().name().equals("first");
// skip text node
root = I.xml("""
<root>
text is ignored
<first/>
<center/>
<last/>
</root>
""");
assert root.firstChild().name().equals("first");
// can't traverse
root = I.xml("<root/>");
assert root.firstChild().size() == 0;
}
public void firstChild() {
// traverse to first child element
XML root1 = I.xml("""
<root>
<first/>
<center/>
<last/>
</root>
""");
assert root1.firstChild().name().equals("first");
// skip text node
XML root2 = I.xml("""
<root>
text is ignored
<first/>
<center/>
<last/>
</root>
""");
assert root2.firstChild().name().equals("first");
// can't traverse
XML root3 = I.xml("<root/>");
assert root3.firstChild().size() == 0;
}
lastChild
()
XML
XML |
A new |
Get the last child element of each element in the current set of matched elements.
This is equivalent to find(">*:last-child")
.
If an element in the set has no child elements, it contributes nothing to the result.
public void lastChild() {
// traverse to last child element
XML root = I.xml("""
<root>
<first/>
<center/>
<last/>
</root>
""");
assert root.lastChild().name().equals("last");
// skip text node
root = I.xml("""
<root>
<first/>
<center/>
<last/>
text is ignored
</root>
""");
assert root.lastChild().name().equals("last");
// can't traverse
root = I.xml("<root/>");
assert root.lastChild().size() == 0;
}
public void lastChild() {
XML root1 = I.xml("""
<root>
<first/>
<center/>
<last/>
</root>
""");
assert root1.lastChild().name().equals("last");
XML root2 = I.xml("""
<root>
<first/>
<center/>
<last/>
text is ignored
</root>
""");
assert root2.lastChild().name().equals("last");
XML root3 = I.xml("<root/>");
assert root3.lastChild().size() == 0;
}
parent
()
XML
XML |
A new |
Get the parent of each element in the current set of matched elements.
If an element has no parent (e.g., it's a document node or a detached element),
or its parent is not an Element
node, it does not contribute to the result set.
The resulting set contains unique parent elements.
public void parent() {
// traverse to parent element
XML root = I.xml("""
<root>
<first/>
<center/>
<last/>
</root>
""");
assert root.find("first").parent().name() == "root";
assert root.find("center").parent().name() == "root";
assert root.find("last").parent().name() == "root";
// traverse to parent element from nested element
root = I.xml("<root><child><grand/></child></root>");
assert root.find("grand").parent().name() == "child";
}
public void parentFromMultipleChildrenWithSameParent() {
String text = """
<root>
<parent1>
<child1 class='target'/>
<child2 class='target'/>
</parent1>
</root>
""";
XML children = I.xml(text).find(".target");
assert children.size() == 2;
XML parent = children.parent();
assert parent.size() == 1;
assert parent.name().equals("parent1");
}
public void parentFromMultipleChildrenWithDifferentParents() {
String text = """
<root>
<parent1>
<child1 class='target'/>
</parent1>
<parent2>
<child2 class='target'/>
</parent2>
</root>
""";
XML children = I.xml(text).find(".target");
assert children.size() == 2;
XML parents = children.parent();
assert parents.size() == 2;
assert parents.first().name() == "parent1";
assert parents.last().name() == "parent2";
}
public void parent() {
XML xml1 = I.xml("""
<root>
<first/>
<center/>
<last/>
</root>
""");
assert xml1.find("first").parent().name().equals("root");
assert xml1.find("center").parent().name().equals("root");
assert xml1.find("last").parent().name().equals("root");
XML xml2 = I.xml("<root><child><grand/></child></root>");
assert xml2.find("grand").parent().name().equals("child");
}
public void parentFromMultipleChildrenWithSameParent() {
XML xml = I.xml("""
<root>
<parent1>
<child1 class='target'/>
<child2 class='target'/>
</parent1>
</root>
""");
XML children = xml.find(".target");
assert children.size() == 2;
XML parent = children.parent();
assert parent.size() == 1;
assert parent.name().equals("parent1");
}
public void parentFromMultipleChildrenWithDifferentParents() {
XML xml = I.xml("""
<root>
<parent1>
<child1 class='target'/>
</parent1>
<parent2>
<child2 class='target'/>
</parent2>
</root>
""");
XML children = xml.find(".target");
assert children.size() == 2;
XML parents = children.parent();
assert parents.size() == 2;
assert parents.first().name().equals("parent1");
assert parents.last().name().equals("parent2");
}
parentUntil
(String
selector
)
XML
String
selector
)String selector |
A CSS selector expression to indicate where to stop matching ancestor elements. If the selector is empty or null, it might retrieve all ancestors up to the root. |
XML |
A new |
Get the ancestors of each element in the current set of matched elements, up to but not including the element matched by the selector. The elements are returned in order from the closest parent to the furthest.
prev
()
XML
XML |
A new |
Get the previous sibling element of each element in the current set of matched elements.
This is equivalent to find("<*")
. Only element nodes are returned.
public void prev() {
XML root = I.xml("""
<root>
<first/>
text is ignored
<center/>
<last/>
</root>
""");
// traverse to previous element
XML next = root.find("last").prev();
assert next.name() == "center";
// skip previous text node
next = root.find("center").prev();
assert next.name() == "first";
// can't traverse
next = root.find("first").prev();
assert next.size() == 0;
}
public void prev() {
XML root = I.xml("""
<root>
<first/>
text is ignored
<center/>
<last/>
</root>
""");
XML prev1 = root.find("last").prev();
assert prev1.name().equals("center");
XML prev2 = root.find("center").prev();
assert prev2.name().equals("first");
XML prev3 = root.find("first").prev();
assert prev3.size() == 0;
}
prevUntil
(String
selector
)
XML
String
selector
)String selector |
A CSS selector expression to indicate where to stop matching preceding sibling elements. |
XML |
A new |
Get all preceding sibling elements of each element in the current set of matched elements, up to but not including the element matched by the selector. The elements are returned in document order (the one closest to the starting element first).
next
()
XML
XML |
A new |
Get the next sibling element of each element in the current set of matched elements.
This is equivalent to find("+*")
. Only element nodes are returned.
public void next() {
XML root = I.xml("""
<root>
<first/>
<center/>
text is ignored
<last/>
</root>
""");
// traverse to next element
XML next = root.find("first").next();
assert next.name() == "center";
// skip next text node
next = root.find("center").next();
assert next.name() == "last";
// can't traverse
next = root.find("last").next();
assert next.size() == 0;
}
public void next() {
XML root = I.xml("""
<root>
<first/>
<center/>
text is ignored
<last/>
</root>
""");
XML next1 = root.find("first").next();
assert next1.name().equals("center");
XML next2 = root.find("center").next();
assert next2.name().equals("last");
XML next3 = root.find("last").next();
assert next3.size() == 0;
}
nextUntil
(String
selector
)
XML
String
selector
)String selector |
A CSS selector expression to indicate where to stop matching following sibling elements. |
XML |
A new |
Get all following sibling elements of each element in the current set of matched elements, up to but not including the element matched by the selector. The elements are returned in document order.
find
(String
selector
)
XML
String
selector
)String selector |
A string containing a CSS selector expression to match elements against. Can also be an XPath expression if prefixed with "xpath:". |
XML |
A new |
Get the descendants of each element in the current set of matched elements, filtered by a CSS selector.
The selector is converted to an XPath expression, which is then evaluated against each
element in the current set. The results are aggregated into a new XML
object.
size
()
int
int |
A size of current node set. |
Return size of the current node set. This indicates how many DOM elements
are currently matched by this XML
object.
effect
(WiseFunctionXML
, R
process
)
R
WiseFunctionXML
, R
process
)R |
The type of the result returned by the process function. |
WiseFunction process |
A |
R |
The result of applying the process function to this |
Apply the specified process to this XML
object itself and return the result
of the process. This is helpful for inserting custom operations into a fluent
method chain without breaking the chain if the process returns this
,
or for extracting a different type of result.
iterator
()
IteratorXML
XML
Iterator |
An |
Returns an iterator over the set of matched elements. Each element
in the iteration is an XML
object representing a single DOM node
from the current set.
This allows the XML
object to be used in enhanced for-loops:
to
()
Node
Node |
The first |
Convert the first element in the current set to its underlying Node
representation.
to
(Appendable
output
)
void
Appendable
output
)Appendable output |
An |
Write the XML representation of the matched elements to the specified Appendable
(e.g., StringBuilder
, Writer
) with default formatting (tab indentation).
If multiple elements are matched, they are serialized sequentially.
to
(Appendable
output
, String
indent
, String
inlineAndNonEmpty
)
void
Appendable
output
, String
indent
, String
inlineAndNonEmpty
)Appendable output |
An output channel. |
String indent |
Specify the indentation string to use when formatting. If null is specified, formatting will not be performed. |
String inlineAndNonEmpty |
At the time of formatting, the element with the specified name is regarded as an inline element, and line breaks and indentation are not performed on the surrounding elements. Also, if an element whose name starts with "&" is specified, it will not be treated as an empty element and will always have a start tag and end tag. |
Write this element to the specified output with your format settings.
escape
(String
input
)
String
String
input
)String input |
The input string to escape. Null is treated as an empty string. |
String |
A string with XML-escaped characters, safe for use in XML contexts. |
Escape XML special characters (&, <, %gt;, ", ') in an idempotent way.
This method replaces the characters &, <, >, ", '
with their
corresponding XML entity references (&, <, >, ", '
).
It ensures idempotency, meaning the same result is returned
even if the method is called multiple times on the same string.
Existing entities (both named and numeric, like &
or &
)
are preserved as-is and are not re-escaped.
toString
()
String
String |