0

What I want to do

I want to export several different Java objects to XML. In order to minimize code duplication, I took the following approach:

I made an abstract class implementing the creation of a standard empty DOM document and the transformer factory part.

Then I added an abstract method for filling the DOM document with the specific object data. I then made a CustomerExporter class which extended the abstract class and implemented the abstract method for that specific object.

I got that to work.

My question

How do write the abstract method so that it can cope with the different Java objects?

The problem

The objects are of different types so the attributes are not always the same. So an Interface wouldn't work (or would it?).

The code

Customer class

package org.flexdataexoporter.dao;

public class Customer{

    private int customerID;
    private String firstname;
    private String lastname;
    private int telnumber;

    public Customer(int customerID, String firstname, String lastname, int telnumber){

        this.customerID = customerID;
        this.firstname = firstname;
        this.lastname = lastname;
        this.telnumber = telnumber;
    }

    public int getCustomerID(){
        return customerID;
    }

    public String getFirstName(){
        return firstname;
    }

    public String getLastName(){
        return lastname;
    }

    public int getTelNumber(){
        return telnumber;
    }

    public void setCustomerID(int customerID) {
        this.customerID = customerID;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    public void setTelnumber(int telnumber) {
        this.telnumber = telnumber;
    }
}

Customers class

package org.flexdataexoporter.dao;

import java.util.ArrayList;

public class Customers extends ArrayList<Customer>  {

    private static final long serialVersionUID = 1L;

    public Customers(){ };

}

Abstract exporter class

package org.flexdataexporter.export;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
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.flexdataexoporter.dao.Customers;
import org.w3c.dom.Document;

public abstract class XMLExporter {

    public void generateXML(Customers customers) throws ParserConfigurationException, TransformerException{
        Document doc = createDomDoc();
        fillXML(doc, customers);
    }

    protected Document createDomDoc() throws ParserConfigurationException{
        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
        Document doc = docBuilder.newDocument();
        return doc;
    }

    public abstract void fillXML(Document doc, Customers customers) throws TransformerException;


    protected void writeDoc(Document doc) throws TransformerException{

        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        DOMSource source = new DOMSource(doc);
        StreamResult result = new StreamResult(System.out);
        transformer.transform(source, result);
    }

}

Specific export class

package org.flexdataexporter.export;

import javax.xml.transform.TransformerException;

import org.flexdataexoporter.dao.Customer;
import org.flexdataexoporter.dao.Customers;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class CustomerExporter extends XMLExporter {

    public CustomerExporter(){ }

    @Override
    public void fillXML(Document doc, Customers customers) throws TransformerException {
        Element rootElement = doc.createElement("customers");
        doc.appendChild(rootElement);

        for(Customer c  : customers){
            Element customer = doc.createElement("customer");
            rootElement.appendChild(customer);
            customer.setAttribute("id", Integer.toString(c.getCustomerID()));

            Element name = doc.createElement("firstname");
            name.appendChild(doc.createTextNode(c.getFirstName()));
            customer.appendChild(name);

            Element lastname = doc.createElement("lastname");
            lastname.appendChild(doc.createTextNode(c.getLastName()));
            customer.appendChild(lastname);

            Element phone = doc.createElement("phone");
            phone.appendChild(doc.createTextNode(Integer.toString(c.getTelNumber())));
            customer.appendChild(phone);
            super.writeDoc(doc);
        }
    }
}

I hope someone can help me with a solution.

4

2 回答 2

0

I suggest a different approach:

  1. Specify the XSD
  2. Use xjc (e.g. via a Maven Plugin or an Ant task) to generate JAXB classes
  3. Use JAXB to marshal the XML documents
于 2013-02-07T15:51:19.777 回答
0

I would suggest looking for a library to do this for you. But assuming you need to write it your self, I think what you want is generics

public abstract class XMLExporter<T> {
    public void generateXML(T object) throws ParserConfigurationException, TransformerException{
        Document doc = createDomDoc();
        fillXML(doc, object);
    }

    public abstract void fillXML(Document doc, T object) throws TransformerException;
}

And then your implementing class

public class CustomerExporter extends XMLExporter<Customers> {

}

I haven't used Java in a while so my syntax maybe wrong or incomplete but hopefully this gets going where you wanted to go.

于 2013-02-07T16:02:14.850 回答