【问题标题】:What's wrong with this Java XML-Parsing code?这个 Java XML-Parsing 代码有什么问题?
【发布时间】:2012-01-04 14:34:32
【问题描述】:

我正在尝试解析 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而不是文本。

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

非常感谢您的帮助!

问候,弗洛

【问题讨论】:

  • 你可能走得太远了。如果在您的循环中,您将获得其中所有元素的子元素 |分隔列表,最后返回的值将是“垃圾邮件”的孩子,不存在。
  • Java 从 JavaSE 5 开始就有一个 XPath 库。它可以在 javax.xml.xpath 包中找到。

标签: java xml parsing


【解决方案1】:

您正在调用 Node.getNodeValue() - 当您在元素上调用它时,它会返回 null。您应该改为调用 getTextContent() - 或者使用更高级别的 API,当然。

【讨论】:

    【解决方案2】:

    正如我之前提到的其他人,您似乎在重新发明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 语言。

    【讨论】:

    • 如果&lt;agent&gt;...&lt;/agent&gt; 部分被复制并且第二个标签名称和 ifc 中还有其他值,我该如何从那里获取集合? (所有代理/例如所有代理/名称值)?
    • nameAnameB
    • @Florian 我添加了一个提取集合的示例。
    【解决方案3】:

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

    手动操作是等待发生的意外;要么使用内置的 XPath 解决方案,要么使用 @duffymo 建议的第三方库。这不是重新发明增加价值的情况,IMO。

    【讨论】:

      【解决方案4】:

      我想知道您为什么不使用像 dom4j 这样的库和内置的 XPath。您正在使用非常低级的 API (WC3 DOM) 进行大量工作。

      使用调试器逐步检查&lt;spam&gt; 节点有哪些子节点。你应该很快弄清楚为什么它是空的。比在这里问要快。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-10-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-05
        • 2017-07-30
        相关资源
        最近更新 更多