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

2022-09-03 06:37:50

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

我需要这样的东西:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--DO NOT EDIT THIS FILE-->
<projects>
</projects>

但是我能够得到的是这个(根内部的换行符,但我需要在注释之后换行):

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--DO NOT EDIT THIS FILE--><projects>

</projects>

我需要在我的评论之后添加换行符。有没有办法做到这一点?

我的代码:

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

        }

    }
}

答案 1

您基本上想要一个文本节点,在注释节点之后包含换行符。

Element docElem = doc.getDocumentElement();

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


编辑:似乎不允许在 的根节点上附加仅空格的文本节点。这在形式上是100%正确的,但也是无益的。org.w3c.dom.Document

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

由于 的内部是硬连线的,因此序列化程序不是公共 API,并且类被标记为 ,重写该行为或设置自定义序列化程序是不可能的。javax.xml.transform.Transformerfinal

换句话说,您很幸运地以干净的方式添加换行符。

但是,您可以以稍微不干净的方式安全地添加它:

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

通常非常不鼓励对 XML 字符串执行搜索和替换操作,但在这种情况下,几乎没有什么错误。


答案 2

一段时间后重新审视这个问题,因为我有同样的问题。我发现了另一个不需要缓冲字符串中的输出的解决方案:

  1. 通过传递空文档来仅写入 XML 声明。这还将附加一个换行符。

  2. 在没有 XML 声明的情况下编写文档内容

法典:

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

推荐