Adding linebreak in xml file before root node

domparser, java, line-breaks, xml

Solution

You basically want a text node containing a line break after the comment node.

Element docElem = doc.getDocumentElement();

doc.insertBefore(doc.createComment("DO NOT EDIT THIS FILE"), docElem);
doc.insertBefore(doc.createTextNode("\\n"), docElem);

EDIT: It seems that appending even whitespace-only text nodes is not allowed at the root node of an `org.w3c.dom.Document`. This is 100% formally correct, but also unhelpful.

The way comments are rendered in the output of the `Transformer` is determined by the serializer it uses (there are different serializers for HTML, XML and plain text outputs). In the built-in XML serializer the end of a comment is defined as `-->` - without a newline.

Since the internals of `javax.xml.transform.Transformer` are hard-wired, the serializers are not public API and the class is marked as `final`, overriding that behavior or setting a custom serializer is impossible.

In other words, you are out of luck adding your line break in a clean way.

You can, however, safely add it in a slightly unclean way:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();

FileInputStream inputXml = new FileInputStream(new File("input.xml"));
Document doc = db.parse(inputXml);

// add the comment node    
doc.insertBefore(doc.createComment("THIS IS A COMMENT"), doc.getDocumentElement());

StringWriter outputXmlStringWriter = new StringWriter();
Transformer transformer = transformerFactory.newTransformer();
// "xml" + "UTF-8" "include XML declaration" is the default anyway, but let's be explicit
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.transform(new DOMSource(doc), new StreamResult(outputXmlStringWriter));

// now insert our newline into the string & write an UTF-8 file
String outputXmlString = outputXmlStringWriter.toString()
    .replaceFirst("<!--", "\n<!--").replaceFirst("-->", "-->\n");

FileOutputStream outputXml = new FileOutputStream(new File("output.xml"));            
outputXml.write(outputXmlString.getBytes("UTF-8"));

Doing search-and-replace operations on XML strings is highly discouraged in general, but in this case there is little that can go wrong.

Problem

I am trying to add line break after my comments above the root node in XML document. I need something like this: ``` <?xml version="1.0" encoding="UTF-8" standalone="no"?> <!--DO NOT EDIT THIS FILE--> <projects> </projects> ``` But What I was able to get is this(Line break inside the root but I need line break after the comment): ``` <?xml version="1.0" encoding="UTF-8" standalone="no"?> <!--DO NOT EDIT THIS FILE--><projects> </projects> ``` I need to add the line break just after my comment. Is there a way to do this? My code: ``` import java.io.File; import java.io.FileInputStream; 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 org.w3c.dom.Comment; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Text; public class XMLNewLine { /** * @param args */ public static void main(String[] args) { System.out.println("Adding comment.."); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setValidating(false); DocumentBuilder db; try { Document doc; StreamResult result; result = new StreamResult(new File("abc.xml")); db = dbf.newDocumentBuilder(); doc = db.parse(new FileInputStream(new File("abc.xml"))); Element element = doc.getDocumentElement(); Text lineBreak = doc.createTextNode("\n"); element.appendChild(lineBreak); Comment comment = doc .createComment("DO NOT EDIT THIS FILE"); element.getParentNode().insertBefore(comment, element); doc.getDocumentElement().normalize(); TransformerFactory transformerFactory = TransformerFactory .newInstance(); Transformer transformer = transformerFactory.newTransformer(); DOMSource source = new DOMSource(doc); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.transform(source, result); } catch (Exception e) { // TODO Auto-generated catch block } } } ```

Original source