第四章. XML与Json文件处理
1. XML简介
1.1 XML(eXtensible Markup Language)
:是一种数据存储格式
- 可扩展标记语言:数据 + 含义
- 标签可自行定义,具有自我描述性
- 纯文本表示,跨系统/平台/语言
常规语法
- 任何的起始标签都必须有一个结束标签。
- 大小写敏感,如<name>和<Name>不一样。
- 所有标签的属性都必须有值,且在值的周围加上引号。
- 注释:<!-- 注释内容 -->
<bookstore>
<book category="CHILDREN">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category="WEB">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>
即:
1.2 XML Schema(XSD,XML Schema Definition)
– 定义 XML 文档的结构
– 支持数据类型,可扩展,功能更完善、强大
– 采用xml编写
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.w3school.com.cn"
xmlns="http://www.w3school.com.cn"
elementFormDefault="qualified">
<xs:element name="note">
<xs:complexType>
<xs:sequence>
<xs:element name="to" type="xs:string"/>
<xs:element name="from" type="xs:string"/>
<xs:element name="heading" type="xs:string"/>
<xs:element name="body" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
2.XML处理
XML解析方法
- 树结构
• DOM: Document Object Model 文档对象模型,擅长(小规模)读/写 - 流结构
• SAX: Simple API for XML 流机制解释器(推模式),擅长读
• Stax: The Streaming API for XML 流机制解释器(拉模式),擅长读,
2.1 XML解析(DOM)
:DOM
– 其处理方式是将 XML 整个作为类似树结构的方式读入内存中以便操作及解析,方便修改。
– 解析大数据量的 XML 文件,会遇到内存泄露及程序崩溃的风险。
主要类:DOM类
• DocumentBuilder 解析类,parse方法
• Node 节点主接口,getChildNodes返回一个NodeList
• NodeList 节点列表,每个元素是一个Node
• Document 文档根节点
• Element 标签节点元素 (每一个标签都是标签节点)
• Text节点 (包含在XML元素内的,都算Text节点)
• Attr节点(每个属性节点)
2.2 XML解析(SAX)
Simple API for XML
- 推模型。当它每发现一个节点就引发一个事件,而我们需要编写这些事件的处理程序。(继承DefaultHandler)
- 采用事件/流模型来解析 XML 文档,更快速、更轻量。
- 有选择的解析和访问,不像 DOM 加载整个文档,内存要求较低。
– SAX 对 XML 文档的解析为一次性读取,不创建/不存储文档对象,很难同时访问文档中的多处数据。
关键类:org.xml.sax
2.3 XML解析(Stax)
Streaming API for XML
- 流模型中的拉模型
- 在遍历文档时,会把感兴趣的部分从读取器中拉出,不需要引发
事件,允许我们选择性地处理节点。这大大提高了灵活性,以及
整体效率。
两套处理API
• 基于指针的API, XMLStreamReader
• 基于迭代器的API,XMLEventReader
基于指针的API:XMLStreamReader
package xml.stax;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.Iterator;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
public class StaxReader {
public static void main(String[] args) {
StaxReader.readByStream();
System.out.println("========华丽丽的分割线==========");
StaxReader.readByEvent();
}
//流模式
public static void readByStream() {
String xmlFile = "books.xml";
XMLInputFactory factory = XMLInputFactory.newFactory();
XMLStreamReader streamReader = null;
try {
streamReader = factory.createXMLStreamReader(new FileReader(xmlFile));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (XMLStreamException e) {
e.printStackTrace();
}
// 基于指针遍历
try {
while (streamReader.hasNext()) {
int event = streamReader.next();
// 如果是元素的开始
if (event == XMLStreamConstants.START_ELEMENT) {
// 列出所有书籍名称
if ("title".equalsIgnoreCase(streamReader.getLocalName())) {
System.out.println("title:" + streamReader.getElementText());
}
}
}
streamReader.close();
} catch (XMLStreamException e) {
e.printStackTrace();
}
}
DOM/SAX/Stax是JDK自带的解析功能。
• 第三方库
– JDOM: www.jdom.org
– DOM4J: dom4j.github.io
• 第三方库一般都包含DOM,SAX等多种方式解析,是对Java
解析进行封装。
3.Json
JSON:一种数据存储交换格式
- JavaScript Object Notation, JS 对象表示法
- 类似XML,更小、更快、更易解析
- 尽管使用Javascript语法,但是独立于编程语言
JSONObject
- 名称/值对。如"firstName":“John”
– JSON对象:{“name":“Jo”,“email”:“a@b.com”}
– 数据在键值对中
– 数据由逗号分隔
– 花括号保存对象
JSON数组
- 方括号保存数组
[{“name":“Jo”,“email”:“a@b.com”}, {“name":“Jo”,“email”:“a@b.com”}]
JSON 主要用途
- JSON生成
- JSON解析
20 JSON校验 - 和Java Bean对象进行互解析
– 具有一个无参的构造函数
– 可以包括多个属性,所有属性都是private
– 每个属性都有相应的Getter/Setter方法
Java的JSON处理(主要类库)
- org.json:JSON官方推荐的解析类
– 简单易用,通用性强
– 复杂功能欠缺 - GSON:Google出品
– 基于反射,可以实现JSON对象、JSON字符串和Java对象互转 - Jackson:号称最快的JSON处理器
– 简单易用,社区更新和发布速度比较快
GSON:
import java.io.File;
import java.io.FileReader;
import java.util.Arrays;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
/**
* 采用Google GSON来处理JSON
* @author Tom
*
*/
public class GsonTest {
public static void main(String[] args) {
testJsonObject();
System.out.println("=========华丽丽的分割线==============");
testJsonFile();
}
public static void testJsonObject() {
//构造对象
Person p = new Person();
p.setName("Tom");
p.setAge(20);
p.setScores(Arrays.asList(60,70,80));
//从Java对象到JSON字符串
Gson gson = new Gson();
String s = gson.toJson(p);
System.out.println(s); //{"name":"Tom","age":20,"scores":[60,70,80]}
//从JSON字符串到Java对象
Person p2 = gson.fromJson(s, Person.class);
System.out.println(p2.getName()); //Tom
System.out.println(p2.getAge()); //20
System.out.println(p2.getScores());//[60, 70, 80]
//调用GSON的JsonObject
JsonObject json = gson.toJsonTree(p).getAsJsonObject(); //将整个json解析为一颗树
System.out.println(json.get("name")); //"Tom"
System.out.println(json.get("age")); //20
System.out.println(json.get("scores"));//[60,70,80]
}
public static void testJsonFile() {
Gson gson = new Gson();
File file = new File("books2.json");
try (FileReader reader = new FileReader(file)) {
List<Book> books = gson.fromJson(reader, new TypeToken<List<Book>>(){}.getType());
for(Book book : books)
{
System.out.println(book.getAuthor() + ", " + book.getTitle());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}