diff --git a/ext/java/nokogiri/XsltStylesheet.java b/ext/java/nokogiri/XsltStylesheet.java
index d35ee8ff91c..d3437184700 100644
--- a/ext/java/nokogiri/XsltStylesheet.java
+++ b/ext/java/nokogiri/XsltStylesheet.java
@@ -40,6 +40,7 @@
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.w3c.dom.Document;
+import org.w3c.dom.Node;
import nokogiri.internals.NokogiriXsltErrorListener;
@@ -185,7 +186,23 @@ public class XsltStylesheet extends RubyObject
java.util.Properties props = this.sheet.getOutputProperties();
if (props.getProperty(OutputKeys.METHOD) == null) {
- props.setProperty(OutputKeys.METHOD, org.apache.xml.serializer.Method.UNKNOWN);
+ Node rootNode = xmlDoc.getNode().getFirstChild();
+
+ if (rootNode != null && rootNode.getNodeType() == Node.ELEMENT_NODE) {
+ String firstChildLocalName = rootNode.getLocalName();
+
+ if (firstChildLocalName.equalsIgnoreCase("html") && rootNode.getNamespaceURI() == null) {
+ Node textNode = rootNode.getPreviousSibling();
+
+ if (textNode == null || (textNode.getNodeType() == Node.TEXT_NODE && textNode.getTextContent().trim().isEmpty())) {
+ props.setProperty(OutputKeys.METHOD, "html");
+ }
+ }
+ }
+
+ if (props.getProperty(OutputKeys.METHOD) == null) {
+ props.setProperty(OutputKeys.METHOD, "xml");
+ }
}
Serializer serializer = SerializerFactory.getSerializer(props);
@@ -195,6 +212,7 @@ public class XsltStylesheet extends RubyObject
return context.getRuntime().newString(writer.toString());
}
+
@JRubyMethod(rest = true, required = 1, optional = 2)
public IRubyObject
transform(ThreadContext context, IRubyObject[] args)
diff --git a/test/xslt/test_xml_header.rb b/test/xslt/test_xml_header.rb
new file mode 100644
index 00000000000..2681f7ef77f
--- /dev/null
+++ b/test/xslt/test_xml_header.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require "minitest/autorun"
+require "nokogiri"
+
+class OutputTest < Minitest::Test
+ def test_output
+ input_xml = <<~XML
+
+
+
+
+