2014-10-31 75 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