Skip to content

Commit 951528e

Browse files
committed
Use XML Transformer for xml serialization to fix missing default namespace when serializing xml
1 parent 71385d1 commit 951528e

File tree

2 files changed

+39
-8
lines changed

2 files changed

+39
-8
lines changed

src/main/java/com/fasterxml/jackson/databind/ext/DOMSerializer.java

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.fasterxml.jackson.databind.ext;
22

33
import java.io.IOException;
4+
import java.io.StringWriter;
45

56
import org.w3c.dom.Node;
67
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
@@ -15,29 +16,41 @@
1516
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
1617
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
1718

19+
import javax.xml.transform.*;
20+
import javax.xml.transform.dom.DOMSource;
21+
import javax.xml.transform.stream.StreamResult;
1822
@SuppressWarnings("serial")
1923
public class DOMSerializer extends StdSerializer<Node>
2024
{
21-
protected final DOMImplementationLS _domImpl;
25+
26+
private final TransformerFactory transformerFactory;
2227

2328
public DOMSerializer() {
2429
super(Node.class);
25-
DOMImplementationRegistry registry;
2630
try {
27-
registry = DOMImplementationRegistry.newInstance();
31+
transformerFactory = TransformerFactory.newInstance();
2832
} catch (Exception e) {
29-
throw new IllegalStateException("Could not instantiate DOMImplementationRegistry: "+e.getMessage(), e);
33+
throw new IllegalStateException("Could not instantiate TransformerFactory: "+e.getMessage(), e);
3034
}
31-
_domImpl = (DOMImplementationLS)registry.getDOMImplementation("LS");
3235
}
3336

3437
@Override
3538
public void serialize(Node value, JsonGenerator jgen, SerializerProvider provider)
3639
throws IOException
3740
{
38-
if (_domImpl == null) throw new IllegalStateException("Could not find DOM LS");
39-
LSSerializer writer = _domImpl.createLSSerializer();
40-
jgen.writeString(writer.writeToString(value));
41+
try {
42+
Transformer transformer = transformerFactory.newTransformer();
43+
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
44+
transformer.setOutputProperty(OutputKeys.INDENT, "no");
45+
StreamResult result = new StreamResult(new StringWriter());
46+
DOMSource source = new DOMSource(value);
47+
transformer.transform(source, result);
48+
jgen.writeString(result.getWriter().toString());
49+
} catch (TransformerConfigurationException e) {
50+
throw new IllegalStateException("Could not create XML Transformer: "+e.getMessage(), e);
51+
} catch (TransformerException e) {
52+
provider.reportMappingProblem(e,"XML Transformation failed: %s", e.getMessage());
53+
}
4154
}
4255

4356
@Override

src/test/java/com/fasterxml/jackson/databind/ext/DOMTypeReadWriteTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ public class DOMTypeReadWriteTest extends com.fasterxml.jackson.databind.BaseMap
1414
"<root attr='3'><leaf>Rock &amp; Roll!</leaf><?proc instr?></root>";
1515
final static String SIMPLE_XML_NS =
1616
"<root ns:attr='abc' xmlns:ns='http://foo' />";
17+
final static String SIMPLE_XML_DEFAULT_NS =
18+
"<root xmlns='http://foo'/>";
1719

1820
private final ObjectMapper MAPPER = new ObjectMapper();
1921

@@ -33,6 +35,22 @@ public void testSerializeSimpleNonNS() throws Exception
3335
assertEquals(SIMPLE_XML, normalizeOutput(output));
3436
}
3537

38+
public void testSerializeSimpleDefaultNS() throws Exception
39+
{
40+
// Let's just parse first, easiest
41+
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse
42+
(new InputSource(new StringReader(SIMPLE_XML_DEFAULT_NS)));
43+
assertNotNull(doc);
44+
// need to strip xml declaration, if any
45+
String outputRaw = MAPPER.writeValueAsString(doc);
46+
// And re-parse as String, since JSON has quotes...
47+
String output = MAPPER.readValue(outputRaw, String.class);
48+
/* ... and finally, normalize to (close to) canonical XML
49+
* output (single vs double quotes, xml declaration etc)
50+
*/
51+
assertEquals(SIMPLE_XML_DEFAULT_NS, normalizeOutput(output));
52+
}
53+
3654
public void testDeserializeNonNS() throws Exception
3755
{
3856
for (int i = 0; i < 2; ++i) {

0 commit comments

Comments
 (0)