Java:连接两个XML NodeList

时间:2014-10-23 11:37:31

标签: java xml concat

我想连接两个节点列表并获取一个新的节点列表。目前我的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");

然后使用值&amp;处理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循环中使用它们很多。没有连接,只有一个大的列表,程序非常快。

1 个答案:

答案 0 :(得分: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();
}