Мой код рекурсивно итерирует по всем тегам DOM'а и, если название тега совпадает с "second", добавляет коммент.
Две проблемы:
1. Коммент добавляется только к последнему тегу.
2. После коммента отсутствует перенос на следующую строку, как это показано в примере в условии.
package com.javarush.task.task33.task3309;
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayInputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
/*
Комментарий внутри xml
*/
public class Solution {
public static void main(String[] args) {
System.out.println(toXmlWithComment(new First(), "second", "it's a comment"));
}
public static String toXmlWithComment(Object obj, String tagName, String comment) {
try {
//marshalling object using JAXB
StringWriter writer = new StringWriter();
JAXBContext context = JAXBContext.newInstance(obj.getClass());
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(obj, writer);
//creating DOM and comment to insert
DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = documentBuilder.parse(new ByteArrayInputStream(writer.toString().getBytes()));
Comment commentForInsertion = document.createComment(comment);
//recursively iterating through DOM and inserting comment
iterateThrowNodesAndAddComment(document.getFirstChild(), tagName, commentForInsertion);
//unmarshalling DOM to XML
DOMSource domSource = new DOMSource(document);
Transformer transformer = TransformerFactory.newInstance().newTransformer();
StringWriter stringWriter = new StringWriter();
StreamResult streamResult = new StreamResult(stringWriter);
transformer.transform(domSource, streamResult);
return stringWriter.toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//recursive method for iteration through parsed DOM and adding the comment on condition
//(node is the root element)
public static void iterateThrowNodesAndAddComment (Node node, String tagName, Comment comment) {
NodeList listOfChildren = node.getChildNodes();
for (int i = 0; i < listOfChildren.getLength(); i++) {
if (listOfChildren.item(i).getNodeName().equals(tagName)) {
node.insertBefore(comment, listOfChildren.item(i));
}
if (listOfChildren.item(i).hasChildNodes()) { //recurse
iterateThrowNodesAndAddComment(listOfChildren.item(i), tagName, comment);
}
}
}
//object for marshalling to XML
@XmlType(name = "First")
@XmlRootElement
public static class First {
@XmlElement
public static List<String> second = new ArrayList<>();
public First() {
second.add("Text-1");
second.add("Text-2");
second.add("Text-3");
second.add("");
}
}
}