【问题标题】:Reading XML tags in java, code optimizationjava中读取XML标签,代码优化
【发布时间】:2016-08-24 02:29:05
【问题描述】:

我实际上在做的是一个递归函数,它读取 xml 中的标签。下面是代码:

private void readTag(org.w3c.dom.Node item, String histoTags, String fileName, Hashtable<String, String> tagsInfos) {
    try {
        if (item.getNodeType() == Node.ELEMENT_NODE) {
            NodeList itemChilds = item.getChildNodes();

            for (int i=0; i < itemChilds.getLength(); i++) {
                org.w3c.dom.Node itemChild = itemChilds.item(i);
                readTag(itemChild, histoTags + "|" + item.getNodeName(), fileName, tagsInfos);
            }
      }
       else if (item.getNodeType() == Node.TEXT_NODE) {
           tagsInfosSoft.put(histoTags, item.getNodeValue());
      }
}

这个函数需要一些时间来执行。函数读取的xml格式如下:

<?xml version="1.0" encoding="UTF-8"?>
<Document>
     <Mouvement>
       <Com>
          <IdCom>32R01000000772669473</IdCom>
          <RefCde>32R</RefCde>
          <Edit>0</Edit>
       <Com>
     <Mouvement>
<Document>

有没有办法在java中优化这段代码?

【问题讨论】:

  • 您可以使用一些 xml 对象映射(例如使用 xstream)来完成这项工作,可能更有效率。也许您可以发布一个重现“缓慢”的 mcve?
  • @RC.: 你能举个例子吗?

标签: java optimization


【解决方案1】:

两个优化,不知道有多大帮助:

  • 不要使用getChildNodes()。使用getFirstChild()getNextSibling()
  • 重复使用单个StringBuilder,而不是为每个元素创建一个新的(由histoTags + "|" + item.getNodeName() 隐式完成)。

但是,您还应该注意,元素节点的文本内容可能被视为多个 TEXT 和 CDATA 节点的组合。

如果您的代码适用于元素而不是节点,您的代码也会更好地运行。

private static void readTag(Element elem, StringBuilder histoTags, String fileName, Hashtable<String, String> tagsInfos) {
    int histoLen = histoTags.length();
    CharSequence textContent = null;
    boolean hasChildElement = false;
    for (Node child = elem.getFirstChild(); child != null; child = child.getNextSibling()) {
        switch (child.getNodeType()) {
            case Node.ELEMENT_NODE:
                histoTags.append('|').append(child.getNodeName());
                readTag((Element)child, histoTags, fileName, tagsInfos);
                histoTags.setLength(histoLen);
                hasChildElement = true;
                break;
            case Node.TEXT_NODE:
            case Node.CDATA_SECTION_NODE:
                //uncomment to test: System.out.println(histoTags + ": \"" + child.getTextContent() + "\"");
                if (textContent == null)
                    // Optimization: Don't copy to a StringBuilder if only one text node will be found 
                    textContent = child.getTextContent();
                else if (textContent instanceof StringBuilder)
                    // Ok, now we need a StringBuilder to collect text from multiple nodes
                    ((StringBuilder)textContent).append(child.getTextContent());
                else
                    // And we keep collecting text from multiple nodes
                    textContent = new StringBuilder(textContent).append(child.getTextContent());
                break;
            default:
                // ignore all others
        }
    }
    if (textContent != null) {
        String text = textContent.toString();
        // Suppress pure whitespace content on elements with child elements, i.e. structural whitespace
        if (! hasChildElement || ! text.trim().isEmpty())
            tagsInfos.put(histoTags.toString(), text);
    }
}

测试

String xml = "<root>\n" +
             "  <tag>hello <![CDATA[world]]> Foo <!-- comment --> Bar</tag>\n" +
             "</root>\n";
Element docElem = DocumentBuilderFactory.newInstance()
                                        .newDocumentBuilder()
                                        .parse(new InputSource(new StringReader(xml)))
                                        .getDocumentElement();
Hashtable<String, String> tagsInfos = new Hashtable<>();
readTag(docElem, new StringBuilder(docElem.getNodeName()), "fileName", tagsInfos);
System.out.println(tagsInfos);

输出(打印未注释)

root: "
  "
root|tag: "hello "
root|tag: "world"
root|tag: " Foo "
root|tag: " Bar"
root: "
"
{root|tag=hello world Foo  Bar}

了解使用 CDATA 和 cmets 拆分 &lt;tag&gt; 节点内的文本如何导致 DOM 节点包含多个 TEXT/CDATA 子节点。

【讨论】:

    猜你喜欢
    • 2016-03-10
    • 2016-11-09
    • 2014-12-10
    • 1970-01-01
    • 2010-11-27
    • 1970-01-01
    • 2014-10-28
    • 2016-12-25
    • 1970-01-01
    相关资源
    最近更新 更多