在java中读取XML标记,代码优化

在java中读取XML标记,代码优化,java,optimization,Java,Optimization,我实际上在做的是一个递归函数,它读取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 itemChil

我实际上在做的是一个递归函数,它读取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());
      }
}
private void readTag(org.w3c.dom.Node项、字符串histortags、字符串文件名、哈希表tagsInfos){
试一试{
if(item.getNodeType()==Node.ELEMENT\u Node){
nodelistitemchilds=item.getChildNodes();
对于(int i=0;i
执行此函数需要一些时间。函数读取的xml格式如下:

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

32R0100000772669473
32R
0

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

两种优化方法,不知道有多大帮助:

  • 不要使用
    getChildNodes()
    。使用
    getFirstChild()
    getNextSibling()
  • 重用单个
    StringBuilder
    ,而不是为每个元素创建一个新的元素(通过
    histortags+“|”+item.getNodeName()
    隐式完成)
但是,您还应该注意,元素节点的文本内容可能被视为多个文本和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);
    }
}

查看使用CDATA和注释拆分
节点内的文本如何导致DOM节点包含多个文本/CDATA子节点。

您可以使用一些xml对象映射(例如使用xstream)来完成这项工作,这可能会更有效。您可以发布一个mcve来重现“慢度”?@RC.:你能举个例子吗?看
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);