2014-07-03 166 views
8

我正在嘗試在XML文檔中的根節點之上的註釋之後添加換行符。在根節點之前在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 

     } 

    } 
} 
+2

*「我試圖XML文檔中的根節點我上面的評論後添加換行符。」 * - 爲什麼地球上你想這樣做嗎? – Tomalak

+0

(不要回答,這是一個反問的問題,我明白這純粹是出於美觀的原因,我也不是說這不可能) – Tomalak

+1

@tomalak感謝您的回覆。這是爲了確保文件在發貨之前看起來很好並且可讀。 –

回答

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,因此覆蓋該行爲或設置自定義串行器是不可能的。

換句話說,你運氣不好,在乾淨的方式中加入你的換行符。

你可以,但是,安全地添加一個稍微不潔方式:

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字符串搜索和替換操作一般是高度氣餒,但在這種情況下,很少有能出錯。

+0

我得到低於錯誤 ** _ org.w3c.dom.DOMException:HIERARCHY_REQUEST_ERR:嘗試插入不允許的節點。 _ ** 何時使用以下代碼: 'doc.insertBefore(doc.createTextNode(「\\ n」),docElem);' –

+0

@Murali請參閱修改後的答案。 – Tomalak

1

因爲我有同樣的問題,在一段時間後重新審視。我發現了另一個解決方案,不需要緩衝輸出的字符串:

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

您可以通過不加註釋節點到文檔實現這一目標,而是部分地改變你的文件。首先改變你自己的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);