首页 > 代码库 > 02-Java是如何解析xml文件的(DOM)

02-Java是如何解析xml文件的(DOM)

Java解析xml文件

在Java程序中读取xml文件的过程也称为“解析xml文件”;
解析的目的:
  • 获取 节点名和节点值
  • 获取 属性名、属性值。
四中解析方式
  • DOM
  • SAX
  • DOM4J
  • JDOM
(其中DOM、SAX是官方提供的解析方式,不需要额外的jar包,后两种则需要)


例:DOM方式解析books.xml文件

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <bookstore>
  3. <book type="fiction" id="1">
  4. <name>冰与火之歌</name>
  5. <author>乔治马丁</author>
  6. <year>2014</year>
  7. <price>89</price>
  8. </book>
  9. <book id="2">
  10. <name>安徒生童话</name>
  11. <year>2004</year>
  12. <price>77</price>
  13. <language>English</language>
  14. </book>
  15. </bookstore>
以上是我们需要解析的xml文件,我们的目的是:通过Java获取xml文件的所有数据。

准备工作

准备工作:
  • (1)创建一个DocumentBuilderFactory对象
  • (2)创建一个DocumentBuilder对象
  • (3)通过DocumentBuilder对象的parse(String fileName)方法解析xml文件
  1. public class DomTest {
  2. public static void main(String[] args) {
  3. //(1)创建DocumentBuilderFactory对象
  4. DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
  5. try {
  6. //(2)创建DocumentBuilder对象
  7. DocumentBuilder db = dbf.newDocumentBuilder();
  8. //(3)通过DocumentBuilder对象的parse方法加载book.xml
  9. Document document = db.parse("books.xml");

  10. } catch (ParserConfigurationException e) {
  11. e.printStackTrace();
  12. } catch (SAXException e) {
  13. e.printStackTrace();
  14. } catch (IOException e) {
  15. e.printStackTrace();
  16. }
  17. }
  18. }

解析xml文件属性

技术分享
解析属性:
  • (1)Document类来获取节点集合
  • (2)遍历节点集合
  • (3)通过item(i)获取节点Node
  • (4)通过Node的getAttributes获取节点的属性集合
  • (5)遍历属性
  • (6)获取属性和属性名
  1. public class DomTest {
  2. public static void main(String[] args) {
  3. //创建DocumentBuilderFactory对象
  4. DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
  5. try {
  6. //创建DocumentBuilder对象
  7. DocumentBuilder db = dbf.newDocumentBuilder();
  8. //通过DocumentBuilder对象的parse方法加载book.xml
  9. Document document = db.parse("books.xml");
  10. //(1)获取所有book节点的集合
  11. NodeList booklist = document.getElementsByTagName("book");
  12. System.out.println("共有" + booklist.getLength() + "本书");
  13. System.out.println("-------------------------------------");
  14. //(2)遍历每个book节点
  15. for (int i = 0; i < booklist.getLength(); i++) {
  16. //(3)通过item(i)获取book节点,nodelist索引从0开始
  17. Node book = booklist.item(i);
  18. //(4)获取book节点的所有属性集合
  19. NamedNodeMap attrs = book.getAttributes();
  20. //获取属性的数量
  21. System.out.println("第" + (i + 1) + "本书有" + attrs.getLength() + "个属性");
  22. System.out.print("分别是:");
  23. //(5)遍历book的属性
  24. for (int j = 0; j < attrs.getLength(); j++) {
  25. //(6)获取属性
  26. Node att = attrs.item(j);
  27. //(6)获取属性的名称
  28. String attName = att.getNodeName();
  29. System.out.print(attName + ", ");
  30. }
  31. System.out.println();
  32. System.out.println("-------------------------------------");
  33. }
  34. } catch (ParserConfigurationException e) {
  35. e.printStackTrace();
  36. } catch (SAXException e) {
  37. e.printStackTrace();
  38. } catch (IOException e) {
  39. e.printStackTrace();
  40. }
  41. }
  42. }
打印结果:
  1. 共有2本书
  2. -------------------------------------
  3. 1本书有2个属性
  4. 分别是:id, type,
  5. -------------------------------------
  6. 2本书有1个属性
  7. 分别是:id,
  8. -------------------------------------

解析xml文件属性的子节点

解析子节点:
  • (1)使用getChildNodes()获取子节点集合
  • (2)遍历子节点
  • (3)获取子节点
  • (4)输出子节点名称和内容
  1. public class DomTest {
  2. public static void main(String[] args) {
  3. //创建DocumentBuilderFactory对象
  4. DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
  5. try {
  6. //创建DocumentBuilder对象
  7. DocumentBuilder db = dbf.newDocumentBuilder();
  8. //通过DocumentBuilder对象的parse方法加载book.xml
  9. Document document = db.parse("books.xml");
  10. //获取所有book节点的集合
  11. NodeList booklist = document.getElementsByTagName("book");
  12. System.out.println("共有" + booklist.getLength() + "本书");
  13. System.out.println("-------------------------------------");
  14. //遍历每个book节点
  15. for (int i = 0; i < booklist.getLength(); i++) {
  16. //通过item(i)获取book节点,nodelist索引从0开始
  17. Node book = booklist.item(i);
  18. //获取book节点的所有属性集合
  19. NamedNodeMap attrs = book.getAttributes();
  20. //获取属性的数量
  21. System.out.println("第" + (i + 1) + "本书有" + attrs.getLength() + "个属性");
  22. System.out.print("分别是:");
  23. //遍历book的属性
  24. for (int j = 0; j < attrs.getLength(); j++) {
  25. //获取属性
  26. Node att = attrs.item(j);
  27. //获取属性的名称
  28. String attName = att.getNodeName();
  29. System.out.print(attName + ", ");
  30. }
  31. System.out.println();
  32. System.out.println("子节点:");
  33. //(1)解析book节点的子节点
  34. NodeList bookChildNodes = book.getChildNodes();
  35. //(2)遍历bookChildNodes获取每个子节点
  36. for (int k = 0; k < bookChildNodes.getLength(); k++) {
  37. //(3)获取子节点
  38. Node bookChild = bookChildNodes.item(k);
  39. //注(a)
  40. //区分text类型的node以及element类型的node(子节点含我们不需要的文本型,所以我们要筛选)
  41. if (bookChild.getNodeType() == Node.ELEMENT_NODE) {
  42. //注(b)
  43. //(4)获取和输出节点名和节点内容
  44. //方法1:
  45. System.out.println(bookChild.getNodeName() + ", " + bookChild.getTextContent());
  46. //方法2:
  47. //System.out.println(bookChild.getNodeName() + ", " + bookChild.getFirstChild().getNodeValue());
  48. }
  49. }
  50. System.out.println("-------------------------------------");
  51. }
  52. } catch (ParserConfigurationException e) {
  53. e.printStackTrace();
  54. } catch (SAXException e) {
  55. e.printStackTrace();
  56. } catch (IOException e) {
  57. e.printStackTrace();
  58. }
  59. }
  60. }
打印结果:
  1. 共有2本书
  2. -------------------------------------
  3. 1本书有2个属性
  4. 分别是:id, type,
  5. 子节点:
  6. name, test冰与火之歌
  7. author, 乔治马丁
  8. year, 2014
  9. price, 89
  10. -------------------------------------
  11. 2本书有1个属性
  12. 分别是:id,
  13. 子节点:
  14. name, 安徒生童话
  15. year, 2004
  16. price, 77
  17. language, English
  18. -------------------------------------


技术分享 
注(a)解析时是把空白也算为文本型的子节点,如下看似只有4个子节点,算上空白会输出9个子节点
  1. <bookstroe>
  2. <book id="1">
  3. <name>冰与火之歌</name>
  4. <author>乔治马丁</author>
  5. <year>2014</year>
  6. <price>89</price>
  7. </book>
  8. </bookstroe
如上图所示,黄色和橙色也都算成了text类型的节点,这是我们不需要的,往往需要判断筛选。

技术分享
  1. <bookstroe>
  2. <book id="1">
  3. <name>冰与火之歌</name>
  4. <author>乔治马丁</author>
  5. <year>2014</year>
  6. <price>89</price>
  7. </book>
  8. </bookstroe>
注(b):假如此时我们想要获取<name>中的“冰与火之歌”
1)获取子节点的内容的时候,不是使用getNodeValue(),如上图,该方法只会返回null;我们要使用getTextContent()来获取两个标签中间的内容
2)另外,也可以使用获取这个子节点的子节点,之前有提到,text也被视为子节点,这里的“冰与火之歌”被视为<name>的子节点,所以获取子节点的子节点以后,再使用getNodeValue()才有意义,即先获取book的子节点<name>,再获取name的子节点;
3)这两种方法的区别
假如有<name><a>test</a>冰与火之歌</name>
getTextContext() --> test冰与火之歌(获取name下所有的文本并拼接起来)
getFirstChild().getNodeValue() --> null(获得子节点并输出其值)


如何在Java中保留xml数据的结构?

创建一个Book类,包含属性name、author、year、price等,在解析该xml的同时,就对该对象中的属性进行赋值。
当然,多个对象的时候,自然还需要存到集合中去。


附件:源码

技术分享
技术分享


来自为知笔记(Wiz)


附件列表

     

    02-Java是如何解析xml文件的(DOM)