This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 06c645979f4ae9bc42a2b5462d28af42cfe0781b
Author: Paul King <[email protected]>
AuthorDate: Mon Apr 13 14:25:58 2026 +1000

    GROOVY-7571: XmlUtil should allow user to specify a character encoding when 
serializing
---
 .../src/main/java/groovy/xml/XmlUtil.java          | 159 ++++++++++++++++++++-
 .../groovy-xml/src/spec/doc/xml-userguide.adoc     |   9 ++
 .../src/spec/test/UserGuideXmlUtilTest.groovy      |  19 +++
 3 files changed, 182 insertions(+), 5 deletions(-)

diff --git a/subprojects/groovy-xml/src/main/java/groovy/xml/XmlUtil.java 
b/subprojects/groovy-xml/src/main/java/groovy/xml/XmlUtil.java
index f8530d957c..21304f80e2 100644
--- a/subprojects/groovy-xml/src/main/java/groovy/xml/XmlUtil.java
+++ b/subprojects/groovy-xml/src/main/java/groovy/xml/XmlUtil.java
@@ -55,7 +55,7 @@ import java.io.PrintWriter;
 import java.io.StringReader;
 import java.io.Writer;
 import java.net.URL;
-import java.nio.charset.StandardCharsets;
+import java.nio.charset.Charset;
 
 /**
  * Used for pretty printing XML content and other XML related utilities.
@@ -283,6 +283,138 @@ public class XmlUtil {
         serialize(asStreamSource(xmlString), w, allowDocTypeDeclaration);
     }
 
+    // --- SerializeOptions overloads ---
+
+    /**
+     * Return a pretty String version of the Element using the specified 
options.
+     *
+     * @param element the Element to serialize
+     * @param options the serialization options
+     * @return the pretty String representation of the Element
+     * @since 6.0.0
+     */
+    public static String serialize(Element element, SerializeOptions options) {
+        Writer sw = new StringBuilderWriter();
+        serialize(new DOMSource(element), sw, options);
+        return sw.toString();
+    }
+
+    /**
+     * Write a pretty version of the Element to the OutputStream using the 
specified options.
+     *
+     * @param element the Element to serialize
+     * @param os      the OutputStream to write to
+     * @param options the serialization options
+     * @since 6.0.0
+     */
+    public static void serialize(Element element, OutputStream os, 
SerializeOptions options) {
+        serialize(new DOMSource(element), os, options);
+    }
+
+    /**
+     * Return a pretty String version of the Node using the specified options.
+     *
+     * @param node    the Node to serialize
+     * @param options the serialization options
+     * @return the pretty String representation of the Node
+     * @since 6.0.0
+     */
+    public static String serialize(Node node, SerializeOptions options) {
+        Writer sw = new StringBuilderWriter();
+        serialize(asStreamSource(asString(node)), sw, options);
+        return sw.toString();
+    }
+
+    /**
+     * Write a pretty version of the Node to the OutputStream using the 
specified options.
+     *
+     * @param node    the Node to serialize
+     * @param os      the OutputStream to write to
+     * @param options the serialization options
+     * @since 6.0.0
+     */
+    public static void serialize(Node node, OutputStream os, SerializeOptions 
options) {
+        serialize(asStreamSource(asString(node)), os, options);
+    }
+
+    /**
+     * Return a pretty String version of the GPathResult using the specified 
options.
+     *
+     * @param node    a GPathResult to serialize to a String
+     * @param options the serialization options
+     * @return the pretty String representation of the GPathResult
+     * @since 6.0.0
+     */
+    public static String serialize(GPathResult node, SerializeOptions options) 
{
+        Writer sw = new StringBuilderWriter();
+        serialize(asStreamSource(asString(node)), sw, options);
+        return sw.toString();
+    }
+
+    /**
+     * Write a pretty version of the GPathResult to the OutputStream using the 
specified options.
+     *
+     * @param node    a GPathResult to serialize
+     * @param os      the OutputStream to write to
+     * @param options the serialization options
+     * @since 6.0.0
+     */
+    public static void serialize(GPathResult node, OutputStream os, 
SerializeOptions options) {
+        serialize(asStreamSource(asString(node)), os, options);
+    }
+
+    /**
+     * Return a pretty String version of the XML content produced by the 
Writable using the specified options.
+     *
+     * @param writable the Writable to serialize
+     * @param options  the serialization options
+     * @return the pretty String representation of the content from the 
Writable
+     * @since 6.0.0
+     */
+    public static String serialize(Writable writable, SerializeOptions 
options) {
+        Writer sw = new StringBuilderWriter();
+        serialize(asStreamSource(asString(writable)), sw, options);
+        return sw.toString();
+    }
+
+    /**
+     * Write a pretty version of the XML content produced by the Writable to 
the OutputStream using the specified options.
+     *
+     * @param writable the Writable to serialize
+     * @param os       the OutputStream to write to
+     * @param options  the serialization options
+     * @since 6.0.0
+     */
+    public static void serialize(Writable writable, OutputStream os, 
SerializeOptions options) {
+        serialize(asStreamSource(asString(writable)), os, options);
+    }
+
+    /**
+     * Return a pretty version of the XML content contained in the given 
String using the specified options.
+     *
+     * @param xmlString the String to serialize
+     * @param options   the serialization options
+     * @return the pretty String representation of the original content
+     * @since 6.0.0
+     */
+    public static String serialize(String xmlString, SerializeOptions options) 
{
+        Writer sw = new StringBuilderWriter();
+        serialize(asStreamSource(xmlString), sw, options);
+        return sw.toString();
+    }
+
+    /**
+     * Write a pretty version of the given XML string to the OutputStream 
using the specified options.
+     *
+     * @param xmlString the String to serialize
+     * @param os        the OutputStream to write to
+     * @param options   the serialization options
+     * @since 6.0.0
+     */
+    public static void serialize(String xmlString, OutputStream os, 
SerializeOptions options) {
+        serialize(asStreamSource(xmlString), os, options);
+    }
+
     /**
      * Factory method to create a SAXParser configured to validate according 
to a particular schema language and
      * optionally providing the schema sources to validate with.
@@ -526,22 +658,39 @@ public class XmlUtil {
     }
 
     private static void serialize(Source source, OutputStream os, boolean 
allowDocTypeDeclaration) {
-        serialize(source, new StreamResult(new OutputStreamWriter(os, 
StandardCharsets.UTF_8)), allowDocTypeDeclaration);
+        serialize(source, os, SerializeOptions.DEFAULT);
+    }
+
+    private static void serialize(Source source, OutputStream os, 
SerializeOptions options) {
+        serialize(source, new StreamResult(new OutputStreamWriter(os, 
options.getCharset())), options);
     }
 
     private static void serialize(Source source, Writer w, boolean 
allowDocTypeDeclaration) {
-        serialize(source, new StreamResult(w), allowDocTypeDeclaration);
+        SerializeOptions options = new SerializeOptions();
+        options.setAllowDocTypeDeclaration(allowDocTypeDeclaration);
+        serialize(source, new StreamResult(w), options);
+    }
+
+    private static void serialize(Source source, Writer w, SerializeOptions 
options) {
+        serialize(source, new StreamResult(w), options);
     }
 
     private static void serialize(Source source, StreamResult target, boolean 
allowDocTypeDeclaration) {
+        SerializeOptions options = new SerializeOptions();
+        options.setAllowDocTypeDeclaration(allowDocTypeDeclaration);
+        serialize(source, target, options);
+    }
+
+    private static void serialize(Source source, StreamResult target, 
SerializeOptions options) {
         TransformerFactory factory = TransformerFactory.newInstance();
-        setFeatureQuietly(factory, 
"http://apache.org/xml/features/disallow-doctype-decl";, 
!allowDocTypeDeclaration);
-        setIndent(factory, 2);
+        setFeatureQuietly(factory, 
"http://apache.org/xml/features/disallow-doctype-decl";, 
!options.isAllowDocTypeDeclaration());
+        setIndent(factory, options.getIndent());
         try {
             Transformer transformer = factory.newTransformer();
             transformer.setOutputProperty(OutputKeys.INDENT, "yes");
             transformer.setOutputProperty(OutputKeys.METHOD, "xml");
             transformer.setOutputProperty(OutputKeys.MEDIA_TYPE, "text/xml");
+            transformer.setOutputProperty(OutputKeys.ENCODING, 
options.getEncoding());
             transformer.transform(source, target);
         }
         catch (TransformerException e) {
diff --git a/subprojects/groovy-xml/src/spec/doc/xml-userguide.adoc 
b/subprojects/groovy-xml/src/spec/doc/xml-userguide.adoc
index ace9bc78ee..23b596e63a 100644
--- a/subprojects/groovy-xml/src/spec/doc/xml-userguide.adoc
+++ b/subprojects/groovy-xml/src/spec/doc/xml-userguide.adoc
@@ -641,3 +641,12 @@ methods to serialize the xml fragment from several type of 
sources
 include::../test/UserGuideXmlUtilTest.groovy[tags=testGettingANode,indent=0]
 ----
 
+Serialization can be customized using `SerializeOptions` to control
+encoding, indentation, and DOCTYPE handling:
+
+[source,groovy]
+.Customizing serialization
+----
+include::../test/UserGuideXmlUtilTest.groovy[tags=testSerializeOptions,indent=0]
+----
+
diff --git a/subprojects/groovy-xml/src/spec/test/UserGuideXmlUtilTest.groovy 
b/subprojects/groovy-xml/src/spec/test/UserGuideXmlUtilTest.groovy
index 77aff2d41a..06171eddf2 100644
--- a/subprojects/groovy-xml/src/spec/test/UserGuideXmlUtilTest.groovy
+++ b/subprojects/groovy-xml/src/spec/test/UserGuideXmlUtilTest.groovy
@@ -51,4 +51,23 @@ class UserGuideXmlUtilTest extends GroovyTestCase {
         // end::testGettingANode[]
     }
 
+    void testSerializeOptions() {
+        // tag::testSerializeOptions[]
+        def response = new XmlParser().parseText(xml)
+
+        // Custom encoding
+        def latin1 = XmlUtil.serialize(response, new 
SerializeOptions(encoding: 'ISO-8859-1'))
+        assert latin1.contains('encoding="ISO-8859-1"')
+
+        // Custom indent (4 spaces instead of default 2)
+        def wideIndent = XmlUtil.serialize(response, new 
SerializeOptions(indent: 4))
+        assert wideIndent.contains('    <value>')
+
+        // Multiple options
+        def custom = XmlUtil.serialize(response, new 
SerializeOptions(encoding: 'ISO-8859-1', indent: 4))
+        assert custom.contains('encoding="ISO-8859-1"')
+        assert custom.contains('    <value>')
+        // end::testSerializeOptions[]
+    }
+
 }

Reply via email to