天天看点

XML、JSON、DOM、DOM4J

XML&JSON

理解XML概念及优势

会编写格式良好的XML文档

会使用DOM操作XML数据

显示/添加/保存

掌握JSON的定义

会使用FastJson生成、解析JSON

XML是什么

XML(EXtensible Markup Language)

可扩展标记语言

特点

XML与操作系统、编程语言的开发平台无关

实现不同系统之间的数据交换

作用

数据交互

配置应用程序和网站

Ajax基石

知道XML的文档结构
	声明
	文档元素描述信息(文档结构)
	
初步了解XML的文档结构
	XML文档内容由一系列标签元素组成
		语法:<元素名 属性名="属性值">元素内容</元素名>
		空元素:
			<name></name>
			<name></name>
			<name/>
	属性值引号包裹
	一个元素可以有多个属性
	属性值中不能直接包含<、&
	不建议使用的字符:"、'、>
	
掌握XML中元素属性的定义注意事项
<?xml version="1.0" encoding="UTF-8"?>
<books>
	<!--图书信息-->
	<book id = "b001">
		<title>图书1</title>
		<author>zzx</author>
	</book>
	<book id = "b002">
		<title>图书2</title>
		<author>gyy</author>
	</book>
	<book>
		<!--空元素-->
	</book>
</books>
           

总结

XML:可扩展标记语言。被用来传输和存储数据

XML文档由声明及文档元素描述信息构成

一个元素可以有多个属性

属性值不能使用及不建议使用的字符可自行编写观看结果

编写格式良好的XML

思考

XML文档元素属性值中不能直接包含<、&

不建议使用的字符:"、’、>

掌握XML中常用的转义符
	XML中的转义符列表
		符号		转义符(预定义实体)
		<			&|t;
		>			&gt;
		"			&quot;
		'			&apos;
		&			&amp;
	当元素出现很多特殊字符时,可以使用CDATA节,CDATA是
		不应该由XML解析器解析的文本数据。如:
	<description>
		<![CDATA[讲解了元素<title>以及<title>的使用]]>
	</description>
		<?xml version="1.0" encoding="UTF-8"?>
		<books>
			<!--图书信息-->
			<book id = "b001" width = "&lt;20">
				输出第一部&lt;book&gt;&lt;/book&gt;图书信息
				<title>图书1</title>
				<author>zzx</author>
			</book>
			<book id = "b002">
				<![CDATA[输出第二部<book></book>图书信息]]>
				<title>图书2</title>
				<author>gyy</author>
			</book>
			<book>
				<!--空元素-->
			</book>
		</books>
		
掌握XML编写注意事项
	注意事项
		所有XML元素都必须有结束标签
		XML标签对大小写敏感
		XML必须正确的嵌套
		同级标签以缩进对齐
		元素的名称可以包含字母、数字或其他字符
		元素名称不能以数字或者标点符号开始
		元素名称中不能含空格
		起名称见名知意
           

编写格式良好的XML练习

练习1:编写XML文档

衣服型号 对应身高

S 身高<165

M 165<身高<170

L 170<身高<175

XL 175<身高<180

XXL 180<身高<185

<?xml version="1.0" encoding="UTF-8"?>

S

M

L

XL

XXL

练习2:编写XML表示学生成绩
学生姓名	预计得分	实际得分
王显明		75			80
宋佳		75			88
<?xml version="1.0" encoding="UTF-8"?>
<studentScores>
	<!--存储学生的预期得分和实际得分-->
	<student>
		<name>王显明</name>
		<expectedScore>78</expectedScore>
		<score>88</score>
	</student>
	<student name="宋佳" expectedSocre="80" socre="90"></student>
</studentScores>
           

XML命名空间

了解XML命名空间的作用

在XML中,元素名称是由开发者定义的,当两个不同文档使用相同的元素名时,就会发生命名冲突

使用前缀避免命名冲突

使用XML命名空间

解决在复杂、大型XML文件中出现名称相同,但是含义不同的元素

我们还可以在一个文档中定义多个命名空间

了解XML命名空间的写法
	默认命名空间
		没有指定前缀的命名空间就会作为页面中元素的默认命名空间
		除非在标签中使用其他命名空间的前缀,否则解析器都会认为元素在默认空间下存在
		一个文档中只能有一个默认的命名空间
           

总结

XML命名空间

解决在复杂、大型XML文件中出现名称相同,但是含义不同的元素

XMLns:前缀

DOM解析XML

了解XML解析技术

DOM

基于XML文档树结构的解析

适用于多次访问的XML文档

特点:比较消耗资源

DOM4J

非常优秀的Java XML API

性能优异、功能强大

开放源代码

SAX

基于事件的解析

适用于大数据的XML文档

特点:占用资源少

掌握DOM解析XML的原理
	DOM介绍
		文档对象模型(Document Object Model)
		DOM把XML文档映射成一个倒挂的树
		元素节点、文本节点、属性节点
	
掌握常用的DOM解析API名称及作用
	DOM解析包:org.w3c.dom
	常用接口						常用方法									说明
	Document:表示整个XML文档		NodeList getElementsByTagName(String Tag)	按文档顺序返回文档中指定标记名称的所有元素集合
									Element createElement(String tagName)		创建指定标记名称的元素
	Node:该文档数中的单个节点		NodeList getChildNodes()					获取该元素的所有子节点,返回节点集合
	Element:XML文档中的一个元素	String getTagName()							获取元素名称
           

获取Document

掌握DOM解析XML的步骤

1、创建解析器工厂对象

2、解析器工厂对象创建解析器对象

3、解析器对象指定XML文件创建Document对象

4、以Document对象为起点操作DOM树

通过代码能获取Document对象
<?xml version="1.0" encoding="UTF-8"?>
<PhoneInfo>
	<Brand name="华为">
		<Type name="Mate 30 Pro"/>
		<Type name="P30 Pro"/>
		<Type name="nova 6"/>
	</Brand>
	<Brand name="苹果">
		<Type name="iPhone11 Pro"/>
	</Brand>
</PhoneInfo>
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
public class ParseXMLDemo {
//全局变量:Document对象
Document document = null;

//解析XML文件获取相应Document对象
public void getDocument(){
    //解析器工厂(DocumentBuilderFactory)
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    try {
        //解析器(DocumentBuilder)
        DocumentBuilder builder = factory.newDocumentBuilder();
        //解析相应XML文件获得Document对象
        document = builder.parse("PhoneInfo.xml");
    } catch (ParserConfigurationException e) {
        e.printStackTrace();
    } catch (SAXException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
           

总结

DOM解析XML步骤通过代码记忆

解析器工厂-解析器-Document对象

获取手机信息

通过对DOM树的操作,实现手机品牌和型号的获取

需求说明

显示“收藏信息.xml”文件中收藏的手机品牌和型号

代码

//获取手机品牌

public void showInfo(){

//获取手机品牌

NodeList brand = document.getElementsByTagName(“Brand”);

//循环获取每一个手机品牌节点

for (int i = 0; i < brand.getLength(); i++) {

Node node = brand.item(i);

//把品牌节点转换为品牌元素

Element element = (Element)node;

//获取每个品牌元素的name属性

System.out.println(element.getAttribute(“name”));

//获得每个品牌节点下面的子节点(型号)
				NodeList types = element.getChildNodes();
				for (int j = 0; j < types.getLength(); j++) {
					Node typeNode = types.item(j);
					//判断型号节点是否为元素,如果是ELEMENT_NODE,再转换为Element
					if (typeNode.getNodeType()==Node.ELEMENT_NODE){
						//把型号节点转换为型号元素
						Element element1 = (Element)typeNode;
						//获取型号元素的name属性
						System.out.println(" "+element1.getAttribute("name"));
					}
				}
			}
		}

		public static void main(String[] args) {
			ParseXMLDemo parseXMLDemo = new ParseXMLDemo();
			parseXMLDemo.getDocument();
			parseXMLDemo.showInfo();
		}
           

添加手机信息

需求说明

为“收藏信息.xml”文件添加新的手机品牌和型号

三星-Galaxy Fold

Document-createElement()

Node-appendChild()

代码

//添加新的节点

//

//

//

public void add(){

//创建新的品牌节点

Element element = document.createElement(“Brand”);

//为品牌节点创建name属性:

element.setAttribute(“name”,“三星”);

//创建新的型号节点

Element element1 = document.createElement(“Type”);

//为型号节点创建name属性:

element1.setAttribute(“name”,“Galaxy Fold”);

//把型号节点作为品牌节点的子节点加进去

element.appendChild(element1);

//把三星新的品牌节点(带有子节点型号的-Galaxy Fold)加到根元素中去

document.getElementsByTagName(“PhoneInfo”).item(0).appendChild(element);

}

总结

Document-createElement()

Node-appendChild()

保存手机信息

思考:DOM树增加节点后,XML文件是否更新了?

保存XML文件

步骤

获取TransformerFactory对象

创建Transformer对象

设置输出属性

创建DOMSource对象

包含XML信息

创建StreamResult对象

包含保存文件的信息

将XML保存到指定文件中

代码

//保存XML–>path:目的地

public void saveXMl(String path){

//转换器工厂

TransformerFactory factory = TransformerFactory.newInstance();

try {

//转换器

Transformer transformer = factory.newTransformer();

//设置输出格式(编码、缩进)

//transformer.setOutputProperty(OutputKeys.ENCODING,“gb2312”);

transformer.setOutputProperty(OutputKeys.INDENT,“yes”);

transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount",“4”);

//源

DOMSource source = new DOMSource(document);

//目的

StreamResult result = new StreamResult(new File(path));

//完成XML保存

transformer.transform(source,result);

} catch (TransformerConfigurationException e) {

e.printStackTrace();

} catch (TransformerException e) {

e.printStackTrace();

}

}

认识JSON

了解什么是JSON

JSON(JavaScript Object Notation)

轻量级的文本数据交换格式

具有自我描述性

比XML传输速度快

JOSN最初用来表示JavaScript中的对象,但目前已独立于JavaScript,成为最常用的数据格式之一
	
掌握JSON的语法规则
	两种数据结构:对象和数组
		大括号内为对象
		中括号内为数组
	对象中的数据由名称/值对构成
		值的类型可为字符串、数字、布尔值、null、数组、对象
		数据之间由逗号分隔
	数组中的数据类型同名称/值对中值的类型
	
了解JSON解析框架Fastjson
	http://central.maven.org/maven2/com/alibaba/fastjson
           

总结

JSON是一种轻量级的文本数据交换格式

JSON两种数据结构:对象和数组

JSON解析框架:阿里开源的Fastjson

Fastjson解析JSON

掌握Fastjson解析JSON

Java对象转为JSON字符串

JSON字符串转为Java对象

需求

实现学员对象和JSON字符串的互相转换

代码

import com.alibaba.fastjson.JSON;

import java.util.ArrayList;

import java.util.List;

//完成学员对象和JSON字符串的互相转换
		public class FastJSONDemo {
			public static void main(String[] args) {
				//Java对象(学员对象)-->JSON字符串
				List<String> skills = new ArrayList<>();
				skills.add("java");
				skills.add("hadoop");
				skills.add("Python");
				Student student = new Student("Jason",20,skills);

				String stuJSON = JSON.toJSON(student).toString();
				System.out.println(stuJSON);
				//JSON字符串-->Java对象
				String json = "{\"skills\":[\"java\",\"hadoop\",\"Python\"],\"name\":\"Jason\",\"age\":20}";
				Student stu = JSON.parseObject(json,Student.class);
				System.out.println("转化为学生对象:"+stu.getName()+"-"+stu.getAge()+"-"+stu.getSkills());
			}
		}
           

总结

XML

可扩展标记语言

编写格式良好的XML文档

使用DOM操作XML数据

显示/添加/保存

JSON

轻量级的文本数据交换格式

会使用FastJson生成、解析JSON

JSON和XML的比较
	可读性
		JSON和XML的可读性可谓不相上下,一边是简易的语法,一边是规范的标签形式,很难分出胜负。
	可扩展性
		XML天生有很好的扩展性,JSON当然也有,没有什么是XML可以扩展而JSON却不能扩展的。
		不过JSON在Javascript主场作战,可以存储Javascript复合对象,有着xml不可比拟的优势。
	编码难度
		XML有丰富的编码工具,比如Dom4j、JDom等,JSON也有提供的工具。无工具的情况下,
		相信熟练的开发人员一样能很快的写出想要的xml文档和JSON字符串,不过,xml文档要多很多结构上的字符。
	解码难度
		XML的解析方式有两种:
		一是通过文档模型解析,也就是通过父标签索引出一组标记。
		例如:xmlData.getElementsByTagName("tagName"),但是这样是要在预先知道文档结构的情况下使用,无法进行通用的封装。
		另外一种方法是遍历节点(document 以及 childNodes)。
		这个可以通过递归来实现,不过解析出来的数据仍旧是形式各异,往往也不能满足预先的要求。

XML扩展
           

会使用DOM操作XML数据(修改/删除)

会使用DOM4J操作XML数据

DOM操作XML-修改

需求说明

给所有Brand标签添加id属性

思路分析

获取Brand标签

调用setAttribute()方法添加属性

代码

//实现XML节点的修改:Brand标签添加一个id属性

public void update(){

//获取所有的Brand元素

NodeList brands = document.getElementsByTagName(“Brand”);

for (int i = 0; i < brands.getLength(); i++) {

Node brand = brands.item(i);

Element elebrand = (Element)brand;

//为每一个Brand元素设置id属性

elebrand.setAttribute(“id”,i+"");

}

//保存XML文件

this.saveXMl(“new.xml”);

}

总结

信息修改

getElementsByTagName()

setAttribute()

注意:修改DOM节点后,需调用XML文件更新的方法

DOM操作XML-删除

通过DOM操作XML,实现手机信息删除

需求说明

删除Brand值为“华为”的标签

getElementsByTagName()方法获取Brand标签列表

获得Brand值为“华为”的标签对象

通过getParentNode()方法获得父节点对象

调用父节点的removeChild()方法删除节点

代码

//实现XML节点的删除,删除所有Brand为华为的节点(元素)

public void delete(){

NodeList brands = document.getElementsByTagName(“Brand”);

//遍历所有的Brand节点,找出华为元素

for (int i = 0; i < brands.getLength(); i++) {

Node brand = brands.item(i);

Element elebrand = (Element)brand;

if (elebrand.getAttribute(“name”).equals(“华为”)){

elebrand.getParentNode().removeChild(elebrand);

}

}

//保存XML

this.saveXMl(“new.xml”);

}

总结

信息删除

getElementsByTagName()

getParentNode()

removeChild()

注意:删除DOM节点后,需调用XML文件更新的方法

DOM4J解析XML

解析XML技术

DOM

基于XML文档树结构的解析

适用于多次访问的XML文档

特点:比较消耗资源

DOM4J
		非常优秀的Java XML API
		性能优异、功能强大
		开放源代码
	SAX
		基于事件的解析
		适用于大数据的XML文档
		特点:占用资源少,内存消耗小

了解什么是DOM4J解析XML
	Document接口:定义XML文档
	Element接口:定义XML元素
	Text接口:定义XML文本节点
	Attribute接口:定义了XML的属性
	
下载DMO4J
	http://dom4j.github.io
	
下载DMO4J常用的API及其作用
           

显示手机收藏信息

使用DOM4J解析XML的方式,显示手机信息

代码

import org.dom4j.Document;

import org.dom4j.DocumentException;

import org.dom4j.Element;

import org.dom4j.io.SAXReader;

import java.io.File;
	import java.util.Iterator;

	//借助DOM4J方式来解析信息
	public class DOM4JXML {
		//全局Document
		Document document = null;

		//获取Document对象,为全局Document赋值
		public void getDocument(){
			//通过解析器解析XML文件,获取Document
			SAXReader saxReader = new SAXReader();
			try {
				document = saxReader.read(new File("PhoneInfo.xml"));
			} catch (DocumentException e) {
				e.printStackTrace();
			}
		}

		//显示手机信息(品牌,信息)
		public void showPhoneInfo(){
			//获取根节点
			Element root = document.getRootElement();
			//获取根节点下面的子节点(Brand),并进行遍历
			for (Iterator itBrand = root.elementIterator();itBrand.hasNext();) {
				Element brand = (Element) itBrand.next();//遍历迭代器中的每一个Brand节点
				//显示品牌:brand的name属性
				System.out.println("品牌:"+brand.attributeValue("name"));
				//获取品牌下的手机型号
				for (Iterator itType = brand.elementIterator();itType.hasNext();){
					Element type = (Element) itType.next();//遍历迭代器中的每一个Brand节点
					System.out.println("\t型号:"+type.attributeValue("name"));
				}
			}
		}

		public static void main(String[] args) {
			DOM4JXML dom4JXML = new DOM4JXML();
			dom4JXML.getDocument();
			dom4JXML.showPhoneInfo();
		}
	}
           

总结

使用DOM4J解析XML的方式,显示手机信息

SAXReader的read()

getRootElement()

elementIterator()

attributeValue()

添加手机信息

使用DOM4J解析XML的方式,添加手机信息

代码

public void add(){

//获取XML根节点

Element root = document.getRootElement();

//为根节点添加一个Brand元素,name属性赋值为三星

Element brand = root.addElement(“Brand”);

brand.addAttribute(“name”,“三星”);

//为brand元素添加Type元素,Type元素name属性赋值Galaxy Fold

Element type = brand.addElement(“Type”);

type.addAttribute(“name”,“Galaxy Fold”);

}

总结

使用DOM4J解析XML的方式,添加手机信息

getRootElement()

addElement()

addAttribute()

保存手机信息

XMLWrite(转换器)

write document

OutputFormat(指定输出格式)

createPrettyPrint()

setEncoding()

代码

//保存XML

public void saveXML(String path) throws IOException {

//输出保存时的格式(如编码等)

OutputFormat format = OutputFormat.createPrettyPrint();

//format.setEncoding(“GBK”);

//创建一个XMLWrite对象(等同于DOM解析器中的转化器)

XMLWriter writer = new XMLWriter(new FileWriter(path),format);

writer.write(document);

writer.close();

}

修改手机信息

需求说明

为Brand元素设置id属性

getRootElement()

elementIterator()

addAttribute()

代码

//修改手机信息,为Brand元素设置id属性

public void update() throws IOException {

//获取XML的根元素

Element root = document.getRootElement();

int id = 0;

//获取根元素下面的所有Brand子元素,遍历

for (Iterator itBrands = root.elementIterator();itBrands.hasNext()😉{

Element brand = (Element)itBrands.next();

//为Brand元素设置id属性

id++;

brand.addAttribute(“id”,id+"");

}

//保存XML

this.saveXML(“new1.xml”);

}

删除手机信息

需求说明

删除品牌“华为”的手机

getRootElement()

elementIterator()

attributeValue()

getParent()

remove()

代码
	//删除手机信息,删除品牌“华为”的手机
	public void delete() throws IOException {
		//获得XML的根元素
		Element root = document.getRootElement();
		//获取所有的Brand子元素,遍历
		for (Iterator itBrands = root.elementIterator();itBrands.hasNext();) {
			Element brand = (Element)itBrands.next();
			//判断Brand的name属性是否为华为,如果是,则删除
			if (brand.attributeValue("name").equals("华为")) {
				//由父节点删除
				brand.getParent().remove(brand);
			}
		}
		//保存XML文件
		this.saveXML("new1.xml");
	}