Java 在根节点之前的xml文件中添加换行符

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24551962/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 12:56:05  来源:igfitidea点击:

Adding linebreak in xml file before root node

javaxmlline-breaksdomparser

提问by Murali Krishna

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

我试图在 XML 文档中根节点上方的注释后添加换行符。

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

        }

    }
}

采纳答案by Tomalak

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);
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.

编辑:似乎不允许在org.w3c.dom.Document. 这在形式上是 100% 正确的,但也无济于事。

The way comments are rendered in the output of the Transformeris 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.

注释在输出中呈现的方式Transformer由它使用的序列化器决定(HTML、XML 和纯文本输出有不同的序列化器)。在内置的 XML 序列化程序中,注释的结尾被定义为-->- 没有换行符。

Since the internals of javax.xml.transform.Transformerare 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.

由于 的内部javax.xml.transform.Transformer是硬连接的,序列化器不是公共 API,并且类被标记为final,覆盖该行为或设置自定义序列化器是不可能的。

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

换句话说,您不走运以干净的方式添加换行符。

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.

一般不鼓励对 XML 字符串执行搜索和替换操作,但在这种情况下,几乎不会出错。

回答by Axel

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

  1. 通过传递一个空文档只编写 XML 声明。这也将附加换行符。

  2. 编写没有 XML 声明的文档内容

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);

回答by eddo

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:

您可以通过不向文档添加注释节点,而是部分转换文档来实现此目的。先分别转换自己的XML处理指令和注释,然后是文档的其余部分:

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);

回答by Sergey Eremin

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

有一个与此相关的JDK 错误。它没有修复(如您所料),因为这可能会给用户现有的应用程序带来许多问题。

Adding the following output property fixes this:

添加以下输出属性可解决此问题:

transformer.setOutputProperty("http://www.oracle.com/xml/is-standalone", "yes");