1

您现在将看到的类是在 Java 中通过 XPath 解析 XML 文档的经典方法:

public class Main {

    private Document createXMLDocument(String fileName) throws Exception {
        DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
        domFactory.setNamespaceAware(true);
        DocumentBuilder builder = domFactory.newDocumentBuilder();
        Document doc = builder.parse(fileName);

        return doc;
    }

    private NodeList readXMLNodes(Document doc, String xpathExpression) throws Exception {
        XPath xpath = XPathFactory.newInstance().newXPath();
        XPathExpression expr = xpath.compile(xpathExpression);

        Object result = expr.evaluate(doc, XPathConstants.NODESET);
        NodeList nodes = (NodeList) result;

        return nodes;
    }

    public static void main(String[] args) throws Exception {
        Main m = new Main();
        Document doc = m.createXMLDocument("tv.xml");
        NodeList nodes = m.readXMLNodes(doc, "//serie/eason/@id");
        int n = nodes.getLength();

        Map<Integer, List<String>> series = new HashMap<Integer, List<String>>();

        for (int i = 1; i <= n; i++) {
            nodes = m.readXMLNodes(doc, "//serie/eason[@id='" + i + "']/episode/text()");
            List<String> episodes = new ArrayList<String>();
            for (int j = 0; j < nodes.getLength(); j++) {
                episodes.add(nodes.item(j).getNodeValue());
            }
            series.put(i, episodes);
        }

        for (Map.Entry<Integer, List<String>> entry : series.entrySet()) {
            System.out.println("Season: " + entry.getKey());
            for (String ep : entry.getValue()) {
                System.out.println("Episodio: " + ep);
            }
            System.out.println("+------------------------------------+");
        }
    }
}

在那里,我发现一些方法令人担心,以防 xml 文件很大。喜欢使用

Document doc = builder.parse(fileName);

return doc;

或者

  Object result = expr.evaluate(doc, XPathConstants.NODESET);
  NodeList nodes = (NodeList) result;

  return nodes;

我很担心,因为我需要处理的 xml 文档是由客户创建的,并且在里面你基本上可以有无限数量的描述电子邮件及其内容的记录(每个用户都有自己的个人电子邮件,所以里面有很多 html)。我知道这不是最聪明的方法,但它是一种可能性,并且在我到达这里之前它已经启动并运行。

我的问题是:如何使用 xpathparseevaluate巨大的 xml 文件?

4

2 回答 2

3

您可以使用 StAX 解析器。它将比 DOM 选项占用更少的内存。在http://tutorials.jenkov.com/java-xml/stax.html上对 StAX 进行了很好的介绍

于 2012-04-22T17:07:16.870 回答
3

首先,XPath 不解析 XML。您的 createXMLDocument() 方法会执行此操作,生成已解析 XML 的树表示形式作为输出。然后使用 XPath 搜索树表示。

您真正需要的是在解析 XML 时动态搜索 XML 的内容。

一种方法是使用实​​现“文档投影”的 XQuery 系统(例如,Saxon-EE)。这将分析您的查询以查看需要文档的哪些部分,并且当您解析文档时,它将构建一个仅包含文档中实际需要的部分的树。

但是,如果查询与示例中的查询一样简单,那么将其编码为 SAX 应用程序并不难,其中诸如 startElement 和 endElement 之类的事件由 XML 解析器通知给应用程序,而无需构建记忆中的树。

于 2012-04-22T17:10:10.777 回答