B站相关课程链接:https://www.bilibili.com/video/BV1hJ411C7Zd?t=2.2
一.XML是什么
1.什么是XML:
extensible matkup language (可拓展的 标记 语言)
html 超文本标记语言 做网页 -> 目的:表现和展示数据
2.XML语言(文件)的作用:
①存储数据:xml文件
手机中的单机游戏中的等级,装备等数据记录在哪?
数据库太大,一般用于网络游戏中,例如将数据打包并通过远程访问将数据包传到服务器的数据库里面
普通文件,io流的读取速度太慢
所以,采用xml文件保存软件的数据
②传输数据:网络上传递数据
网络游戏一般通过数据包传递数据,并发量比较小,数据比较少
而像一些购物平台,比如京东,淘宝等,在双11的时候有很多的人访问,这些庞大的数据量就不能够通过数据包来传递数据,而是采用xml文件的方式
③配置文件
在之前java学习过程中,我们通常写配置文件如下: *.properties
也可以使用xml来写配置文件:*.xml
二.XML的特点
-
跨平台性(window linux都可以使用)
-
90%的语言都支持xml,不支持xml的10%的语言发布的时候,还没有xml
-
xml具有自我描述性(内容自定义)
(1)html文件中,所有元素(标签)都是官方定义好的,我们直接引用
(2)xml文件中,所有元素自定义
三.XML的语法规则
(1)xml文件必须有根元素,它是所有其他元素的父元素。以下实例中 root 就是根元素
<root>
<child>
<subchild>.....</subchild>
</child>
</root>
(2)xml元素(标签)有开必有合(结束标签)。
html不一样,html有些标签可以不写结束标签
<p>This is a paragraph.
<br>
在 XML 中,省略关闭标签是非法的。所有元素都必须有关闭标签
<p>This is a paragraph.</p>
<br />
(3)xml元素对大小写敏感,必须使用相同的大小写来编写打开标签和关闭标签:
<Message>这是错误的</message>
<message>这是正确的</message>
(4)xml元素必须正确的嵌套
在 HTML 中,常会看到没有正确嵌套的元素:
<b><i>This text is bold and italic</b></i>
在 XML 中,所有元素都必须彼此正确地嵌套:
<b><i>This text is bold and italic</i></b>
(5)xml元素的属性必须加引号(单引双引都可以)
<note date=12/11/2007> // 错误,属性必须加引号 正确写法:<note date="12/11/2007"></note>
<to>Tove</to>
<from>Jani</from>
</note>
XML 声明:
XML 声明文件的可选部分,如果存在需要放在文档的第一行,如下所示:
<?xml version="1.0" encoding="utf-8"?>
XML注释:与html的注释相同
XML中的实体引用:
在 XML 中,一些字符拥有特殊的意义。如果您把字符 “<” 放在 XML 元素中,会发生错误,这 是因为解析器会把它当作新元素的开始。这样会产生 XML 错误:
<message>if salary < 1000 then</message>
为了避免这个错误,请用实体引用来代替 “<” 字符:
<message>if salary < 1000 then</message>
在 XML 中,有 5 个预定义的实体引用:
< <
> >
& &
' ’
" "
还有一种方式:CDATA区
语法:<![CDATA[xxxx]]> xxxx为需要转转义的字符
<student>
<!-- 报错 <compare> 10 < 5 </compare> -->
<compare> <![CDATA[10 > 5]]> </compare>
</student>
在 XML 中,空格会被保留:
HTML 会把多个连续的空格字符裁减(合并)为一个;
在 XML 中,文档中的空格不会被删减。
四.DTD文件(DTD File)
了解即可
1.什么是DTD?
- DTD : document Type Definition (文档类型定义)
2.DTD的目的?
帮助你编写合法的代码,按照DTD文件的规定书写xml中的元素,即DTD文件可以规定标签的定义。如果不按照该文件的规定而自定义标签,代码就会报错。这些文件一般都是官方写好了的,我们只需要直接引用即可。
在MyBatis中会接触到该文件
3.DTD和XML之间的关系
- 类似于类和对象的关系,DTD定义了XML中要包含的属性,就像类规范了对象的行为
- 数据库表和行(一条记录)
dtd有专门的语法,跟xml的语法不一样,也不支持数据类型。比如字符串在它的定义是 #PCDATA
五. XSD文件(XML Schemas File)
了解即可
1.什么是XSD文件?
- xsd 是 xml 结构定义 (XML Schemas Definitiom)
- xsd 是 dtd 的替代品,比 dtd 高端。在spring中也会看到该文件
- xsd 优点:
- xsd 的代码基于 xml,没有专门的语法。和xml一样的解析和处理
- xsd 支持一系列的数据类型
学会解析XML
1.解析 xml 共有四种方式:
- DOM 解析(不咋地)
- SAX 解析(老二)
- JDOM 解析(不咋地)
- DO4J 解析(最吊的)
前两种属于基础方法,是官方提供的与平台无关的解析方式。后两种属于拓展方法,他们是在基础方法之上拓展出来的,只适用于java平台。
DOM 解析
-
dom解析的原理是解析xml的时候,把文档中的所有元素按照其出现的层次关系,在内存中构造出树形结构。
(根元素作为根节点)
-
dom 的优点:可以遍历和修改节点的内容
-
dom 的缺点:内存压力较大,解析较慢
SAX 解析
- 是一种 xml 解析的替代方法
- 相对比 dom 方式,sax 是一种速度更快,更有效的方法
- 缺点:不能修改节点内容
JDOM 解析(不常用)
- 仅适用具体的类,而不用接口,不灵活
DOM4J 解析(重点掌握)
- JDOM 的一种智能的分支,合并了许多超出基本 xml 文档的功能
- hibernate框架就是用 dom4j 来解析的(ssh已经寄了,现在一般用的是MyBatis框架 )
dom4j 性能最高,其次是SAX, dom 和 jdom 表现不好(解析10mb的 xml 文件,就内存溢出了)
2.java解析xml文件
使用的是 dom4j 解析。需要导jar包(放在该笔记的同级目录下)
导入jar包
在idea中导入jar包有两种方式:
方式一:
依次 右击 " 项目名 -> New -> Directory " 新建目录lib(名字随意,最好固定下来), 然后将 jar 包复制到该目录下面,右击该 jar 包,点击 “Add as Library” 将该 jar 包导入该项目
方式二:
点击 “ File -> Project Structure -> Modules -> Dependencies -> 下方的 + 号 "
并选择第一个 ” JARS or Directories “,然后选择本机上的 jar 包,勾选前面的 “方框”,点击ok,Apply
到此,就可以将该jar包导入该项目
dom4j.jar包的版本选择1.6.1,不然的话后续Xpath中有些方法不能用
编写xml文件
右键src, 选择 XML File 创建 xml 文件。(这里我写的是test.xml)
<?xml version="1.0" encoding="UTF-8" ?>
<students>
<student type="usa" color="black">
<id>1</id>
<name>科比</name>
<age>38</age>
</student>
<student type="england" color="write">
<id>2</id>
<name>乔丹</name>
<age>30</age>
</student>
</students>
补充:idea没有直接创建xml文件的选项,需要自己配置。步骤如下
- 点击 File -> Setting -> Editor -> File and Code Templates
- 点击 右侧 files ,再点击下方的 + 号。将右侧的 Name 选项填入 XML File, Extension 选项填入 xml
这样就可以通过new 来创建xml文件了
编写java代码解析xml文件中的内容
下面代码包含的东西很多:
主要涉及反射,io流,集合。
java获取xml文件的根节点students,java获取xml文件根节点的下一层节点 student, java 遍历 student 节点下一层的所有元素, java获取 student 的 属性
package com;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.InputStream;
import java.util.List;
public class TestXML_1 {
/**
* 常见错误:
*文件位置错误:xml文件要放在src下
* 类型引用错误:import 导包导错了
*/
public static void main(String[] args) throws DocumentException {
//1.加载xml文件到jvm中,形成数据流
InputStream is =TestXML_1.class.getClassLoader().getResourceAsStream("test.xml");
//2.创建解析对象
SAXReader sax = new SAXReader();
//3.获得文档对象(整个xml文件, 即上面的test.xml文件), 将数据流转换成一个xml 文件对象
Document doc = sax.read(is);
//4.获得根元素(root即上面的 students)
Element root = doc.getRootElement();
//5.获得根元素下的所有子节点(即 所有的 student)
List<Element> list = root.elements();
System.out.println(list.size());
//lambada 表达式遍历list(即遍历 student)
list.forEach(s -> System.out.println(s));
//遍历节点
for(Element e1: list){
//使用增强for循环遍历list
// System.out.println(e1.getName());
List<Element> list2 = e1.elements(); //得到list的下一层元素(即 id name, age)
for(Element e2 : list2){
System.out.println(e2.getName() + ":"+ e2.getData());
}
}
System.out.println("================");
// 获取 student 标签的 相关属性(访问节点属性)
for (Element e3 : list){
Attribute type = e3.attribute("type");
System.out.println(type.getValue());
}
}
}
使用java程序添加XML文件
package com;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import java.io.*;
public class TestXML_2 {
public static void main(String[] args) throws DocumentException, IOException {
InputStream is= TestXML_2.class.getClassLoader().getResourceAsStream("test.xml");
SAXReader sax= new SAXReader();
Document doc = sax.read(is);
Element root = doc.getRootElement();
//创建元素(节点)-> 对应 xml 文件中根节点的下一层级 student
Element student = root.addElement("student");
//在节点下创建 -> 对应xml文件中 student 层级的下一层级。这个操作是在内存中进行的
Element id = student.addElement("id");
id.setText("3");
Element name = student.addElement("name");
name.setText("姚明");
Element age = student.addElement("age");
age.setText("32");
//写入xml文件中
FileOutputStream out = new FileOutputStream(new File("D:/xx.xml"));
OutputFormat format = new OutputFormat("\t",true, "UTF-8");
XMLWriter xw = new XMLWriter(out,format);
//将整个文档对象写入到文件中
xw.write(doc);
System.out.println("写入成功");
xw.close();
}
}
Xpath
xml 文件 path 路径
- xpath 是一门在 xml 文档中快速查找信息的方式
- 单纯的使用 dom4j 访问节点时, 需要一层一层的处理。如果有了xpath,范文层级的节点就简单了
- 使用 xpath 需要导包: jaxen-1.1-beta-7.jar
package com;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.InputStream;
import java.util.List;
public class TestXML_3 {
public static void main(String[] args) throws Exception {
InputStream is = TestXML_3.class.getClassLoader().getResourceAsStream("test.xml");
SAXReader sax = new SAXReader();
Document doc = sax.read(is);
Element root = doc.getRootElement();
//获得所有学生
// List<Element> list= root.selectNodes("student");
// list.forEach(s -> System.out.println(s));
//查询所有学生的名字
List<Element> list = root.selectNodes("student/name");
// list.forEach(System.out::println); //获得所有学生
list.forEach(s -> System.out.println(s.getData()));
//当xml文件中第二个层级有不同的标签(即不止有student,还有别的),如何获取他们下一层级相同的属性呢?
// 将 "student/name" 改为 "//name"
//获得第一个学生的名字
// List<Element> list = root.selectNodes("student[1]/name");
// list.forEach(s -> System.out.println(s.getData()));
//获取前两个学生的名字
// List<Element> list = root.selectNodes("student[position() < 3]/name");
// list.forEach(s -> System.out.println(s.getData()));
//获取最后一个学生的名字. 获得倒数第二个学生将 last() 改为 last() -1 即可
// List<Element> list = root.selectNodes("student[last()]/name");
// list.forEach(s -> System.out.println(s.getData()));
//获取所有带 type 属性的学生
// List<Element> list = root.selectNodes("student[@type]/name");
// list.forEach(s -> System.out.println(s.getData()));
//获取所有type属性等于 usa 的学生。usa必须加单引号,否则会跟前面的双引号冲突
// List<Element> list = root.selectNodes("student[@type = ‘usa’]/name");
// list.forEach(s -> System.out.println(s.getData()));
//获取年龄大于32的学生
// List<Element> list = root.selectNodes("student[age > 32]/name");
// list.forEach(s -> System.out.println(s.getData()));
}
}