результирующий XML:
<?xml version="1.0" encoding="UTF-8"?>
<first>
<!--it’s a comment-->
<second>
some string
</second>
<!--it’s a comment-->
<second>
<![CDATA[need CDATA because of <second>]]>
</second>
<!--it’s a comment-->
<second/>
<third>
second2
</third>
<forth>
<!--it’s a comment-->
<second>
some string
</second>
<!--it’s a comment-->
<second>
<![CDATA[need CDATA because of <second>]]>
</second>
</forth>
<fifth>
<![CDATA[need CDATA because of "]]>
</fifth>
</first>
standalone="yes" не стал, хотя document.setXmlStandalone(true); использовал.package com.javarush.task.task33.task3309;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
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 java.io.*;
/*
Комментарий внутри xml
*/
public class Solution {
public static String toXmlWithComment(Object obj, String tagName, String comment) throws JAXBException, ParserConfigurationException, IOException, SAXException, TransformerException {
JAXBContext jaxbContext = JAXBContext.newInstance(obj.getClass());
Marshaller marshaller = jaxbContext.createMarshaller();
StringWriter stringWriter = new StringWriter();
marshaller.marshal(obj, stringWriter);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance().newInstance();
dbf.setCoalescing(true);
DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
Document document = documentBuilder.parse(new ByteArrayInputStream(stringWriter.toString().getBytes()));
document.setXmlStandalone(true);
StreamResult streamResult = new StreamResult(new ByteArrayOutputStream());
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
//Метод toXmlWithComment не должен изменять входящий xml в случае, если искомый тег отсутствует в нём.
if (document.getElementsByTagName(tagName).getLength() == 0){
DOMSource source = new DOMSource(document);
transformer.transform(source, streamResult);
return streamResult.getOutputStream().toString();
}
walkToDocument(document.getDocumentElement(), tagName, comment, document);
DOMSource source = new DOMSource(document);
transformer.transform(source, streamResult);
return streamResult.getOutputStream().toString();
}
public static void main(String[] args) throws JAXBException, IOException, SAXException, ParserConfigurationException, TransformerException {
String string = toXmlWithComment(new First(), "second2", "it’s a comment");
int i = 1;
}
public static void walkToDocument(Node node, String tagName, String comment, Document document){
if (node == null) return;
String nodeValue = node.getNodeValue();
Node parent = node.getParentNode();
if (nodeValue != null && node.getNodeType() == Node.TEXT_NODE && nodeValue.matches("(\\w|\\W)*([\"'<>&])(\\w|\\W)*")){
Node nextSibling = node.getNextSibling();
CDATASection cdataSection = document.createCDATASection(nodeValue);
parent.insertBefore(cdataSection, nextSibling);
parent.removeChild(node);
node = cdataSection;
} else if (node.getNodeName().equals(tagName)) {
Comment cmnt = document.createComment(comment);
node.getParentNode().insertBefore(cmnt, node);
}
walkToDocument(node.getFirstChild(), tagName, comment, document);
walkToDocument(node.getNextSibling(), tagName, comment, document);
}
@XmlRootElement(name = "first")
public static class First {
@XmlElement(name = "second")
public String item1 = "some string";
@XmlElement(name = "second")
public String item2 = "need CDATA because of <second>";
@XmlElement(name = "second")
public String item3 = "";
@XmlElement(name = "third")
public String item4 = "second2";
@XmlElement(name = "forth")
public Second[] third = new Second[]{new Second()};
@XmlElement(name = "fifth")
public String item5 = "need CDATA because of \"";
}
public static class Second {
@XmlElement(name = "second")
public String item1 = "some string";
@XmlElement(name = "second")
public String item2 = "need CDATA because of <second>";
}
}