2014-10-31 47 views
0

我想連接兩個org.w3c.dom.Document中的S,我有這樣的事情:連接兩個org.w3c.dom.Document中

Document finalDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument() 
Document document1 = createDocumentOne(); 
Document document2 = createDocumentTwo(); 

// This didn't work 
changeFileDocument.appendChild(document1); 
changeFileDocument.appendChild(document2); 

的文檔1和文件2的格式是一樣的東西這樣的:

<headerTag> 
    <tag1>value</tag1> 
</headerTag> 

而我想的是,到了最後,像這樣的文件:

<headerTag> 
    <tag1>valueForDocument1</tag1> 
</headerTag> 
<headerTag> 
    <tag1>valueForDocument2</tag1> 
</headerTag> 

我認爲你不能做到這一點,因爲他們應該有一個共同的父母。如果是這樣,我想創建該「假」母,連接文件,但只能恢復元素列表headerTag

我該怎麼做?

+0

是'headerTag'的根元素嗎?如果不是什麼是根元素? – A4L 2014-10-31 18:51:19

+0

您需要一個根元素來構建適當的xml文檔。如果它不是xml,請提及構建它的標記語言。此外,爲什麼不將org.w3c.Document轉換爲各自的String文件並將它們連接起來,最後再創建另一個org.w3c.Document實例。 – 2014-10-31 18:52:11

+0

@ A4L,'headerTag'是由方法'createDocument1'和'createDocument2'創建的文檔的根元素,我唯一想要的是將一個接一個地連接起來,即使我必須創建一個根父級。 – Manuelarte 2014-10-31 19:04:36

回答

1

您在正確的軌道上創建新文檔,解析零件並將其添加到新零件中。

您接近失敗,因爲您嘗試將整個文檔追加到另一個不可能的地方。

你可以嘗試這樣的事:

public org.w3c.dom.Document concatXmlDocuments(String rootElementName, InputStream... xmlInputStreams) throws ParserConfigurationException, SAXException, IOException { 
    DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); 
    org.w3c.dom.Document result = builder.newDocument(); 
    org.w3c.dom.Element rootElement = result.createElement(rootElementName); 
    result.appendChild(rootElement); 
    for(InputStream is : xmlInputStreams) { 
     org.w3c.dom.Document document = builder.parse(is); 
     org.w3c.dom.Element root = document.getDocumentElement(); 
     NodeList childNodes = root.getChildNodes(); 
     for(int i = 0; i < childNodes.getLength(); i++) { 
      Node importNode = result.importNode(childNodes.item(i), true); 
      rootElement.appendChild(importNode); 
     } 
    } 
    return result; 
} 

以上副本的代碼每個文檔的根元素下找到的所有節點。當然,您可以選擇僅複製您感興趣的節點。生成的文檔將反映這兩個文檔中的所有節點。

測試

@Test 
public void concatXmlDocuments() throws ParserConfigurationException, SAXException, IOException, TransformerException { 
    try (
      InputStream doc1 = new ByteArrayInputStream((
       "<headerTag>\r\n" + 
       " <tag1>doc1 value</tag1>\r\n" + 
       "</headerTag>").getBytes(StandardCharsets.UTF_8)); 
      InputStream doc2 = new ByteArrayInputStream((
       "<headerTag>\r\n" + 
       " <tag1>doc2 value</tag1>\r\n" + 
       "</headerTag>").getBytes(StandardCharsets.UTF_8)); 
      ByteArrayOutputStream docR = new ByteArrayOutputStream(); 

     ) { 

     org.w3c.dom.Document result = concatXmlDocuments("headerTag", doc1, doc2); 
     TransformerFactory trf = TransformerFactory.newInstance(); 
     Transformer tr = trf.newTransformer(); 
     tr.setOutputProperty(OutputKeys.INDENT, "yes"); 
     DOMSource source = new DOMSource(result); 
     StreamResult sr = new StreamResult(docR); 
     tr.transform(source, sr); 
     System.out.print(new String(docR.toByteArray(), StandardCharsets.UTF_8)); 
    } 
} 

輸出

<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
<headerTag> 
    <tag1>doc1 value</tag1> 
    <tag1>doc2 value</tag1> 
</headerTag> 

編輯

我想創建一個 「假」 的父母,串聯的文件,BU T,然後只能收回元素的列表headerTag

正如你所說,創建父。這裏是你如何能做到這一點:

1)執行級聯

public org.w3c.dom.Document concatXmlDocuments(InputStream... xmlInputStreams) throws ParserConfigurationException, SAXException, IOException { 
    DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); 
    org.w3c.dom.Document result = builder.newDocument(); 
    org.w3c.dom.Element rootElement = result.createElement("fake"); 
    result.appendChild(rootElement); 
    for(InputStream is : xmlInputStreams) { 
     org.w3c.dom.Document document = builder.parse(is); 
     org.w3c.dom.Element subRoot = document.getDocumentElement(); 
     Node importNode = result.importNode(subRoot, true); 
     rootElement.appendChild(importNode); 
    } 
    return result; 
} 

2)恢復節點列表headerTag

public NodeList recoverTheListOfElementsHeaderTag(String xml) throws ParserConfigurationException, SAXException, IOException { 
    NodeList listOfElementsHeaderTag = null; 
    DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); 
    try (InputStream is = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))) { 
     listOfElementsHeaderTag = recoverTheListOfElementsHeaderTag(builder.parse(is)); 
    } 
    return listOfElementsHeaderTag; 
} 

public NodeList recoverTheListOfElementsHeaderTag(org.w3c.dom.Document doc) { 
    org.w3c.dom.Element root = doc.getDocumentElement(); 
    return root.getChildNodes(); 
} 

測試

@Test 
public void concatXmlDocuments() throws ParserConfigurationException, SAXException, IOException, TransformerException { 
    try (
      InputStream doc1 = new ByteArrayInputStream((
       "<headerTag>" + 
       "<tag1>doc1 value</tag1>" + 
       "</headerTag>").getBytes(StandardCharsets.UTF_8)); 
      InputStream doc2 = new ByteArrayInputStream((
       "<headerTag>" + 
       "<tag1>doc2 value</tag1>" + 
       "</headerTag>").getBytes(StandardCharsets.UTF_8)); 

     ) { 

     org.w3c.dom.Document result = concatXmlDocuments(doc1, doc2); 
     String resultXML = toXML(result); 
     System.out.printf("%s%n", resultXML); 
     NodeList listOfElementsHeaderTag = null; 
     System.out.printf("===================================================%n"); 
     listOfElementsHeaderTag = recoverTheListOfElementsHeaderTag(resultXML); 
     printNodeList(listOfElementsHeaderTag); 
     System.out.printf("===================================================%n"); 
     listOfElementsHeaderTag = recoverTheListOfElementsHeaderTag(result); 
     printNodeList(listOfElementsHeaderTag); 
    } 
} 


private String toXML(org.w3c.dom.Document result) throws TransformerFactoryConfigurationError, TransformerConfigurationException, TransformerException, IOException { 
    String resultXML = null; 
    try (ByteArrayOutputStream docR = new ByteArrayOutputStream()) { 
     TransformerFactory trf = TransformerFactory.newInstance(); 
     Transformer tr = trf.newTransformer(); 
     DOMSource source = new DOMSource(result); 
     StreamResult sr = new StreamResult(docR); 
     tr.transform(source, sr); 
     resultXML = new String(docR.toByteArray(), StandardCharsets.UTF_8); 
    } 
    return resultXML; 
} 

private void printNodeList(NodeList nodeList) { 
    for(int i = 0; i < nodeList.getLength(); i++) { 
     printNode(nodeList.item(i), ""); 
    } 
} 

private void printNode(Node node, String startIndent) { 
    if(node != null) { 
     System.out.printf("%s%s%n", startIndent, node.toString()); 
     NodeList childNodes = node.getChildNodes(); 
     for(int i = 0; i < childNodes.getLength(); i++) { 
      printNode(childNodes.item(i), startIndent+ " "); 
     } 
    } 
} 

輸出

<?xml version="1.0" encoding="UTF-8" standalone="no"?><fake><headerTag><tag1>doc1 value</tag1></headerTag><headerTag><tag1>doc2 value</tag1></headerTag></fake> 
=================================================== 
[headerTag: null] 
    [tag1: null] 
     [#text: doc1 value] 
[headerTag: null] 
    [tag1: null] 
     [#text: doc2 value] 
=================================================== 
[headerTag: null] 
    [tag1: null] 
     [#text: doc1 value] 
[headerTag: null] 
    [tag1: null] 
     [#text: doc2 value] 
+0

Hi @ A4L,感謝您的評論,但這不是我感興趣的輸出。我感興趣的 ' DIC1值 DOC2值 ' – Manuelarte 2014-10-31 22:57:25

+0

@Manuelarte,OK,那麼爲什麼用XML解析費心呢?你想要的輸出不是有效的XML,那麼根標籤出現兩次或者沒有根標籤,所以只需將兩個文件作爲文本讀取並應用'+'運算符。如果您之後需要將其解析爲XML,則需要將其包裝在名稱不是「headerTag」的根標籤中,然後使用「Document#getDocumentElement()。getElementsByTagName(」tag1「)獲取所需的節點。 ;' – A4L 2014-10-31 23:23:11

+0

@Manuelarte,我已經編輯了我的答案,希望它能反映出你的要求。 – A4L 2014-11-01 12:13:57

1

正如您所說,您需要有一個根節點 - 並且您需要導入其他文檔。例如:

Element root = finalDocument.createElement("root"); 
finalDocument.appendChild(root); 
root.appendChild(
    finalDocument.importNode(document1.getDocumentElement(), true)); 
root.appendChild(
    finalDocument.importNode(document2.getDocumentElement(), true)); 
+0

然後,我使用finalDocument.changeFileDocument.getChildNodes()檢索我感興趣的元素?我呢? – Manuelarte 2014-10-31 18:53:00

+0

@Manuelarte:那麼它完全不清楚'changeFileDocument'是什麼意思,或者你說的「我感興趣的元素」是什麼意思。 – 2014-10-31 18:53:46

+0

您使用方法createDocument1(),createDocument2()創建XML文檔。然後,你想將它們連接成一個單獨的文件,稱爲finalDocument。稍後,我想從finalDocument中恢復只有節點。它更清楚嗎? – Manuelarte 2014-10-31 19:01:55