3

Is it possible to deserialize a "org.w3c.dom.Document" type into a Java class? We have this class (Employee), and we have an existing method in our application that calls a web service and returns a "Document" type of the Employee class. Can we serialize the Document to Employee class?

Can you please show some example? Most of the sample I found from the internet reads an XML file in a directory then deserialize it to the class. But in our scenario, the object is a Document type.

What I'm trying to achieve is something like as below (pseudocode):

String employeeID = "12344444";
org.w3c.dom.Document xmlEmployee = helperClass.callWebServiceEmployee(employeeID);

EmployeeClass employee = new EmployeeClass();

employee = (EmployeeClass)xmlEmployee. 
Chii
  • 14,540
  • 3
  • 37
  • 44
yonan2236
  • 13,371
  • 33
  • 95
  • 141
  • What's the definition of `Document type` ? – Nir Alfasi Jul 26 '14 at 03:49
  • Document type, from package - org.w3c.dom.Document – yonan2236 Jul 26 '14 at 03:50
  • You mean serialize from `package`? – Rajendra arora Jul 26 '14 at 03:52
  • no, to serialize the Document type to Employee class. The type of the Document I'm referring to is org.w3c.dom.Document – yonan2236 Jul 26 '14 at 03:53
  • 1
    Though you want to use Document, [*the interface*](http://docs.oracle.com/javase/7/docs/api/org/w3c/dom/Document.html) doesn't support such actions as deserialization. Serialization/deserialization is done with XML/JSON packages (like JAXB, Jackson, xerces, DocumentBuilder, XStream...) – Nir Alfasi Jul 26 '14 at 04:11
  • @afasin, so do you have any suggestion? – yonan2236 Jul 26 '14 at 04:14
  • Is the WebService interface and the returned object under your control development-wise? If yes then you could redefine the service interface to use the Employee bean directly based on JAXB. DOM interfaces would NOT be needed at all. I can provide a detailed answer if you say you can modify the service. – Michael Jul 26 '14 at 10:32

3 Answers3

1

Part of the reason people aren't leaping to help you is that you've got the terminology wrong. Going from DOM objects to domain-specific Java objects is NOT serialization. It is translation one object form to another object form. Serialization is when you go from an object form (e.g. DOM) to a serial form; e.g. XML.

(And it isn't deserialisation either :-) )


Anyway ...

Given where you currently are, I think this approach should work:

  1. Serialise the DOM objects to XML.

  2. Deserialise the XML to POJOs using XStream or JAXB or some other "XML binding" technology.

It is not the most efficient approach (in terms of runtime costs), but I suspect that the efficient approach would entail implementing a mapping / binding technology that doesn't currently exist and (frankly) wouldn't be much use to other people.

But then I don't know why you are starting from DOM objects in the first place. It doen't make a lot of sense to me:

  • If you got the DOM objects by parsing XML, then it would better to start with the XML and go directly to step 2.

  • If you constructed the DOM some other way ..... why?

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Do you have any reference link for 1.Serialise the DOM objects to XML. ? – yonan2236 Jul 26 '14 at 04:36
  • does "serializing" means writing the object to a physical file? – yonan2236 Jul 26 '14 at 04:42
  • @yonan2236 - Not necessarily. I can serialize to a socket. I can serialize to an in-memory buffer that never gets written anywhere. Serialization just means conversion to a serial form; typically a sequence of bytes or characters. In this case, you probably want to serialize to a `ByteArrayOutputStream` or something like that. – Stephen C Jul 26 '14 at 04:48
  • many thanks! I have found this post but it uses an external library: http://stackoverflow.com/questions/13731322/xml-parsing-and-deserialization, is there any standard java library I can use similar to this? – yonan2236 Jul 26 '14 at 04:59
  • JAXB is provided by Oracle, and has been part of Java SE since Java 6. – Stephen C Jul 26 '14 at 08:00
0

You can't directly type cast Document type Object to your own class. What you can do is having a Constructor in Your class that takes Document as parameter and then populate your class attributes with the values from Document Object

String employeeID = "12344444";
org.w3c.dom.Document xmlEmployee = helperClass.callWebServiceEmployee(employeeID);

EmployeeClass employee = new EmployeeClass(xmlEmployee);

where this constructor might have implementation like:

public EmployeeClass(Document xmlEmployee) {
      // this is just an example assuming your xml had a Name Node  
      this.employeeName = xmlEmployee.getElementByTagName("Name")[0].getNodeValue();
}

Similarly you can populate other attributes of your EmployeeClass

EDIT

If you are looking for some other way of doing things you can make use of JSON APIs. In that case your web service might return a JSON Object String and you can get your object from it. here is a Stack overflow post that might help you to check different options for JSON.

Community
  • 1
  • 1
Sanjeev
  • 9,876
  • 2
  • 22
  • 33
  • Thanks, that's exactly what we're currently doing, but the Employee class has a lot of member fields and we would like to find a better solution instead of reading each node of the xml one by one. – yonan2236 Jul 26 '14 at 04:22
0

The following static methods will achieve the required conversion:

import java.io.StringWriter;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Node;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;

public class Utils {
    public static String convertNodeToString(Node node) {
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer;
        try {
            transformer = tf.newTransformer();
            // below code to remove XML declaration
            // transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
            StringWriter writer = new StringWriter();
            transformer.transform(new DOMSource(node), new StreamResult(writer));
            String output = writer.getBuffer().toString();
            return output;
        } catch (TransformerException e) {
            e.printStackTrace();
        }

        return null;
    }

    public static <T> T convertNodeToObject(Node node, Class<T> type) throws JsonMappingException, JsonProcessingException {
        return convertNodeToObject(node, new XmlMapper(), type);
    }

    public static <T> T convertNodeToObject(Node node, XmlMapper xmlMapper, Class<T> type) throws JsonMappingException, JsonProcessingException {
        T obj=null;
        String xmlStr = convertNodeToString(node);
        obj = xmlMapper.readValue(xmlStr, type);
        return obj;
    }
}

Following is the dependency I used for Jackson:

        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
            <version>2.12.7</version>
        </dependency>
tarekahf
  • 738
  • 1
  • 16
  • 42