Ругается на условия:
1. Если во входящем xml отсутствует искомый тег, то добавлять комментарии не нужно.
2. Метод toXmlWithComment должен возвращать xml в виде строки преобразованной в соответствии с условием задачи.
По идее, всё работает правильно.
package com.javarush.task.task33.task3309;
/*
Комментарий внутри xml
Реализовать метод toXmlWithComment, который должен возвращать строку - xml представление объекта obj.
В строке перед каждым тегом tagName должен быть вставлен комментарий comment.
Сериализация obj в xml может содержать CDATA с искомым тегом. Перед ним вставлять комментарий не нужно.
Пример вызова:
toXmlWithComment(firstSecondObject, "second", "it's a comment")
Пример результата:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<first>
<!--it's a comment-->
<second>some string</second>
<!--it's a comment-->
<second>some string</second>
<!--it's a comment-->
<second><![CDATA[need CDATA because of < and >]]></second>
<!--it's a comment-->
<second/>
</first>
Требования:
1. Метод toXmlWithComment должен быть статическим.
2. Метод toXmlWithComment должен быть публичным.
3. Если во входящем xml отсутствует искомый тег, то добавлять комментарии не нужно.
4. Количество комментариев вставленных в xml должно быть равно количеству тегов tagName.
5. Метод toXmlWithComment должен возвращать xml в виде строки преобразованной в соответствии с условием задачи.
*/
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
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 java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Solution {
public static String toXmlWithComment(Object obj, String tagName, String comment) throws TransformerException, IOException, SAXException, JAXBException, ParserConfigurationException {
//сериализуем объект в XML
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);
String xml = writer.toString();
//сериализация
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = docBuilderFactory.newDocumentBuilder();
Document doc = builder.parse(new InputSource(new StringReader(xml)));//представление XML в виде множества узлов
//альтернативный вариант: сразу сериализовать объект в doc
//Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
//marshaller.marshal(obj, doc);
NodeList nodes = doc.getElementsByTagName("*"); //это коллекция, которая содержит все ЭЛЕМЕНТЫ представления XML
//метод Document.getElementsByTagName() позволяет проходить XML не построчно, а по ЭЛЕМЕНТАМ
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if (node.getNodeName().equals(tagName)) {
Comment com = doc.createComment(comment); //+ System.getProperty("line.separator")
node.getParentNode().insertBefore(com, node);
}
replaceTextWithCDATA(node, doc);
}
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
writer = new StringWriter();
transformer.transform(new DOMSource(doc), new StreamResult(writer));
return writer.toString();
}
private static void replaceTextWithCDATA(Node node, Document doc) {
//".*[<>&'\"].*"
//"[<>&'\"]"
if ((node.getNodeType() == 3) && (Pattern.compile(".*[<>&'\"].*").matcher(node.getTextContent()).find())) {
Node cnode = doc.createCDATASection(node.getNodeValue());
node.getParentNode().replaceChild(cnode, node);
}
NodeList list = node.getChildNodes();
for (int i = 0; i < list.getLength(); i++) {
replaceTextWithCDATA(list.item(i), doc);
}
}
public static void main(String[] args) throws Exception {
SomeObject someObject = new SomeObject();
someObject.name = "daedra";
System.out.println(toXmlWithComment(someObject, "name", "it's a comment"));
}
}