Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 26 additions & 16 deletions src/main/java/com/fasterxml/jackson/databind/ext/DOMSerializer.java
Original file line number Diff line number Diff line change
@@ -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<Node>
{
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ public class DOMTypeReadWriteTest extends com.fasterxml.jackson.databind.BaseMap
"<root attr='3'><leaf>Rock &amp; Roll!</leaf><?proc instr?></root>";
final static String SIMPLE_XML_NS =
"<root ns:attr='abc' xmlns:ns='http://foo' />";
final static String SIMPLE_XML_DEFAULT_NS =
"<root xmlns='http://foo'/>";

private final ObjectMapper MAPPER = new ObjectMapper();

Expand All @@ -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) {
Expand Down