这个Java XML解析代码有什么问题?

问题描述:

我试图解析一个XML文件,并能够插入一个路径并获得该字段的值。这个Java XML解析代码有什么问题?

它看起来如下:

import java.io.IOException; 
import javax.xml.parsers.*; 
import org.w3c.dom.*; 
import org.xml.sax.SAXException; 

public class XMLConfigManager { 
    private Element config = null; 

    public XMLConfigManager(String file) { 
     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
     try { 
      Document domTree; 
      DocumentBuilder db = dbf.newDocumentBuilder(); 
      domTree = db.parse(file); 
      config = domTree.getDocumentElement(); 
     } 
     catch (IllegalArgumentException iae) { 
      iae.printStackTrace(); 
     } 
     catch (ParserConfigurationException pce) { 
      pce.printStackTrace(); 
     } 
     catch (SAXException se) { 
      se.printStackTrace(); 
     } 
     catch (IOException ioe) { 
      ioe.printStackTrace(); 
     } 
    } 
    public String getStringValue(String path) { 
     String[] pathArray = path.split("\\|"); 
     Element tempElement = config; 
     NodeList tempNodeList = null; 
     for (int i = 0; i < pathArray.length; i++) { 
      if (i == 0) { 
       if (tempElement.getNodeName().equals(pathArray[0])) { 
        System.out.println("First element is correct, do nothing here (just in next step)"); 
       } 
       else { 
        return "**This node does not exist**"; 
       } 
      } 
      else { 
       tempNodeList = tempElement.getChildNodes(); 
       tempElement = getChildElement(pathArray[i],tempNodeList); 
      } 
     }  
     return tempElement.getNodeValue(); 
    } 
    private Element getChildElement(String identifier, NodeList nl) { 
     String tempNodeName = null; 
     for (int i = 0; i < nl.getLength(); i++) { 
      tempNodeName = nl.item(i).getNodeName(); 
      if (tempNodeName.equals(identifier)) { 
       Element returner = (Element)nl.item(i).getChildNodes(); 
       return returner; 
      } 
     } 
     return null; 
    } 
} 

的XML看起来像这样(用于测试目的):

<?xml version="1.0" encoding="UTF-8"?> 
<amc> 
    <controller> 
     <someOtherTest>bla</someOtherTest> 
     <general> 
      <spam>This is test return String</spam> 
      <interval>1000</interval> 
     </general> 
    </controller> 
    <agent> 
     <name>test</name> 
     <ifc>ifcTest</ifc> 
    </agent> 
</amc> 

现在我可以调用类这样

XMLConfigManager xmlcm = new XMLConfigManager("myConfig.xml"); 
System.out.println(xmlcm.getStringValue("amc|controller|general|spam")); 

这里,我期待标签spam的价值,所以这将是“This is test return String”。但我得到null

我试图解决这个问题好几天了,我无法得到它。迭代可以工作,所以它会到达标记spam,但是,正如我所说的那样,它会返回null而不是文本。

这是一个错误还是我只是做错了?为什么? :(

非常感谢您的帮助!

问候,弗洛

+0

你可能会更进一步。如果在你的循环中,你会得到那个|中所有元素的子元素分隔列表中,最后返回的值将是“垃圾邮件”的子元素,它不存在。 – Tudor 2012-01-04 14:40:11

+2

自从JavaSE 5以来,Java已经有了一个XPath库。它可以在'javax.xml.xpath'包中找到。 – Dev 2012-01-04 14:42:42

正如其他人在我之前提到的,您似乎在重塑XPath的概念。你可以用下面的代码替换代码:

javax.xml.xpath.XPath xpath = javax.xml.xpath.XPathFactory.newInstance().newXPath(); 
String expression = "/amc/controller/general/spam"; 
org.xml.sax.InputSource inputSource = new org.xml.sax.InputSource("myConfig.xml"); 
String result = xpath.evaluate(expression, inputSource); 

参见:XML Validation and XPath Evaluation in J2SE 5.0

编辑:

使用XPath提取收集的一个例子:

NodeList result = (NodeList) xpath.evaluate(expression, inputSource, XPathConstants.NODESET); 
for (int i = 0; i < result.getLength(); i++) { 
    System.out.println(result.item(i).getTextContent()); 
} 

javax.xml.xpath.XPath界面被记录为here,并且还有几个考试在aforementioned article

此外,还有第三方库用于XML操作,您可能会发现更方便,例如dom4j(由duffymo建议)或JDOM。无论您使用哪个库,都可以使用功能非常强大的XPath语言。

+0

如果零件' ...'被复制,并且第二个标签名称和ifc中还有其他值,那么我该如何获得一个集合? (所有代理/例如所有代理/名称值)? – 2012-01-04 16:05:20

+0

(小例子:) – 2012-01-04 16:34:33

+0

NAMEA nameB 2012-01-04 16:36:58

为什么你不使用图书馆像dom4j和内置的XPath我不知道。你做了很多使用非常低级别的API(WC3 DOM)工作

用调试器逐步完成并查看子节点有哪些子节点,你应该快速找出它为什么是空的,它会比在这里询问要快。

你打给我Node.getNodeValue() - 将其记录为在元素上调用时返回null。您应该拨打getTextContent(),或者使用更高级别的API,当然。

因为您使用getNodeValue()而不是getTextContent()

用手做这件事是等待发生的事故;可以使用@duffymo建议的内置XPath解决方案或第三方库。这不是重新发明增加价值的情况,IMO。