Adding linebreak in xml file before root node

前端 未结 5 2738
庸人自扰
庸人自扰 2021-02-20 01:41

I am trying to add line break after my comments above the root node in XML document.

I need something like this:



        
相关标签:
5条回答
  • 2021-02-20 02:22

    Had the same issue. I solved it by putting the comment inside the root element. Not exactly the same, but I think acceptable.

    0 讨论(0)
  • 2021-02-20 02:26

    You can achieve this by not adding the comment node to your document, but instead partially transforming your document. First transform your own XML processing instruction and comment separately, and then the rest of document:

    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    DocumentBuilder db = dbf.newDocumentBuilder();
    Document doc = db.parse(new FileInputStream(new File("abc.xml")));
    
    Result output = new StreamResult(new File("abc.xml"));
    Source input = new DOMSource(doc);
    
    
    // xml processing instruction and comment node
    ProcessingInstruction xmlpi = doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"");
    Comment comment = doc.createComment("DO NOT EDIT THIS FILE");
    
    // first transform the processing instruction and comment
    transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
    transformer.transform(new DOMSource(xmlpi), output);
    transformer.transform(new DOMSource(comment), output);
    // then the document
    transformer.transform(input, output);
    
    0 讨论(0)
  • 2021-02-20 02:36

    There is a JDK bug concerning this. It was not fixed (as you would expect) because that would likely cause many problems to users' existing applications.

    Adding the following output property fixes this:

    transformer.setOutputProperty("http://www.oracle.com/xml/is-standalone", "yes");
    
    0 讨论(0)
  • 2021-02-20 02:43

    Revisiting this after some time because I had the same issue. I found another solution that does not need to buffer the output in a String:

    1. Write only the XML-declaration by passing an empty document. This will also append a linebreak.

    2. Write the document content without XML-declaration

    Code:

    StreamResult streamResult = new StreamResult(writer);
    // output XML declaration with an empty document
    transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
    transformer.transform(new DOMSource(), streamResult);
    // output the document without XML declaration
    transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
    transformer.transform(new DOMSource(doc), streamResult);
    
    0 讨论(0)
  • 2021-02-20 02:46

    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.

    0 讨论(0)
提交回复
热议问题