本文转载自:http://www.cnblogs.com/Qian123/p/5231303.html
Java文件操作①——XML文件的读取
一、邂逅XML
文件种类是丰富多彩的,XML作为众多文件类型的一种,经常被用于数据存储和传输。所以XML在现今应用程序中是非常流行的。本文主要讲Java解析和生成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
四种解析方式: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方式解析xml 17 */ 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类型的node 68 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文件中的"<book>...</book>"中整个元素 5 * 在遇到<book>标签,证明我们要存储新的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类:
测试类: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方式解析XML 16 */ 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 冰与火之歌 乔治马丁 2014 89 null ----finish---- 2 安徒生童话 null 2004 77 English ----finish----
四、应用 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<Book> booksList = new ArrayList<Book>(); 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<Element> 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<Attribute> 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<Element> 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 }