XML processing utilities for Apache Groovy including markup builders, parsers, and navigation tools
—
Groovy XML provides JAXB (Java Architecture for XML Binding) integration through extension methods that simplify marshalling and unmarshalling operations.
Extension methods that add JAXB functionality to standard JAXB classes.
@Deprecated
class JaxbGroovyMethods {
/**
* Marshall an object to a xml String.
* @param self a Marshaller which can marshall the type of the given object
* @param jaxbElement object to marshall to a String
* @return String representing the object as xml
*/
static <T> String marshal(Marshaller self, T jaxbElement)
/**
* Unmarshall XML String to an object.
* @param self an Unmarshaller
* @param xml the XML String to unmarshall
* @return the unmarshalled object
*/
static <T> T unmarshal(Unmarshaller self, String xml)
/**
* Create a Marshaller from JAXBContext.
* @param self a JAXBContext
* @return a new Marshaller instance
*/
static Marshaller createMarshaller(JAXBContext self)
/**
* Create an Unmarshaller from JAXBContext.
* @param self a JAXBContext
* @return a new Unmarshaller instance
*/
static Unmarshaller createUnmarshaller(JAXBContext self)
}Note: This class is deprecated. Use org.apache.groovy.jaxb.extensions.JaxbExtensions for new projects.
import javax.xml.bind.JAXBContext
import javax.xml.bind.annotation.XmlRootElement
@XmlRootElement
class Person {
String name
int age
String email
}
// Create JAXB context
def context = JAXBContext.newInstance(Person)
def marshaller = context.createMarshaller()
marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, true)
// Create and marshal object
def person = new Person(name: 'John Doe', age: 30, email: 'john@example.com')
def xmlString = marshaller.marshal(person) // Extension method
println xmlStringdef xmlText = '''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person>
<name>Jane Smith</name>
<age>25</age>
<email>jane@example.com</email>
</person>'''
def context = JAXBContext.newInstance(Person)
def unmarshaller = context.createUnmarshaller()
def person = unmarshaller.unmarshal(xmlText) // Extension method
println "Name: ${person.name}, Age: ${person.age}"import javax.xml.bind.annotation.*
@XmlRootElement(name = "catalog")
@XmlAccessorType(XmlAccessType.FIELD)
class BookCatalog {
@XmlElement(name = "book")
List<Book> books = []
}
@XmlAccessorType(XmlAccessType.FIELD)
class Book {
@XmlAttribute
String id
@XmlElement
String title
@XmlElement
String author
@XmlElement
BigDecimal price
}
// Create complex object structure
def catalog = new BookCatalog()
catalog.books << new Book(id: '1', title: 'The Great Gatsby',
author: 'F. Scott Fitzgerald', price: 12.99)
catalog.books << new Book(id: '2', title: '1984',
author: 'George Orwell', price: 13.99)
// Marshal with formatting
def context = JAXBContext.newInstance(BookCatalog, Book)
def marshaller = context.createMarshaller()
marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, true)
def catalogXml = marshaller.marshal(catalog)
println catalogXml
// Unmarshal back
def unmarshaller = context.createUnmarshaller()
def restoredCatalog = unmarshaller.unmarshal(catalogXml)
restoredCatalog.books.each { book ->
println "Book: ${book.title} by ${book.author} - \$${book.price}"
}import javax.xml.bind.annotation.XmlSchema
@XmlRootElement(name = "document", namespace = "http://example.com/ns")
@XmlAccessorType(XmlAccessType.FIELD)
class NamespacedDocument {
@XmlElement(namespace = "http://example.com/ns")
String title
@XmlElement(namespace = "http://example.com/ns")
String content
}
def doc = new NamespacedDocument(
title: 'Namespaced Document',
content: 'This document uses XML namespaces'
)
def context = JAXBContext.newInstance(NamespacedDocument)
def marshaller = context.createMarshaller()
marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, true)
def nsXml = marshaller.marshal(doc)
println nsXml // Will include namespace declarations// Combine JAXB objects with MarkupBuilder
def createHybridDocument = { jaxbObject ->
def context = JAXBContext.newInstance(jaxbObject.class)
def marshaller = context.createMarshaller()
// Get JAXB XML as string
def jaxbXml = marshaller.marshal(jaxbObject)
// Parse and integrate with MarkupBuilder
def parser = new XmlParser()
def jaxbNode = parser.parseText(jaxbXml)
def writer = new StringWriter()
def xml = new MarkupBuilder(writer)
xml.document {
header {
title('Combined Document')
generated(new Date().toString())
}
// Embed JAXB content
jaxbContent {
mkp.yieldUnescaped(jaxbXml)
}
footer {
note('Generated using JAXB and MarkupBuilder')
}
}
return writer.toString()
}
def person = new Person(name: 'Alice Johnson', age: 28, email: 'alice@example.com')
def hybridDoc = createHybridDocument(person)
println hybridDocimport javax.xml.bind.JAXBException
import javax.xml.bind.UnmarshalException
def safeUnmarshal = { xmlString, clazz ->
try {
def context = JAXBContext.newInstance(clazz)
def unmarshaller = context.createUnmarshaller()
// Enable validation if schema is available
// unmarshaller.setSchema(schema)
return unmarshaller.unmarshal(xmlString)
} catch (UnmarshalException e) {
println "Unmarshalling failed: ${e.message}"
return null
} catch (JAXBException e) {
println "JAXB error: ${e.message}"
return null
}
}
// Test with invalid XML
def invalidXml = '<person><name>John</name><age>not-a-number</age></person>'
def result = safeUnmarshal(invalidXml, Person)
if (result) {
println "Successfully unmarshalled: ${result.name}"
} else {
println "Failed to unmarshal XML"
}For new projects, use the updated JAXB extensions:
// Instead of deprecated JaxbGroovyMethods
import org.apache.groovy.jaxb.extensions.JaxbExtensions
def context = JAXBContext.newInstance(Person)
def marshaller = context.createMarshaller()
def person = new Person(name: 'Bob', age: 35, email: 'bob@example.com')
// Use new extension methods
def xmlString = JaxbExtensions.marshal(marshaller, person)
println xmlString// Reuse JAXBContext instances - they are thread-safe and expensive to create
class JaxbHelper {
private static final Map<Class, JAXBContext> contexts = [:]
static JAXBContext getContext(Class clazz) {
return contexts.computeIfAbsent(clazz) { c ->
JAXBContext.newInstance(c)
}
}
static String marshal(Object obj) {
def context = getContext(obj.class)
def marshaller = context.createMarshaller()
return marshaller.marshal(obj)
}
static <T> T unmarshal(String xml, Class<T> clazz) {
def context = getContext(clazz)
def unmarshaller = context.createUnmarshaller()
return unmarshaller.unmarshal(xml)
}
}
// Usage with cached contexts
def person1 = new Person(name: 'Person 1', age: 30, email: 'p1@example.com')
def person2 = new Person(name: 'Person 2', age: 25, email: 'p2@example.com')
def xml1 = JaxbHelper.marshal(person1) // Creates context
def xml2 = JaxbHelper.marshal(person2) // Reuses context
println xml1
println xml2Install with Tessl CLI
npx tessl i tessl/maven-org-codehaus-groovy--groovy-xml