2

给定一组三个 XML 文件:

第一个.xml

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

补丁1.xml

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

补丁2.xml

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

我想以 XML 结尾:

补丁.xml

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

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


我应该补充一点,没有从树中删除元素的用例(我们的文件替换的分层性质导致这对于使用修补文件的应用程序来说是一个错误情况)。我做了更多的搜索来寻找一个预先构建的工具或库,但找不到任何合适的东西,所以接受了 Andrew 的建议,即使用 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;
    }
}
4

1 回答 1

0

如果文件足够小以适合内存,我会编写一些 Java 代码将它们全部放入单独的 DOM 中,然后根据您描述的附加/破坏性逻辑将它们合并到一个 DOM 中,然后将合并的 DOM 吐回输出到目标文件中。有几个 Java 库可用于读取和写入 XML 文件,例如 dom4j。您不希望自己尝试解析或构造 XML 时弄得一团糟。

于 2013-01-17T11:09:44.170 回答