diff --git a/src/main/java/com/fasterxml/jackson/databind/ext/DOMSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ext/DOMSerializer.java index 91ea5ccc68..868d944936 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ext/DOMSerializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/ext/DOMSerializer.java @@ -1,43 +1,53 @@ package com.fasterxml.jackson.databind.ext; -import java.io.IOException; - -import org.w3c.dom.Node; -import org.w3c.dom.bootstrap.DOMImplementationRegistry; -import org.w3c.dom.ls.DOMImplementationLS; -import org.w3c.dom.ls.LSSerializer; - -import com.fasterxml.jackson.core.*; +import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper; import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import org.w3c.dom.Node; +import javax.xml.XMLConstants; +import javax.xml.transform.*; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.IOException; +import java.io.StringWriter; @SuppressWarnings("serial") public class DOMSerializer extends StdSerializer { - protected final DOMImplementationLS _domImpl; + + private final TransformerFactory transformerFactory; public DOMSerializer() { super(Node.class); - DOMImplementationRegistry registry; try { - registry = DOMImplementationRegistry.newInstance(); + transformerFactory = TransformerFactory.newInstance(); + transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); } catch (Exception e) { - throw new IllegalStateException("Could not instantiate DOMImplementationRegistry: "+e.getMessage(), e); + throw new IllegalStateException("Could not instantiate TransformerFactory: "+e.getMessage(), e); } - _domImpl = (DOMImplementationLS)registry.getDOMImplementation("LS"); } @Override public void serialize(Node value, JsonGenerator jgen, SerializerProvider provider) throws IOException { - if (_domImpl == null) throw new IllegalStateException("Could not find DOM LS"); - LSSerializer writer = _domImpl.createLSSerializer(); - jgen.writeString(writer.writeToString(value)); + try { + Transformer transformer = transformerFactory.newTransformer(); + transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + transformer.setOutputProperty(OutputKeys.INDENT, "no"); + StreamResult result = new StreamResult(new StringWriter()); + DOMSource source = new DOMSource(value); + transformer.transform(source, result); + jgen.writeString(result.getWriter().toString()); + } catch (TransformerConfigurationException e) { + throw new IllegalStateException("Could not create XML Transformer: "+e.getMessage(), e); + } catch (TransformerException e) { + provider.reportMappingProblem(e,"XML Transformation failed: %s", e.getMessage()); + } } @Override diff --git a/src/test/java/com/fasterxml/jackson/databind/ext/DOMTypeReadWriteTest.java b/src/test/java/com/fasterxml/jackson/databind/ext/DOMTypeReadWriteTest.java index 21359aa474..c4fbc30dc8 100644 --- a/src/test/java/com/fasterxml/jackson/databind/ext/DOMTypeReadWriteTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/ext/DOMTypeReadWriteTest.java @@ -14,6 +14,8 @@ public class DOMTypeReadWriteTest extends com.fasterxml.jackson.databind.BaseMap "Rock & Roll!"; final static String SIMPLE_XML_NS = ""; + final static String SIMPLE_XML_DEFAULT_NS = + ""; private final ObjectMapper MAPPER = new ObjectMapper(); @@ -33,6 +35,22 @@ public void testSerializeSimpleNonNS() throws Exception assertEquals(SIMPLE_XML, normalizeOutput(output)); } + public void testSerializeSimpleDefaultNS() throws Exception + { + // Let's just parse first, easiest + Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse + (new InputSource(new StringReader(SIMPLE_XML_DEFAULT_NS))); + assertNotNull(doc); + // need to strip xml declaration, if any + String outputRaw = MAPPER.writeValueAsString(doc); + // And re-parse as String, since JSON has quotes... + String output = MAPPER.readValue(outputRaw, String.class); + /* ... and finally, normalize to (close to) canonical XML + * output (single vs double quotes, xml declaration etc) + */ + assertEquals(SIMPLE_XML_DEFAULT_NS, normalizeOutput(output)); + } + public void testDeserializeNonNS() throws Exception { for (int i = 0; i < 2; ++i) {