博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java文件操作①——XML文件的读取
阅读量:6637 次
发布时间:2019-06-25

本文共 17613 字,大约阅读时间需要 58 分钟。

一、邂逅XML

文件种类是丰富多彩的,XML作为众多文件类型的一种,经常被用于数据存储和传输。所以XML在现今应用程序中是非常流行的。本文主要讲Java解析和生成XML。用于不同平台、不同设备间的数据共享通信。

XML文件的表现:以“.xml”为文件扩展名的文件;

   存储结构:树形结构;

 

节点名称区分大小写。

1、<book id="1"></book> id为属性, <book><id>1</id></book> id为节点

2、xml文件开头要加上版本信息和编码方式<?xml version="1.0" encoding="UTF-8"?>

 比如:

❤ 为什么要使用XML?

思考1:不同应用程序之间的通信?

思考2:不同平台间的通信?

思考3:不同平台间的数据共享?

答案就是我们要学习的XML文件。我们可以使用相同的xml把不同的文件联系起来

二、应用 DOM 方式解析 XML

❤ 在Java程序中如何获取XML文件的内容

解析的目的:获取节点名、节点值、属性名、属性值;

四种解析方式:DOM、SAX、DOM4J、JDOM 

DOM、SAX :java 官方方式,不需要下载jar包

DOM4J、JDOM :第三方,需要网上下载jar包

示例:解析XML文件,目标是解析XML文件后,Java程序能够得到xml文件的所有数据

思考:如何在Java程序中保留xml数据的结构?

 

如何保留节点之间的层级关系?

注意常用的节点类型:

 下面介绍DOM方式解析XML:

 功能说明:

代码示例:

1 package com.study.domtest; 2  3 import java.io.IOException; 4  5 import javax.xml.parsers.DocumentBuilder; 6 import javax.xml.parsers.DocumentBuilderFactory; 7 import javax.xml.parsers.ParserConfigurationException; 8  9 import org.w3c.dom.Document;10 import org.w3c.dom.NamedNodeMap;11 import org.w3c.dom.Node;12 import org.w3c.dom.NodeList;13 import org.xml.sax.SAXException;14 15 /**16  * DOM方式解析xml17  */18 public class DOMTest {19 20     public static void main(String[] args) {21         //1、创建一个DocumentBuilderFactory的对象22         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();23         //2、创建一个DocumentBuilder的对象24         try {25             //创建DocumentBuilder对象26             DocumentBuilder db = dbf.newDocumentBuilder();27             //3、通过DocumentBuilder对象的parser方法加载books.xml文件到当前项目下28             /*注意导入Document对象时,要导入org.w3c.dom.Document包下的*/29             Document document = db.parse("books.xml");//传入文件名可以是相对路径也可以是绝对路径30             //获取所有book节点的集合31             NodeList bookList = document.getElementsByTagName("book");32             //通过nodelist的getLength()方法可以获取bookList的长度33             System.out.println("一共有" + bookList.getLength() + "本书");34             //遍历每一个book节点35             for (int i = 0; i < bookList.getLength(); i++) {36                 System.out.println("=================下面开始遍历第" + (i + 1) + "本书的内容=================");37         //❤未知节点属性的个数和属性名时:38                 //通过 item(i)方法 获取一个book节点,nodelist的索引值从0开始39                 Node book = bookList.item(i);40                 //获取book节点的所有属性集合41                 NamedNodeMap attrs = book.getAttributes();42                 System.out.println("第 " + (i + 1) + "本书共有" + attrs.getLength() + "个属性");43                 //遍历book的属性44                 for (int j = 0; j < attrs.getLength(); j++) {45                     //通过item(index)方法获取book节点的某一个属性46                     Node attr = attrs.item(j);47                     //获取属性名48                     System.out.print("属性名:" + attr.getNodeName());49                     //获取属性值50                     System.out.println("--属性值" + attr.getNodeValue());51                 }52           //❤已知book节点有且只有1个id属性:53              /* 54               //前提:已经知道book节点有且只能有1个id属性55               //将book节点进行强制类型转换,转换成Element类型56               Element book1 = (Element) bookList.item(i);57               //通过getAttribute("id")方法获取属性值58               String attrValue = book1.getAttribute("id");59               System.out.println("id属性的属性值为" + attrValue);60               */61                 62              //解析book节点的子节点63                 NodeList childNodes = book.getChildNodes();64               //遍历childNodes获取每个节点的节点名和节点值65                 System.out.println("第" + (i+1) + "本书共有" + childNodes.getLength() + "个子节点");66                 for (int k = 0; k < childNodes.getLength(); k++) {67                   //区分出text类型的node以及element类型的node68                     if(childNodes.item(k).getNodeType() == Node.ELEMENT_NODE){69                       //获取了element类型节点的节点名70                         System.out.print("第" + (k + 1) + "个节点的节点名:" + childNodes.item(k).getNodeName());71                       //获取了element类型节点的节点值72                         System.out.println("--节点值是:" + childNodes.item(k).getFirstChild().getNodeValue());73 //                        System.out.println("--节点值是:" + childNodes.item(k).getTextContent());74                     }75                 }76                 System.out.println("======================结束遍历第" + (i + 1) + "本书的内容=================");77             }78 79         } catch (ParserConfigurationException e) {80             e.printStackTrace();81         } catch (SAXException e) {82             e.printStackTrace();83         } catch (IOException e) {84             e.printStackTrace();85         }86     }87 88 }

 三、应用 SAX 方式解析 XML

SAX是SIMPLE API FOR XML的缩写,与DOM比较而言,SAX是一种轻量型的方法。

Dom解析会将整个xml文件加载到内存中,然后再逐个解析

Sax解析是通过Handler处理类逐个依次解析每个节点

在处理DOM的时候,我们需要读入整个的XML文档,然后在内存中创建DOM树,生成DOM树上的每个NODE对象。当文档比较小的时候,这不会造成什么问题,但是一旦文档大起来,处理DOM就会变得相当费时费力。特别是其对于内存的需求,也将是成倍的增长,以至于在某些应用中使用DOM是一件很不划算的事。这时候,一个较好的替代解决方法就是SAX。 SAX在概念上与DOM完全不同。首先,不同于DOM的文档驱动,它是事件驱动的,也就是说,它并不需要读入整个文档,而文档的读入过程也就是SAX的解析过程。所谓事件驱动,是指一种基于回调(callback)机制的程序运行方法。在XMLReader接受XML文档,在读入XML文档的过程中就进行解析,也就是说读入文档的过程和解析的过程是同时进行的,这和DOM区别很大。

❤ 

代码示例:Book实体类

1 package com.study.saxtest.entity; 2  3 /** 4  * 用Book实体类代表XML文件中的"
...
"中整个元素 5 * 在遇到
标签,证明我们要存储新的book时需要创建Book对象 6 */ 7 public class Book { 8 private String id; 9 private String name;10 private String author;11 private String year;12 private String price;13 private String language;14 public String getId() {15 return id;16 }17 public void setId(String id) {18 this.id = id;19 }20 public String getName() {21 return name;22 }23 public void setName(String name) {24 this.name = name;25 }26 public String getAuthor() {27 return author;28 }29 public void setAuthor(String author) {30 this.author = author;31 }32 public String getYear() {33 return year;34 }35 public void setYear(String year) {36 this.year = year;37 }38 public String getPrice() {39 return price;40 }41 public void setPrice(String price) {42 this.price = price;43 }44 public String getLanguage() {45 return language;46 }47 public void setLanguage(String language) {48 this.language = language;49 }50 }

SAXParserHandler类:

1 package com.study.saxtest.handler;  2   3 import java.util.ArrayList;  4   5 import org.xml.sax.Attributes;  6 import org.xml.sax.SAXException;  7 import org.xml.sax.helpers.DefaultHandler;  8   9 import com.study.saxtest.entity.Book; 10  11 public class SAXParserHandler extends DefaultHandler{ 12     /*注意DefaultHandler是org.xml.sax.helpers包下的*/ 13      14     int bookIndex = 0;//设置全局变量,用来记录是第几本书 15      16     String value = null; 17     Book book = null; 18     private ArrayList
bookList = new ArrayList
();//保存book对象 19 20 public ArrayList
getBookList() { 21 return bookList; 22 } 23 24 /** 25 * 用来标识解析开始 26 */ 27 @Override 28 public void startDocument() throws SAXException { 29 super.startDocument(); 30 System.out.println("SAX解析开始"); 31 32 } 33 34 /** 35 * 用来标识解析结束 36 */ 37 @Override 38 public void endDocument() throws SAXException { 39 super.endDocument(); 40 System.out.println("SAX解析结束"); 41 } 42 43 /** 44 * 用来遍历xml文件的开始标签 45 * 解析xml元素 46 */ 47 @Override 48 public void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException { 49 //调用DefaultHandler类的startElement方法 50 super.startElement(uri, localName, qName, attributes); 51 if (qName.equals("book")) { 52 bookIndex++; 53 //创建一个book对象 54 /*Book*/ book = new Book(); 55 //开始解析book元素的属性 56 System.out.println("======================开始遍历第"+bookIndex+"本书的内容================="); 57 /* //❤已知节点的属性名时:比如已知id属性,根据属性名称获取属性值 58 String value = attributes.getValue("id"); 59 System.out.print("book的属性值是:"+value);*/ 60 //❤未知节点的属性名时,获取属性名和属性值 61 int num=attributes.getLength(); 62 for(int i=0;i

测试类:SAXTest

1 package com.study.saxtest.test; 2  3 import java.io.IOException; 4  5 import javax.xml.parsers.ParserConfigurationException; 6 import javax.xml.parsers.SAXParser; 7 import javax.xml.parsers.SAXParserFactory; 8  9 import org.xml.sax.SAXException;10 11 import com.study.saxtest.entity.Book;12 import com.study.saxtest.handler.SAXParserHandler;13 14 /**15  * sax方式解析XML16  */17 public class SAXTest {18 19     public static void main(String[] args) {20         //1.获取一个SAXParserFactory的实例对象21         SAXParserFactory factory = SAXParserFactory.newInstance();22         //2.通过factory的newSAXParser()方法获取一个SAXParser类的对象。23         try {24             SAXParser parser = factory.newSAXParser();25             //创建SAXParserHandler对象26             SAXParserHandler handler = new SAXParserHandler();27             parser.parse("books.xml", handler);28             System.out.println("~~~~~共有"+handler.getBookList().size()+"本书");29             for (Book book : handler.getBookList()) {30                 System.out.println(book.getId());31                 System.out.println(book.getName());32                 System.out.println(book.getAuthor());33                 System.out.println(book.getYear());34                 System.out.println(book.getPrice());35                 System.out.println(book.getLanguage());36                 System.out.println("----finish----");37             }38         } catch (ParserConfigurationException e) {39             e.printStackTrace();40         } catch (SAXException e) {41             e.printStackTrace();42         } catch (IOException e) {43             e.printStackTrace();44         }45     }46 47 }

 运行结果:

SAX解析开始======================开始遍历第1本书的内容=================book元素的第1个属性名是:id---属性值是:1节点名是:name---节点值是:冰与火之歌节点名是:author---节点值是:乔治马丁节点名是:year---节点值是:2014节点名是:price---节点值是:89======================结束遍历第1本书的内容=======================================开始遍历第2本书的内容=================book元素的第1个属性名是:id---属性值是:2节点名是:name---节点值是:安徒生童话节点名是:year---节点值是:2004节点名是:price---节点值是:77节点名是:language---节点值是:English======================结束遍历第2本书的内容=================SAX解析结束~~~~~共有2本书1冰与火之歌乔治马丁201489null----finish----2安徒生童话null200477English----finish----
View Code

 四、应用 DOM4J 及 JDOM 方式解析 XML

 # JDOM 方式解析 XML

  JDOM 开始解析前的准备工作:

  JDOM是第三方提供的解析XML方法,需要jdom-2.0.5.jar包

 

 示例代码:

1 package com.study.jdomtest1.test;  2   3 import java.io.FileInputStream;  4 import java.io.FileNotFoundException;  5 import java.io.IOException;  6 import java.io.InputStream;  7 import java.io.InputStreamReader;  8 import java.util.ArrayList;  9 import java.util.List; 10  11 import org.jdom2.Attribute; 12 import org.jdom2.Document; 13 import org.jdom2.Element; 14 import org.jdom2.JDOMException; 15 import org.jdom2.input.SAXBuilder; 16  17 import com.study.jdomtest1.entity.Book; 18  19 /** 20  *  JDOM 解析XML 21  */ 22 public class JDOMTest { 23     private static ArrayList
booksList = new ArrayList
(); 24 25 public static void main(String[] args) { 26 // 进行对books.xml文件的JDOM解析 27 //❤准备工作 28 // 1.创建一个SAXBuilder的对象 29 SAXBuilder saxBuilder = new SAXBuilder();//注意SAXBuilder是org.jdom2.input包下的 30 InputStream in; 31 try { 32 // 2.创建一个输入流,将xml文件加载到输入流中 33 in=new FileInputStream("books.xml");//如果将xml文件放在src/res包下,此时应该输入“src/res/books.xml” 34 InputStreamReader isr = new InputStreamReader(in, "UTF-8");//使用包装流InputStreamReader进行读取编码的指定,防止乱码 35 // 3.通过saxBuilder的build方法,将输入流加载到saxBuilder中 36 Document document = saxBuilder.build(isr); 37 // 4.通过document对象获取xml文件的根节点 38 Element rootElement = document.getRootElement(); 39 // 5.获取根节点下的子节点的List集合 40 List
bookList = rootElement.getChildren(); 41 //❤ 继续解析,采用for循环对bookList进行遍历 42 for (Element book : bookList) { 43 Book bookEntity = new Book(); 44 System.out.println("======开始解析第" + (bookList.indexOf(book) + 1) + "书======");//indexOf()返回的是index的位置,是从0开始 45 // 解析book的属性集合 46 List
attrList = book.getAttributes();//适用于未知属性情况下 47 /*//知道节点下属性名称时,获取节点值 48 book.getAttributeValue("id");*/ 49 // 遍历attrList(针对不清楚book节点下属性的名字及数量) 50 for (Attribute attr : attrList) { 51 /**注:JDom中,Attribute的getName和getValue方法获取到的都是实际的名称和值, 52 * 不会出现SAX和DOM中的空格和换行的情况*/ 53 // 获取属性名 54 String attrName = attr.getName(); 55 // 获取属性值 56 String attrValue = attr.getValue(); 57 System.out.println("属性名:" + attrName + "----属性值:" + attrValue); 58 if (attrName.equals("id")) { 59 bookEntity.setId(attrValue); 60 } 61 } 62 63 //❤对book节点的子节点的节点名以及节点值的遍历 64 List
bookChilds = book.getChildren(); 65 for (Element child : bookChilds) { 66 System.out.println("节点名:" + child.getName() + "----节点值:" + child.getValue()); 67 if (child.getName().equals("name")) { 68 bookEntity.setName(child.getValue()); 69 } 70 else if (child.getName().equals("author")) { 71 bookEntity.setAuthor(child.getValue()); 72 } 73 else if (child.getName().equals("year")) { 74 bookEntity.setYear(child.getValue()); 75 } 76 else if (child.getName().equals("price")) { 77 bookEntity.setPrice(child.getValue()); 78 } 79 else if (child.getName().equals("language")) { 80 bookEntity.setLanguage(child.getValue()); 81 } 82 83 } 84 System.out.println("======结束解析第" + (bookList.indexOf(book) + 1) + "书======"); 85 booksList.add(bookEntity); 86 bookEntity = null; 87 //测试数据 88 System.out.println(booksList.size()); 89 System.out.println(booksList.get(0).getId()); 90 System.out.println(booksList.get(0).getName()); 91 92 } 93 } catch (FileNotFoundException e) { 94 e.printStackTrace(); 95 } catch (JDOMException e) { 96 e.printStackTrace(); 97 } catch (IOException e) { 98 e.printStackTrace(); 99 }100 }101 102 }

注意:

❤关于 JDOM 使用过程中 JAR 包的引用 :

方式1:通过右击项目-->build path-->add external archives...-->然后选择本地文件的jar包

这种方式并不能将jar包真正导入到项目源码中,当把项目导出放在另外的机器上,这个jar包并不会随着project一同被导出。

如图:

方式2:项目根目录下新建lib文件夹——复制、粘帖jar包——右击jar包选择“build path构建路径”——“add to build path添加至构建路径”即可

如图:

  # DOM4J 方式解析 XML 

  DOM4J 是第三方提供的解析XML方法,需要dom4j-1.6.1.jar包

示例:

1 package com.study.dom4jtest; 2  3 import java.io.File; 4 import java.util.Iterator; 5 import java.util.List; 6  7 import org.dom4j.Attribute; 8 import org.dom4j.Document; 9 import org.dom4j.DocumentException;10 import org.dom4j.Element;11 import org.dom4j.io.SAXReader;12 13 /**14  * DOM4J 方式解析XML15  */16 public class DOM4JTest {17 18     public static void main(String[] args) {19         // 解析books.xml文件20         // 创建SAXReader的对象reader21         SAXReader reader = new SAXReader();22         try {23             // 通过reader对象的read方法加载books.xml文件,获取docuemnt对象。24             Document document = reader.read(new File("books.xml"));25             // 通过document对象获取根节点bookstore26             Element bookStore = document.getRootElement();27             // 通过element对象的elementIterator方法获取迭代器28             Iterator it = bookStore.elementIterator();29             // 遍历迭代器,获取根节点中的信息(书籍)30             while (it.hasNext()) {31              System.out.println("=====开始遍历某一本书=====");32              Element book = (Element) it.next();33              // 获取book的属性名以及 属性值34              List
bookAttrs = book.attributes();35 for (Attribute attr : bookAttrs) {36 System.out.println("属性名:" + attr.getName() + "--属性值:" + attr.getValue());37 }38 //解析子节点的信息39 Iterator itt = book.elementIterator();40 while (itt.hasNext()) {41 Element bookChild = (Element) itt.next();42 System.out.println("节点名:" + bookChild.getName() + "--节点值:" + bookChild.getStringValue());43 }44 System.out.println("=====结束遍历某一本书=====");45 }46 47 } catch (DocumentException e) {48 e.printStackTrace();49 }50 }51 52 }

五、四种解析方式比较分析

基础方法:DOM(平台无关的官方解析方式)、SAX(基于事件驱动的解析方式)

扩展方法:JDOM、DOM4J(在基础的方法上扩展出的,只有在java中能够使用的解析方法)

##解析速度的分析 

 

XML四种解析方式性能测试:

SAX>DOM>DOM4J>JDOM

JUnit是Java提供的一种进行单元测试的自动化工具。测试方法可以写在任意类中的任意位置。使用JUnit可以没有main()入口进行测试。

DOM4J在灵活性和对复杂xml的支持上都要强于DOM
DOM4J的应用范围非常的广,例如在三大框架的Hibernate中是使用DOM4J的方式解析文件的。
DOM是w3c组织提供的一个官方解析方式,在一定程度上是有所应用的。
当XML文件比较大的时候,会发现DOM4J比较好用
1.JUnit:Java提供的单元测试;@Test注解;采用JUnit不需要程序入口main方法
2.性能测试结果:几kB的xml文件;建议使用DOM4J解析
  DOM-33ms
  SAX-6ms
  JDOM-69ms
  DOM4J-45ms
工程右键build path --Add library--JUnit单元测试 --version:JUnit4
  DOM:33,SAX:6
  JDOM:69;DOM4J:45
  DOM 有可能溢出
多使用DOM4J

转载于:https://www.cnblogs.com/Qian123/p/5231303.html

你可能感兴趣的文章
吉软—Java-Css+Div 实现导航
查看>>
jquery banner 轮播配置方法
查看>>
Linux 关机前执行脚本
查看>>
Java 基础数据类型 、 == 、 equals
查看>>
通俗易懂的 Npm 入门教程
查看>>
深入理解jQuery中live与bind方法的区别
查看>>
推荐一款不错的jquery时间控件(强大的处理事务性)
查看>>
不同系统下的回车\r和换行\n,及其历史
查看>>
Spring boot + io.springfox Swagger2 统一添加header 参数的方法:globalOperationParameters
查看>>
Java 复习 —— 一张图读懂多线程
查看>>
postgresql备份恢复之pg_dump大数据处理
查看>>
百万级数据下的mysql深度解析
查看>>
package-info.java——简介
查看>>
JavaScript 在数组指定位置插入元素
查看>>
URL匹配设计考
查看>>
使用hugo制作基于md文档的静态网站
查看>>
第四章-java多线程核心技术-Lock锁-第一篇
查看>>
运维监控工具选择
查看>>
HttpClient基本用法
查看>>
浮点数的负零
查看>>