Closed. This question is off-topic。它当前不接受答案。
                            
                        
                    
                
                            
                                
                
                        
                            
                        
                    
                        
                            想改善这个问题吗? Update the question,所以它是on-topic,用于堆栈溢出。
                        
                        4年前关闭。
                                                                                            
                
        
给定一组三个XML文件:

first.xml

<root>
    <item1>A</item1>
    <complexItem>
        <item2>B</item2>
        <item3>C</item2>
    </complexItem>
</root>


patch1.xml

<root>
     <item1>X</item1>
</root>


patch2.xml

<root>
     <complexItem>
         <item3>Y</item>
     </complexItem>
     <differentItem>Z</differentItem>
<root>


我想以XML结尾:

补丁文件

<root>
    <item1>X</item1>
    <complexItem>
        <item2>B</item2>
        <item3>Y</item2>
    </complexItem>
    <differentItem>Z</differentItem>
</root>


因此,补丁中的新元素是可加的,而补丁中的现有元素是破坏性的。这些添加和更新可以在文档树的任何级别进行。理想情况下,这将是一个可以将文件列表作为参数的Maven插件,尽管Java中的解决方案(即可用库-我正努力避免重新发明似乎应该已经完成​​的东西!)很好因为我可以自己编写插件。每个文件(基本文件和修补程序)将始终具有相同的根元素。



我应该添加,没有用例可以从树中删除元素(我们文件替换的层级性质导致这对于使用修补文件的应用程序来说是错误的情况)。我做了一些更多的搜索,以寻找一个预先构建的工具或库,但找不到合适的东西,于是安德鲁建议使用dom4j从头开始构建一些东西。完全不熟悉dom4j,但这大致就是我想出的(无需审查/错误处理/正确的注释等):

public void execute(){

    // Environment specific file loading removed

    SAXReader reader = new SAXReader();
Document patchedDocument = null;
for (InputStream is : loadedFiles) {
    Document d = null;
    try {
        d = reader.read(is);
    } catch (DocumentException e) {
        e.printStackTrace();
    }
    if (patchedDocument == null) {
        patchedDocument = d;
    } else {
        Element root = d.getRootElement();
        patch(patchedDocument, root);
    }
}

    // Environment specific file writing

}

private void patch(Document patchedDocument, Element element) {

    for (Iterator i = element.elementIterator(); i.hasNext();) {
        Element nextElement = (Element) i.next();
        if (nextElement.isTextOnly()) {
            String path = nextElement.getUniquePath();
            Node n = patchedDocument.selectSingleNode(path);
            if (n != null)
            {
                                // This already exists and needs content replacing
                n.setText(nextElement.getText());
            }else{
                                // This doesn't exist and needs to be added to the tree
                addElement(patchedDocument, nextElement);
            }
        } else {
            patch(patchedDocument, nextElement);
        }
    }
}

private Node addElement(Document patchedDocument, Element element)
{
    Element parent = element.getParent();
    String parentPath = parent.getPath();
    Node n = patchedDocument.selectSingleNode(parentPath);
    if (n == null){
        return addElement(patchedDocument, parent);
    } else {
        ((Branch)n).add(element.detach());
        return n;
    }
}

最佳答案

如果文件足够小以适合内存,我将编写一些Java代码以将它们全部封装到单独的DOM中,然后根据您描述的加性/破坏性逻辑将它们合并为一个DOM,然后将合并的DOM吐回移到目标文件中。有几种Java库可用于读取和写入XML文件,例如dom4j。您不想自己尝试解析或构造XML就是一件麻烦事。

09-16 00:33