【问题标题】:Java: Concatinate two XML NodeListJava:连接两个 XML NodeList
【发布时间】:2014-12-19 01:38:02
【问题描述】:

我想连接两个节点列表并获得一个新的节点列表。目前我的 XML 文档如下所示: 第一个 XML:

<machine>
<values>
<value1> <...> </value1>
<value2> <...> </value2>
</values>

<days>
<value1> <...> </value1>
<value2> <...> </value2>
</days>
</machine>

第二个 XML:

<machine>
<values>
<value3> <...> </value1>
<value4> <...> </value2>
</values>

<days>
<value3> <...> </value1>
<value4> <...> </value2>
</days>
</machine>

目前我只使用一个带有以下内容的 XML:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = null;
document = builder.parse(myxml.xml);
NodeList values = document.getElementsByTagName("values");
NodeList days = document.getElementsByTagName("days");

然后使用值和天数处理 NodeList。我的程序运行良好。现在我以同样的方式创建第二个列表,所以:

DocumentBuilderFactory factory2 = DocumentBuilderFactory.newInstance();
DocumentBuilder builder2 = factory2.newDocumentBuilder();
Document document2 = null;
document2 = builder2.parse(myxml_second.xml);
NodeList values2 = document.getElementsByTagName("values");
NodeList days2 = document.getElementsByTagName("days");

这提出了一个问题: 如何将两个列表连接起来,得到一个列表values 和一个列表days

我需要一个新的 NodeList(类型),因为我的整个程序都使用 NodeList 类型。

我发现了几个线程来解决这个问题,但没有任何效果或返回另一种类型,但不是 NodeList。一种方法有效:

public static NodeList join(final NodeList... lists) {

    class JoinedNodeList implements NodeList {
      public int getLength() {
        int len = 0;
        for (NodeList list : lists) {
          len += list.getLength();
        }
        return len;
      }

      public Node item(int index) {
        for (NodeList list : lists) {
          if (list.getLength() > index) {
            return list.item(index);
          } else {
            index -= list.getLength();
          }
        }
        return null;
      }
    }

    return new JoinedNodeList();
  }

然后我的程序完美地与连接的 NodeList 一起工作,但它变得很慢!我认为它来自覆盖这两种方法,因为我在 while 或 for 循环中经常使用它们。没有串联和只有一个大列表,程序非常快。

【问题讨论】:

  • 您是否需要NodeLists 才能继续保持动态?
  • 尝试 col.retainAll(otherCol) // 用于交集和 col.addAll(otherCol) // 用于 Collection 类的并集,看看是否有任何改进
  • @T.J.克劳德动态?我不知道你是什么意思。一旦程序启动,就会调用上面的这个代码块,然后我只使用 NodeLists 值/天
  • @РоманГуйван 你说的retainAll是什么意思?你能和我的两个 NodeList 共享一个代码 sn-p 吗?!谢谢你!

标签: java xml concat


【解决方案1】:

我想提出以下优化建议,可能会解决您的“病态缓慢”问题。

  • 在施工期间计算一次长度,因为这不会改变。
  • 在构造过程中将 NodeList 实例展平为原始数组,这样 item() 就不必做太多工作。

假设

  • 列表不需要是动态的,即 DOM 更改不会反映在列表中,这可能是因为我认为 getElementsByTagName() 返回的结果无论如何都不是动态的
  • 文档相对较小,因此额外的内存不是问题。
  • 后来有很多读物说明施工期间的额外工作会带来投资回报。

代码

public static NodeList join(final NodeList... lists) {

    int count = 0;
    for (NodeList list : lists) {
        count += list.getLength();
    }
    final int length = count;

    Node[] joined = new Node[length];
    int outputIndex = 0;
    for (NodeList list : lists) {
        for (int i = 0, n = list.getLength(); i < n; i++) {
            joined[outputIndex++] = list.item(i);
        }
    }
    class JoinedNodeList implements NodeList {
        public int getLength() {
            return length;
        }

        public Node item(int index) {
            return joined[index];
        }
    }

    return new JoinedNodeList();
}

【讨论】:

  • 完美,完美,完美。太感谢了!它甚至比我的旧版本更快:) 解决方案非常简单.. PS:我的 Eclipse 只接受 Node[] 作为最终加入。为什么?但它有效:)
  • @asdf:这就是我去吃午饭前提出问题的原因。 :-) (NodeList 实例是动态的,这意味着如果基础文档以影响NodeList 的方式更改,您会看到该更改反映在NodeList 中。您问题中的实现保持这一点,但在巨大的成本。Adam 的实现没有维护它,从而显着提高了性能。)
  • @T.J.Crowder 好的,谢谢您的解释!哪里有好心的论坛提问,虽然在我学习期间谷歌给我带来了很多次给你:)谢谢!
  • @asdf 这个答案能解决你的问题吗?您还需要信息吗?
  • @asdf:很高兴能提供帮助(我敢肯定,Adam 也是如此)。如果亚当的回答回答了您的问题,本网站的工作方式,您将通过单击旁边的复选标记“接受”该答案。详情:stackoverflow.com/help/someone-answersBest,
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-14
  • 1970-01-01
  • 2014-06-06
相关资源
最近更新 更多