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

时间:2014-07-03 11:02:04

标签: java xml line-breaks domparser

我正在尝试在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

        }

    }
}

5 个答案:

答案 0 :(得分:7)

你基本上想要一个包含注释节点后换行符的文本节点。

Element docElem = doc.getDocumentElement();

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

<击>


编辑:似乎在org.w3c.dom.Document的根节点上不允许附加仅空白文本节点。这是100%正式的,但也没有帮助。

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

由于javax.xml.transform.Transformer的内部是硬连线的,因此序列化程序不是公共API,并且该类标记为final,因此无法覆盖该行为或设置自定义序列化程序。

换句话说,如果以 clean 的方式添加换行符,你就不幸了。

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

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字符串执行搜索和替换操作是非常不鼓励的,但在这种情况下,几乎没有什么可以出错。

答案 1 :(得分:2)

一段时间之后重新审视这个问题,因为我遇到了同样的问题。我找到了另一个不需要在String中缓冲输出的解决方案:

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

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

  3. 代码:

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

答案 2 :(得分:0)

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

$ANDROID_HOME

答案 3 :(得分:0)

JDK bug这个问题。它没有固定(如你所料),因为这可能会给用户造成许多问题。现有的申请。

添加以下输出属性修复了此问题:

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

答案 4 :(得分:0)

有同样的问题。 我通过将注释放在根元素中来解决了这一问题。 不完全相同,但我认为可以接受。