Apache Groovy is a powerful multi-faceted programming language for the JVM platform
—
Comprehensive XML parsing, navigation, and generation capabilities including both tree-based (XmlParser) and streaming (XmlSlurper) approaches with GPath expression support. These tools provide powerful XML manipulation and generation capabilities.
Streaming XML parser that creates GPathResult objects for efficient navigation.
class XmlSlurper {
/**
* Creates an XmlSlurper with default settings.
*/
XmlSlurper();
/**
* Creates an XmlSlurper with validation enabled/disabled.
*/
XmlSlurper(boolean validating);
/**
* Creates an XmlSlurper with validation and namespace awareness.
*/
XmlSlurper(boolean validating, boolean namespaceAware);
/**
* Creates an XmlSlurper with custom SAXParser.
*/
XmlSlurper(SAXParser parser);
/**
* Creates an XmlSlurper with custom XMLReader.
*/
XmlSlurper(XMLReader reader);
/**
* Parses XML from a string.
*/
GPathResult parseText(String text);
/**
* Parses XML from a file.
*/
GPathResult parse(File file);
/**
* Parses XML from a URL.
*/
GPathResult parse(URL url);
/**
* Parses XML from an InputStream.
*/
GPathResult parse(InputStream input);
/**
* Parses XML from a Reader.
*/
GPathResult parse(Reader reader);
/**
* Sets the XML parser to use.
*/
void setXMLReader(XMLReader reader);
/**
* Gets the XML parser being used.
*/
XMLReader getXMLReader();
/**
* Sets an entity resolver.
*/
void setEntityResolver(EntityResolver resolver);
/**
* Sets an error handler.
*/
void setErrorHandler(ErrorHandler handler);
/**
* Sets a DTD handler.
*/
void setDTDHandler(DTDHandler handler);
/**
* Sets whether to keep ignorable whitespace.
*/
void setKeepIgnorableWhitespace(boolean keepIgnorableWhitespace);
}GPathResult provides powerful XML navigation using GPath expressions.
abstract class GPathResult implements Iterable<GPathResult>, Writable {
/**
* Gets the text content of this node.
*/
String text();
/**
* Gets the number of child nodes.
*/
int size();
/**
* Checks if this result is empty.
*/
boolean isEmpty();
/**
* Gets all child nodes.
*/
GPathResult children();
/**
* Gets the parent node.
*/
GPathResult parent();
/**
* Finds child nodes matching the closure condition.
*/
GPathResult find(Closure closure);
/**
* Finds all child nodes matching the closure condition.
*/
GPathResult findAll(Closure closure);
/**
* Collects values from child nodes using a closure.
*/
List<Object> collect(Closure closure);
/**
* Iterates over child nodes.
*/
GPathResult each(Closure closure);
/**
* Gets an attribute value.
*/
String attribute(String name);
/**
* Gets all attributes.
*/
Map<String, String> attributes();
/**
* Gets the local name of this node.
*/
String name();
/**
* Gets the namespace URI of this node.
*/
String namespaceURI();
/**
* Converts to a Node object.
*/
Node convertToNode();
/**
* Gets child by index.
*/
GPathResult getAt(int index);
/**
* Gets child by name.
*/
GPathResult getProperty(String name);
/**
* Sets a property value (for XML generation).
*/
void setProperty(String name, Object value);
/**
* Writes the XML representation to a Writer.
*/
Writer writeTo(Writer writer);
/**
* Returns an Iterator over child nodes.
*/
Iterator<GPathResult> iterator();
/**
* Returns a ListIterator over child nodes.
*/
ListIterator<GPathResult> listIterator();
/**
* Applies a closure to each child node and returns results.
*/
List<Object> list();
/**
* Gets the depth-first iterator.
*/
Iterator<GPathResult> depthFirst();
/**
* Gets the breadth-first iterator.
*/
Iterator<GPathResult> breadthFirst();
}XmlParser creates Node trees for XML processing with full DOM-like access.
class XmlParser {
/**
* Creates an XmlParser with default settings.
*/
XmlParser();
/**
* Creates an XmlParser with validation enabled/disabled.
*/
XmlParser(boolean validating);
/**
* Creates an XmlParser with validation and namespace awareness.
*/
XmlParser(boolean validating, boolean namespaceAware);
/**
* Creates an XmlParser with custom SAXParser.
*/
XmlParser(SAXParser parser);
/**
* Creates an XmlParser with custom XMLReader.
*/
XmlParser(XMLReader reader);
/**
* Parses XML from a string.
*/
Node parseText(String text);
/**
* Parses XML from a file.
*/
Node parse(File file);
/**
* Parses XML from a URL.
*/
Node parse(URL url);
/**
* Parses XML from an InputStream.
*/
Node parse(InputStream input);
/**
* Parses XML from a Reader.
*/
Node parse(Reader reader);
/**
* Sets trimming of whitespace-only text nodes.
*/
void setTrimWhitespace(boolean trimWhitespace);
/**
* Gets whether whitespace-only text nodes are trimmed.
*/
boolean isTrimWhitespace();
/**
* Sets whether to keep ignorable whitespace.
*/
void setKeepIgnorableWhitespace(boolean keepIgnorableWhitespace);
/**
* Sets an entity resolver.
*/
void setEntityResolver(EntityResolver resolver);
/**
* Sets an error handler.
*/
void setErrorHandler(ErrorHandler handler);
/**
* Sets a DTD handler.
*/
void setDTDHandler(DTDHandler handler);
}Builder for creating XML/HTML markup programmatically.
class MarkupBuilder extends BuilderSupport {
/**
* Creates a MarkupBuilder that writes to a Writer.
*/
MarkupBuilder(Writer writer);
/**
* Creates a MarkupBuilder that writes to a PrintWriter.
*/
MarkupBuilder(PrintWriter writer);
/**
* Creates a MarkupBuilder with indenting.
*/
MarkupBuilder(IndentPrinter printer);
/**
* Gets whether to escape attributes.
*/
boolean getEscapeAttributes();
/**
* Sets whether to escape attributes.
*/
void setEscapeAttributes(boolean escapeAttributes);
/**
* Gets whether the output should be omitted.
*/
boolean isOmitEmptyAttributes();
/**
* Sets whether empty attributes should be omitted.
*/
void setOmitEmptyAttributes(boolean omitEmptyAttributes);
/**
* Gets whether null attributes should be omitted.
*/
boolean isOmitNullAttributes();
/**
* Sets whether null attributes should be omitted.
*/
void setOmitNullAttributes(boolean omitNullAttributes);
/**
* Creates a processing instruction.
*/
void processingInstruction(Map<String, Object> attributes);
/**
* Creates a comment.
*/
void comment(String comment);
/**
* Creates CDATA section.
*/
void cdata(String content);
/**
* Yields to allow mixed content.
*/
void yield(String value);
/**
* Yields to allow mixed content with escaping control.
*/
void yield(String value, boolean escapeXml);
/**
* Yields unescaped content.
*/
void yieldUnescaped(String value);
}StreamingMarkupBuilder for efficient generation of large XML documents.
class StreamingMarkupBuilder {
/**
* Creates a StreamingMarkupBuilder.
*/
StreamingMarkupBuilder();
/**
* Gets the encoding to use.
*/
String getEncoding();
/**
* Sets the encoding to use.
*/
void setEncoding(String encoding);
/**
* Gets whether to use double quotes for attributes.
*/
boolean getUseDoubleQuotes();
/**
* Sets whether to use double quotes for attributes.
*/
void setUseDoubleQuotes(boolean useDoubleQuotes);
/**
* Binds a closure to create a Writable.
*/
Writable bind(Closure closure);
/**
* Binds a closure with custom binding.
*/
Writable bind(Map binding, Closure closure);
}Classes for handling XML namespaces.
class Namespace {
/**
* Creates a namespace with URI.
*/
Namespace(String uri);
/**
* Creates a namespace with URI and prefix.
*/
Namespace(String uri, String prefix);
/**
* Gets the namespace URI.
*/
String getUri();
/**
* Gets the namespace prefix.
*/
String getPrefix();
/**
* Creates a QName in this namespace.
*/
QName getName(String localName);
}
class QName {
/**
* Creates a QName with local name only.
*/
QName(String localName);
/**
* Creates a QName with namespace URI and local name.
*/
QName(String namespaceURI, String localName);
/**
* Creates a QName with namespace URI, local name, and prefix.
*/
QName(String namespaceURI, String localName, String prefix);
/**
* Gets the namespace URI.
*/
String getNamespaceURI();
/**
* Gets the local part.
*/
String getLocalPart();
/**
* Gets the prefix.
*/
String getPrefix();
/**
* Gets the qualified name.
*/
String getQualifiedName();
/**
* Checks if this QName matches another.
*/
boolean matches(Object object);
}import groovy.util.XmlSlurper;
import groovy.util.slurpersupport.GPathResult;
// Parse XML document
XmlSlurper slurper = new XmlSlurper();
String xml = """
<catalog xmlns:book="http://example.com/books">
<book:book id="1" category="fiction">
<book:title>The Great Gatsby</book:title>
<book:author>F. Scott Fitzgerald</book:author>
<book:price>12.99</book:price>
<book:available>true</book:available>
</book:book>
<book:book id="2" category="non-fiction">
<book:title>Sapiens</book:title>
<book:author>Yuval Noah Harari</book:author>
<book:price>15.99</book:price>
<book:available>false</book:available>
</book:book>
</catalog>
""";
GPathResult catalog = slurper.parseText(xml);
// Navigate and extract data using GPath
System.out.println("Total books: " + catalog.book.size());
// Access specific elements
GPathResult firstBook = catalog.book[0];
System.out.println("First book title: " + firstBook.title.text());
System.out.println("First book ID: " + firstBook.attribute("id"));
// Find books using closures
GPathResult fictionBooks = catalog.book.findAll { book ->
book.attribute("category").equals("fiction");
});
System.out.println("Fiction books: " + fictionBooks.size());
// Collect specific data
List<String> titles = catalog.book.collect { book ->
return book.title.text();
};
System.out.println("All titles: " + titles);
// Navigate with namespaces
GPathResult availableBooks = catalog.book.findAll { book ->
book.available.text().equals("true");
});
for (GPathResult book : availableBooks) {
System.out.println("Available: " + book.title.text() + " - $" + book.price.text());
}import groovy.xml.MarkupBuilder;
import java.io.StringWriter;
// Create XML using MarkupBuilder
StringWriter writer = new StringWriter();
MarkupBuilder builder = new MarkupBuilder(writer);
// Generate XML structure
builder.catalog(xmlns: "http://example.com/books") {
book(id: "1", category: "fiction") {
title("The Great Gatsby");
author("F. Scott Fitzgerald");
price("12.99");
available("true");
}
book(id: "2", category: "non-fiction") {
title("Sapiens");
author("Yuval Noah Harari");
price("15.99");
available("false");
description {
yieldUnescaped("<![CDATA[A fascinating look at human history]]>");
}
}
}
String generatedXml = writer.toString();
System.out.println(generatedXml);
// Using programmatic approach
StringWriter writer2 = new StringWriter();
MarkupBuilder builder2 = new MarkupBuilder(writer2);
List<Map<String, Object>> books = Arrays.asList(
Map.of("id", "1", "title", "Book One", "author", "Author One"),
Map.of("id", "2", "title", "Book Two", "author", "Author Two")
);
builder2.library() {
for (Map<String, Object> book : books) {
book(id: book.get("id")) {
title((String) book.get("title"));
author((String) book.get("author"));
}
}
}import groovy.xml.StreamingMarkupBuilder;
import groovy.lang.Closure;
// Create large XML documents efficiently
StreamingMarkupBuilder builder = new StreamingMarkupBuilder();
builder.setEncoding("UTF-8");
Closure xmlClosure = new Closure(null) {
public Object doCall() {
// This would be dynamically constructed
return new Object() {
public Object methodMissing(String name, Object args) {
if ("catalog".equals(name)) {
return new Object() {
public Object methodMissing(String innerName, Object innerArgs) {
// Handle nested elements
return null;
}
};
}
return null;
}
};
}
};
Writable xml = builder.bind(xmlClosure);
// Write to output
StringWriter output = new StringWriter();
xml.writeTo(output);
System.out.println(output.toString());import groovy.util.XmlParser;
import groovy.util.Node;
import groovy.util.NodeList;
// Parse XML into Node tree
XmlParser parser = new XmlParser();
parser.setTrimWhitespace(true);
Node catalog = parser.parseText(xml);
// Navigate using Node API
System.out.println("Root element: " + catalog.name());
// Get all book nodes
NodeList bookNodes = catalog.get("book");
for (Node book : bookNodes) {
// Access attributes
Map<String, String> attributes = book.attributes();
String id = attributes.get("id");
String category = attributes.get("category");
// Access child elements
Node titleNode = (Node) book.get("title").get(0);
Node authorNode = (Node) book.get("author").get(0);
Node priceNode = (Node) book.get("price").get(0);
System.out.println("Book " + id + " (" + category + "):");
System.out.println(" Title: " + titleNode.text());
System.out.println(" Author: " + authorNode.text());
System.out.println(" Price: $" + priceNode.text());
}
// Modify the tree
Node newBook = new Node(catalog, "book",
Map.of("id", "3", "category", "science"));
new Node(newBook, "title", "Cosmos");
new Node(newBook, "author", "Carl Sagan");
new Node(newBook, "price", "14.99");
catalog.append(newBook);import groovy.util.XmlSlurper;
import groovy.util.XmlParser;
import groovy.xml.XmlUtil;
// Transform XML structure
XmlSlurper slurper = new XmlSlurper();
GPathResult catalog = slurper.parseText(originalXml);
// Filter and transform
GPathResult expensiveBooks = catalog.book.findAll { book ->
Double.parseDouble(book.price.text()) > 13.0;
};
// Convert GPathResult to Node for manipulation
Node catalogNode = catalog.convertToNode();
// Add new elements
for (Node book : catalogNode.get("book")) {
Node price = (Node) book.get("price").get(0);
double priceValue = Double.parseDouble(price.text());
// Add discount element
Node discount = new Node(book, "discount",
priceValue > 15.0 ? "10%" : "5%");
}
// Serialize back to XML
String transformedXml = XmlUtil.serialize(catalogNode);
System.out.println(transformedXml);import groovy.xml.Namespace;
import groovy.xml.QName;
import groovy.util.XmlSlurper;
// Define namespaces
Namespace bookNS = new Namespace("http://example.com/books", "book");
Namespace authorNS = new Namespace("http://example.com/authors", "auth");
// Parse namespaced XML
XmlSlurper slurper = new XmlSlurper();
slurper.setNamespaceAware(true);
String namespacedXml = """
<catalog
xmlns:book="http://example.com/books"
xmlns:auth="http://example.com/authors">
<book:item id="1">
<book:title>Sample Book</book:title>
<auth:writer>Sample Author</auth:writer>
</book:item>
</catalog>
""";
GPathResult catalog = slurper.parseText(namespacedXml);
// Access namespaced elements
QName itemQName = bookNS.getName("item");
QName titleQName = bookNS.getName("title");
QName writerQName = authorNS.getName("writer");
// Navigate with namespace awareness
GPathResult items = catalog.getProperty(itemQName.getLocalPart());
for (GPathResult item : items) {
String title = item.getProperty(titleQName.getLocalPart()).text();
String writer = item.getProperty(writerQName.getLocalPart()).text();
System.out.println("Book: " + title + " by " + writer);
}Install with Tessl CLI
npx tessl i tessl/maven-org-codehaus-groovy--groovy