繁体   English   中英

在Java中合并多个XML文件

[英]Merging multiple XML files in Java

我一直在寻找最好的方法来做到这一点,但我似乎无法找到一个明确的答案如何做到这一点。

我的Java代码中有一个Arraylist of Files,表示应该合并并写入新XML文件的xml文件列表。 这不是固定长度列表,我估计它将在2-10个文件之间。 所有这些文件都有一个非常相似的文档结构,但是一些属性应该在合并时求和。 例如:

文件1

<events>
  <commandEvents date="2013-07-16">
    <commandEvent count="1" commandId="update"/>
    <commandEvent count="1" commandId="debug"/>
    <commandEvent count="3" commandId="resume"/>
  </commandEvents>
</events>

档案2

<events>
  <commandEvents date="2013-07-16">
    <commandEvent count="2" commandId="resume"/>
  </commandEvents>
  <commandEvents date="2013-07-15">
    <commandEvent count="2" commandId="resume"/>
    <commandEvent count="1" commandId="update"/>
  </commandEvents>
</events>

结果

<events>
  <commandEvents date="2013-07-16">
    <commandEvent count="1" commandId="update"/>
    <commandEvent count="1" commandId="debug"/>
    <commandEvent count="5" commandId="resume"/>
  </commandEvents>
  <commandEvents date="2013-07-15">
    <commandEvent count="2" commandId="resume"/>
    <commandEvent count="1" commandId="update"/>
  </commandEvents>
</events>

为了澄清,合并应该发生在commandEvents [@date] / commandEvent [@commandId]。commandEvent元素有一些更多的属性,但是每个元素都是相同的,所以我在这里省略了它们。 并非所有日期都会在每个文档中提供。

我首先找到了一些XSLT路由的答案,但我对XSLT语法很困惑。 虽然我不完全确定这些文件可能达到的大小,但我会非常惊讶它们将> 1mb,所以像JDOM或XOM这样的Java DOM解析器可能也可以工作,但我必须加载所有这些文件同时或成对迭代。

什么被认为是最好的方法? 如果XSLT被认为是最好的解决方案,那么可以给我一些提示吗?

这是一个简单的合并,其中一个文档中根节点的所有子节点都附加到第二个文档的根节点:

public static void mergeSecondLevel(Document from, Document to) {
    Element fromRoot = from.getDocumentElement();
    Element toRoot = to.getDocumentElement();

    Node child = null;
    while ((child = fromRoot.getFirstChild()) != null) {
        to.adoptNode(child);
        toRoot.appendChild(child);
    }
}

如果您在合并它们之前尝试在节点上进行某种处理(您说某些属性应该求和),那么这将是不够的。 有一个链接的帖子涵盖了使用XPath来检索节点,但即使这样,你也必须编写逻辑来确保正确的更新。

检查XmlCombiner ,它是一个实现XML合并的Java库,并允许添加过滤器,您可以在其中指定用于汇总'count'属性值的逻辑。

以下是库初始化的代码:

import org.atteo.xmlcombiner.XmlCombiner;

// create combiner specifying the attributes which are used as a keys
XmlCombiner combiner = new XmlCombiner(Lists.newArrayList("date", "commandId"));
// add the filter
combiner.setFilter(filter);
// combine files
combiner.combine(firstFile);
combiner.combine(secondFile);
// store the result
combiner.buildDocument(resultFile);

以下是过滤器本身的代码:

XmlCombiner.Filter filter = new XmlCombiner.Filter() {
    @Override
    public void postProcess(Element recessive, Element dominant, Element result) {
        if (recessive == null || dominant == null) {
            return;
        }
        Attr recessiveNode = recessive.getAttributeNode("count");
        Attr dominantNode = dominant.getAttributeNode("count");
        if (recessiveNode == null || dominantNode == null) {
            return;
        }

        int recessiveValue = Integer.parseInt(recessiveNode.getValue());
        int dominantValue = Integer.parseInt(dominantNode.getValue());

        result.setAttribute("count", Integer.toString(recessiveValue + dominantValue));
    }
};

免责声明:我是XmlCombiner的作者。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM