I need to generate an XML file from just having a map, which contains the parent element and his children.
Map looks like this:
Map<String, List<Element>> elementMap = new LinkedHashMap<String, List<Element>>();
root: el1 el2 el3 el4 // root is the parent and el1... are his children.
el1: el5 el6
el2: el7 el8
Expected XML Model:
<root>
<el1>
<el5></el5>
<el6></el6>
</el1>
<el2>
<el7></el7>
<el8></el87>
</el2>
<el3></el3>
<el4></el4>
</root>
Can you give me some tips, algorithms how I could generate that XML?
I thought about recursion, but I don't know where to start.
Any suggestions?
Your thoughts were good. You have to use iterating every one of your map keys and generate the list of elements based on values from this key. The result should be append to the general document.
You haven't posted your Element
class. I will show some example based on Map<String, List<String>> elementMap
.
Here is code snippet:
import com.epam.lab.model.exceptions.CreateDocumentConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class XmlBuilder {
private DocumentBuilder builder;
private Document doc;
/**
* Constructs an item list builder.
*
* @throws CreateDocumentConfigurationException
*/
public XmlBuilder() throws CreateDocumentConfigurationException {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
builder = factory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
throw new CreateDocumentConfigurationException("exception create new document", e);
}
}
/**
* Builds a DOM document for an array list of items.
*
* @param elementMap map of items.
* @return a DOM document describing the items.
*/
public Document build(Map<String, List<String>> elementMap) {
doc = builder.newDocument();
doc.appendChild(createItems(elementMap));
return doc;
}
/**
* Builds a DOM element for an array list of items.
*
* @param elementMap the map of items
* @return a DOM element describing the items
*/
private Element createItems(Map<String, List<String>> elementMap) {
Element e = null;
for (Map.Entry<String, List<String>> anItem : elementMap.entrySet()) {
e = doc.createElement(anItem.getKey());
for (Node node : createItemsList(anItem.getValue())) {
e.appendChild(node);
}
}
return e;
}
private List<Node> createItemsList(List<String> items) {
List<Node> result = new ArrayList<>();
for (String item : items) {
Element item1 = createItem(item);
result.add(item1);
}
return result;
}
/**
* Builds a DOM element for an item.
*
* @param anItem the item
* @return a DOM element describing the item
*/
private Element createItem(String anItem) {
// if you need some text element to your element - just append it here.
return doc.createElement(anItem);
}
/**
* Builds the text content for document
*
* @param name element
* @param text content
* @return text element
*/
private Element createTextElement(String name, String text) {
Text t = doc.createTextNode(text);
Element e = doc.createElement(name);
e.appendChild(t);
return e;
}
private String generateXmlContent(Map<String, List<String>> elementMap) {
String content;
Document doc = build(elementMap);
DOMImplementation impl = doc.getImplementation();
DOMImplementationLS implLS = (DOMImplementationLS) impl.getFeature("LS", "3.0");
LSSerializer ser = implLS.createLSSerializer();
ser.getDomConfig().setParameter("format-pretty-print", true);
content = ser.writeToString(doc);
return content;
}
public void writeToXmlFile(String xmlContent) {
File theDir = new File("./output");
if (!theDir.exists())
theDir.mkdir();
String fileName = "./output/" + this.getClass().getSimpleName() + "_"
+ Calendar.getInstance().getTimeInMillis() + ".xml";
try (OutputStream stream = new FileOutputStream(new File(fileName))) {
try (OutputStreamWriter out = new OutputStreamWriter(stream, StandardCharsets.UTF_16)) {
out.write(xmlContent);
out.write("\n");
}
} catch (IOException ex) {
System.err.println("Cannot write to file!" + ex.getMessage());
}
}
public static void main(String[] args) throws CreateDocumentConfigurationException {
XmlBuilder xmlBuilder = new XmlBuilder();
Map<String, List<String>> map = MapFactory.mapOf(MapFactory.entry("root", Arrays.asList("element1", "element2", "element3")));
String xmlContent = xmlBuilder.generateXmlContent(map);
xmlBuilder.writeToXmlFile(xmlContent);
}
}
After generating XML document you have to write it to file.
But you have to prepare XML content before writing, something like:
private String generateXmlContent(Map<String, List<String>> elementMap) {
String content;
Document doc = build(elementMap);
DOMImplementation impl = doc.getImplementation();
DOMImplementationLS implLS = (DOMImplementationLS) impl.getFeature("LS", "3.0");
LSSerializer ser = implLS.createLSSerializer();
ser.getDomConfig().setParameter("format-pretty-print", true);
content = ser.writeToString(doc);
return content;
}
And finally writing to file can look like:
public void writeToXmlFile(String xmlContent) {
File theDir = new File("./output");
if (!theDir.exists())
theDir.mkdir();
String fileName = "./output/" + this.getClass().getSimpleName() + "_"
+ Calendar.getInstance().getTimeInMillis() + ".xml";
try (OutputStream stream = new FileOutputStream(new File(fileName))) {
try (OutputStreamWriter out = new OutputStreamWriter(stream, StandardCharsets.UTF_16)) {
out.write(xmlContent);
out.write("\n");
}
} catch (IOException ex) {
System.err.println("Cannot write to file!", ex);
}
}
Utility factory for creating Map, based on literals:
public class MapFactory {
// Creates a map from a list of entries
@SafeVarargs
public static <K, V> Map<K, V> mapOf(Map.Entry<K, V>... entries) {
LinkedHashMap<K, V> map = new LinkedHashMap<>();
for (Map.Entry<K, V> entry : entries) {
map.put(entry.getKey(), entry.getValue());
}
return map;
}
// Creates a map entry
public static <K, V> Map.Entry<K, V> entry(K key, V value) {
return new AbstractMap.SimpleEntry<>(key, value);
}
}
After executing main()
I have got following XML file XmlBuilder_1456910256665.xml
:
<?xml version="1.0" encoding="UTF-16"?>
<root>
<element1/>
<element2/>
<element3/>
</root>
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments