使用DOM

因为XML是一种树形结构的文档,它有两种标准的解析API:

  • DOM:一次性读取XML,并在内存中表示为树形结构;
  • SAX:以流的形式读取XML,使用事件回调。

我们先来看如何使用DOM来读取XML。

DOM是Document Object Model的缩写,DOM模型就是把XML结构作为一个树形结构处理,从根节点开始,每个节点都可以包含任意个子节点。

我们以下面的XML为例:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <book id="1">
  3. <name>Java核心技术</name>
  4. <author>Cay S. Horstmann</author>
  5. <isbn lang="CN">1234567</isbn>
  6. <tags>
  7. <tag>Java</tag>
  8. <tag>Network</tag>
  9. </tags>
  10. <pubDate/>
  11. </book>

如果解析为DOM结构,它大概长这样:

  1. ┌─────────┐
  2. document
  3. └─────────┘
  4. ┌─────────┐
  5. book
  6. └─────────┘
  7. ┌──────────┬──────────┼──────────┬──────────┐
  8. ┌─────────┐┌─────────┐┌─────────┐┌─────────┐┌─────────┐
  9. name ││ author ││ isbn ││ tags ││ pubDate
  10. └─────────┘└─────────┘└─────────┘└─────────┘└─────────┘
  11. ┌────┴────┐
  12. ┌───────┐ ┌───────┐
  13. tag tag
  14. └───────┘ └───────┘

注意到最顶层的document代表XML文档,它是真正的“根”,而<book>虽然是根元素,但它是document的一个子节点。

Java提供了DOM API来解析XML,它使用下面的对象来表示XML的内容:

  • Document:代表整个XML文档;
  • Element:代表一个XML元素;
  • Attribute:代表一个元素的某个属性。

使用DOM API解析一个XML文档的代码如下:

  1. InputStream input = Main.class.getResourceAsStream("/book.xml");
  2. DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
  3. DocumentBuilder db = dbf.newDocumentBuilder();
  4. Document doc = db.parse(input);

DocumentBuilder.parse()用于解析一个XML,它可以接收InputStream,File或者URL,如果解析无误,我们将获得一个Document对象,这个对象代表了整个XML文档的树形结构,需要遍历以便读取指定元素的值:

  1. void printNode(Node n, int indent) {
  2. for (int i = 0; i < indent; i++) {
  3. System.out.print(' ');
  4. }
  5. switch (n.getNodeType()) {
  6. case Node.DOCUMENT_NODE: // Document节点
  7. System.out.println("Document: " + n.getNodeName());
  8. break;
  9. case Node.ELEMENT_NODE: // 元素节点
  10. System.out.println("Element: " + n.getNodeName());
  11. break;
  12. case Node.TEXT_NODE: // 文本
  13. System.out.println("Text: " + n.getNodeName() + " = " + n.getNodeValue());
  14. break;
  15. case Node.ATTRIBUTE_NODE: // 属性
  16. System.out.println("Attr: " + n.getNodeName() + " = " + n.getNodeValue());
  17. break;
  18. default: // 其他
  19. System.out.println("NodeType: " + n.getNodeType() + ", NodeName: " + n.getNodeName());
  20. }
  21. for (Node child = n.getFirstChild(); child != null; child = child.getNextSibling()) {
  22. printNode(child, indent + 1);
  23. }
  24. }

解析结构如下:

  1. Document: #document
  2. Element: book
  3. Text: #text =
  4. Element: name
  5. Text: #text = Java核心技术
  6. Text: #text =
  7. Element: author
  8. Text: #text = Cay S. Horstmann
  9. Text: #text =
  10. ...

对于DOM API解析出来的结构,我们从根节点Document出发,可以遍历所有子节点,获取所有元素、属性、文本数据,还可以包括注释,这些节点被统称为Node,每个Node都有自己的Type,根据Type来区分一个Node到底是元素,还是属性,还是文本,等等。

使用DOM API时,如果要读取某个元素的文本,需要访问它的Text类型的子节点,所以使用起来还是比较繁琐的。

练习

下载练习:使用DOM解析XML (推荐使用IDE练习插件快速下载)

小结

Java提供的DOM API可以将XML解析为DOM结构,以Document对象表示;

DOM可在内存中完整表示XML数据结构;

DOM解析速度慢,内存占用大。

读后有收获可以支付宝请作者喝咖啡,读后有疑问请加微信群讨论

使用DOM - 图1使用DOM - 图2