Reputation: 1371
I have a class Container
:
public class Container implements Exportable {
private Node root;
private String name;
public void exportXML(Element target, Document document) {
target.setAttribute("name", name);
root.exportXML(target, document);
}
}
Which implements the interface Exportable
which defines two abstracts methods, one for importing, one for exporting. The objective is to export my classes to XML format.
As you can see, the class Container take a Node
which is the root of a Node
tree. This is the Node
class:
public class Node implements Exportable {
private ArrayList<Node> children = new ArrayList<>();
private String name;
public void exportXML(Element target, Document document) {
Element node = document.createElement("node");
target.appendChild(node);
node.setAttribute("name", name);
if (children.size() > 0) {
Element nodes = document.createElement("nodes");
node.appendChild(nodes);
for (Node child : children) {
child.exportXML(nodes, document);
}
}
}
}
I use a SaveManager
class for exporting the Container
object:
public class SaveManager {
public static void exportContainer(Container container, String pathname) {
try {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.newDocument();
Element projectNode = document.createElement("container");
document.appendChild(projectNode);
container.exportXML(projectNode, document);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
DOMSource source = new DOMSource(document);
StreamResult result = new StreamResult(new File(pathname));
transformer.transform(source, result);
} catch (ParserConfigurationException | TransformerException e) {
e.printStackTrace();
}
}
}
I need to be able to export the Node
alone, without a Container
. For example, if I call nodeA.exportXML()
, the nodeA
will be the root of the tree.
The problem is that I will have two methods in my SaveManager
doing exactly the same thing (ie call exportXML() on an object and save the result into an XML file) and I will have to create to methods exportXML()
in my Node
class, one where the Node
is a child and one where it's the root. I did exactly the same thing in C++ using pugixml
and it was much easier because the document itself was a node, so I just had to give it to the exportXML() method if I wanted anything to be a root otherwise.
Is it possible to have a generic exportXML() method with the Java XML implementation?
Upvotes: 4
Views: 281
Reputation: 10931
Sticking with the DOM approach, it looks like the simplest way to do this would be to let the Container
create its own element. Both Node
and Container
would then be able to add themselves to whatever parent Document
or Element
was passed in.
(We're about to have to deal with two Node
classes here unfortunately, but ...) The trick to doing this is to use a org.w3c.dom.Node
as the first parameter in exportXML()
- this is the superinterface for both Document
and Element
, so can handle the root or child being passed in:
public class Container implements Exportable {
private Node root;
private String name;
@Override
public void exportXML(org.w3c.dom.Node target, Document document) {
Element node = document.createElement("container");
document.appendChild(node);
node.setAttribute("name", name);
root.exportXML(target, document);
}
}
SaveManager
can then just pass the Document
in at the start:
Document document = documentBuilder.newDocument();
//Element projectNode = document.createElement("container");
//document.appendChild(projectNode);
container.exportXML(document, document);
And your Node
class should work unchanged, just with a org.w3c.dom.Node target
passed in now.
But agree with the earlier comments about XStream or JAX-B. For example most of the XML being generated so far would be well with the capabilities of a few @XmlElement
and @XmlAttribute
annotations.
Upvotes: 2