XML:
一、概念:
Extensible Markup Language 可扩展标记语言
1. 功能
1. 存储数据
2. 配置文件
3. 在网络中传输(现在常用JSON,它的解析效率更高)
2. xml与html的区别
1. xml标签都是自定义的,html标签是预定义。
2. xml的语法严格,html语法松散
3. xml是存储数据的,html是展示数据
二、语法格式以及特点
1. XML文档声明
<?xml version="1.0" encoding="UTF-8"?>2. 标记(元素 / 标签 / 节点)
XML文档,由一个个的标记组成。
语法:
- 开始标记(开放标记):<标记名称>
- 结束标记(闭合标记):<标记名称>
- 标记名称:自定义名称,必须遵循以下的命名规则
- 1.名称可以包含字母、数字以及其他字符
2.名称不能以数字或者标点符号开始
3.名称不能以字符“xml”(或者XML、Xml)开始
4.名称不能包含空格,不能包含冒号(:)
5.名称区分大小写
- 1.名称可以包含字母、数字以及其他字符
- 标记内容:开始标记与结束标记之间,是标记的内容
- 例如:
<name>Tom</name>
3. 一个XML文档中,必须有且仅有一个根标记
正例:
<names>
<name>张三</name>
<name>李四</name>
</names>
反例:
<name>张三</name>
<name>李四</name>
4. 标记可以嵌套,但是不允许交叉
正例:
<person>
<name>张三</name>
<age>18</age>
</person>
反例:
<person>
<name>张三<age></name>
18</age>
</person>
5. 标记的层级称呼
子标记,父标记,兄弟标记,后代标记,祖先标记
6. 标记名称允许重复
7. 标记除了开始和结束,还有属性
-
标记中的属性,在标记开始时描述,由属性名和属性值组成
-
格式:
在开始标记中描述属性
可以包含0~n个属性,每一个属性是一个键值对
属性不允许重复,键与值之间使用等号连接,多属性之间使用空格分割
属性值 必须被引号包住
-
案例:
<person> <person id="1001" groupid="1"> <name>Tom</name> <age>18</age> </person> <person id="1003" groupid="1"> <name>Lucy</name> <age>20</age> </person> </person>
8. 注释
- 注释不能写在文档声明前
- 注释不能嵌套注释
- 格式:
注释开始:<!--
注释结束:-->
- 格式:
9. CDATA区域
- CDATA是一个不应该由XML解析器解析的文本数据区。
- 像”<“和”&“字符在XML元素中都是非法的。
- ”<“会产生错误,因为解析器会把该字符解释为新元素的开始。
- ”&“会产生错误,因为解析器会把该字符解释为字符实体的开始。
- 某些文本,比如JavaScript代码,包含大量的"<"和“&”字符。为了避免错误,可以把脚本代码定义为CDATA。
-== CDATA部分中的所有内容都会被解析器忽略。== - CDATA格式:
<![CDATA[ 内容 ]]>
实例:
<![CDATA[<a>哈哈</a>]]>
10. 命名空间
约束:规定xml文档的书写规则,限制它的可扩展性
作为框架的使用者(程序员):
- 能够在xml中引入约束文档
- 能够简单的读懂约束文档
分类:
-
DTD:一种简单的约束技术Schema:一种复杂的约束技术。
引入dtd文档到xml文档中:
- 内部dtd:将约束规则定义在xml文档中
- 外部dtd:将约束的规则定义在外部的dtd文件中
- 本地:
- 网络:
-
Schema:一种复杂的约束技术。
引入:
- 1.填写xml文档的根元素
- 2.引入xsi前缀. xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
- 3.引入xsd文件命名空间. xsi:schemaLocation=“http://www.java.cn/xml student.xsd”
- 4.为每一个xsd约束声明一个前缀,作为标识 xmlns=“http://www.java.cn/xml”
实例:
<students xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.java.cn/xml student.xsd"
xmlns="http://www.java.cn/xml">
三、面试题
问:Java中有几种XML解析方式?分别是什么?有什么样的优缺点?
答:四种
-
SAX解析(Simple API For XML)
解析方式是事件驱动机制!
SAX解析器,逐行读取XML文件解析,每当解析到一个标签的开始/结束/属性/内容时,触发事件,
我们可以编写程序在这些事件发生时,进行相应的处理
优点
:- 解析能够立即开始,而不是等待所有的数据被处理
- 逐行加载,节省内存,有助于解析大于系统内容的的文档
- 有时不必解析整个文档,他可以在某个条件得到满足时停止解析
缺点
:- 1.单向解析,无法定位文档层次,无法同时访问同一个文档不同部分的数据(因为逐行解析,当解析第n行时,第n-1行已经被释放,无法再进行操作了)。
- 2.无法得知事件发生时元素的层次,只能维护节点的父子关系。
- 只读解析方式,无法修改XML文档的内容
-
DOM解析(Document Object Model)
是用与平台和语言无关的方式表示XML文档的官方W3C标准,分析该结构通常需要加载整个文档和内存建立文档树模型,程序员可以通过操作文档树,来完成数据的获取,修改,删除等操作
优点
:- 文档在内存中加载,允许对结构和数据进行修改
- 访问是双向的,可以在任何时候对树中的数据进行双向解析
缺点
:- 文档全部加载到内存中,消耗资源较大
-
JDOM解析(Java Document Object Model)
目的是成为Java特定文档模型,它简化与XML的交互并且使用比DOM解析更快。由于是第一个Java特定模型,JDOM一直得到大力推广和促进。
JDOM文档声明其目的是“使用20%(或更少)的精力解决80%(或更多)Java/XML问题”
优点
:- 使用具体类而不是接口,简化了DOMAPI
- 大量使用了Java集合类,方便Java开发人员
缺点
:- 没有较好的灵活性
- 性能不是那么优异
-
DOM4J解析
它是JDOM的智能分支。它合并了许多超出基本XML文档表示的功能,包括集成的XPath支持、XMLSchema支持以及用于大文档或流化文档的基于事件的处理。它还提供了构建文档表示的选项,DOM4J是非常优秀的Java XML API,具有性能优异、功能强大和非常易于使用的特点,同时它也是一个开放源码的软件。有越来越多的Java软件都在使用DOM4J来读写XML。
目前许多开源项目中大量采用了JDOM技术,例如Hibernate
四、解析
1. DOM4J解析XML
步骤:
1.引入jar文件 dom4j . jar
2.创建一个指向XML文件的输入流
- FileInputStream fis = new FileInputStream(“xml文件的地址”);
3.创建一个xml读取工具对象
- SAXReader sr = new SAXReader();
4.使用读取工具对象,读取XML读取文档的输入流,并得到文档对象
- Document doc = sr.read(fis);
5.通过文档对象,获取XML文档中的根元素对象
- Element root = doc.getRootElement();
2. 文档对象 Document
指的是加载到内存中的 整个XML文档
常用方法:
- 1.通过文档对象,获取XML文档中的根元素对象
- Element root = doc.getRootElement();
- 2.添加根节点
- Element root = doc.addElement(“根节点名称”);
3. 元素对象 Element
指的是XML文档中的单个节点
常用方法:
- 1.获取节点名称
- String getName();
- 2.获取节点内容
- String getText();
- 3.获取全部该节点的全部子节点
- List elements();
- 4.获取下一级节点中某一个节点的内容
- String elementText(“下一级节点中某一个节点名”);
4. 实例
实例1:解析本地文件
XML文件:Students.xml
<?xml version="1.0" encoding="UTF-8" ?>
<students>
<student id="1002">
<name>张三</name>
<age>18</age>
</student>
<student id="1003">
<name>李四</name>
<age>15</age>
</student>
<student id="1004">
<name>王二</name>
<age>22</age>
</student>
</students>
解析程序:
public static void main(String[] args) throws DocumentException, IOException {
//1. 获取文件的输入流
FileInputStream fis = new
FileInputStream("E:\\Students.xml");
//2. 创建XML读取工具对象
SAXReader sr = new SAXReader();
//3. 通过读取工具, 读取XML文档的输入流 , 并得到文档对象
Document doc = sr.read(fis);
//4. 通过文档对象 , 获取文档的根节点对象
Element root = doc.getRootElement();
//5. 通过根节点, 获取所有子节点
List<Element> es = root.elements();
//6. 循环遍历三个book
for (Element e : es) {
//1. 获取id属性值
String id = e.attributeValue("id");
//2. 获取子节点name , 并获取它的内容
String name = e.element("name").getText();
//3. 获取子节点age , 并获取它的内容
String age = e.element("age").getText();
System.out.println("id="+id+",name="+name+",age="+age);
}
fis.close();
}
实例2:解析网络文件
一个公共的手机号查询网址:“http://apis.juhe.cn/mobile/get?phone=”+phone+"&dtype=xml&key=9f3923e8f87flea50ed4ec8c39cc9253"
juhe是一个服务接口网站
,直接百度“api平台”
网络资源浏览器访问结果:
<root>
<resultcode>101</resultcode>
<reason>错误的请求KEY</reason>
<result/>
<error_code>10001</error_code>
</root>
解析程序:
public static void main(String[] args) throws IOException, DocumentException {
//1. 获取XML资源的输入流
String phone = "18516955565";
URL url = new URL("http://apis.juhe.cn/mobile/get?phone="+phone+"&dtype=xml&key=9f3923e8f87flea50ed4ec8c39cc9253");
URLConnection conn = url.openConnection();
//2. 创建一个XML读取对象
SAXReader sr = new SAXReader();
//3. 通过读取对象 读取XML数据,并返回文档对象
Document doc = sr.read(conn.getInputStream());
//4. 获取根节点
Element root = doc.getRootElement();
//5. 解析内容
List elements = root.elements();
String code = root.elementText("resultcode");
if("200".equals(code)){
Element result = root.element("result");
String province = result.elementText("province");
String city = result.elementText("city");
if(province.equals(city)){
System.out.println("手机号码归属地为:"+city);
}else{
System.out.println("手机号码归属地为:"+"province"+"city");
}
}else{
System.out.println("请输入正确的手机号码");
}
}
5. DOM4J - XPATH解析XML
原理:通过路径快速的查找一个或一组元素
路径表达式:
- / : 从根节点开始查找
- // : 从发起查找的节点位置 查找后代节点 ***
- . : 查找当前节点
- … : 查找父节点
- @ : 选择属性 *
属性使用方式:
[@属性名=‘值’]
[@属性名>‘值’]
[@属性名<‘值’]
[@属性名!=‘值’] - 例子:以上面的Students.xml为例
- 路径://student[@id=‘1’]//name
- 查找到id位1的student的name
使用步骤
通过Node类的两个方法, 来完成查找:
(Node是 Document 与 Element 的父接口)
方法1.
//根据路径表达式, 查找匹配的单个节点
Element e = doc.selectSingleNode("路径表达式");
方法2.
List es = doc.selectNodes("路径表达式");
实例:
public static void main(String[] args) throws DocumentException, IOException {
//1. 获取文件的输入流
FileInputStream fis = new
FileInputStream("E:\\Students.xml");
//2. 创建XML读取工具对象
SAXReader sr = new SAXReader();
//3. 通过读取工具, 读取XML文档的输入流 , 并得到文档对象
Document doc = sr.read(fis);
//4. 通过文档对象+xpath,查找所有的name节点
List<Node> names = doc.selectNodes("//name");
for (int i = 0; i <names.size() ; i++) {
System.out.println(names.get(i).getName());
System.out.println(names.get(i).getText());
}
//5.查找单个对象
//5.1 用selectNodes查找
List<Node> names = doc.selectNodes("//student[@id=1003]//name");
for (int i = 0; i <names.size() ; i++) {
System.out.println(names.get(i).getName());
System.out.println(names.get(i).getText());
}
//5.2 用selectSingleNode查找(!!!推荐)
Node name = doc.selectSingleNode("//student[@id=1003]//name");
System.out.println(name.getName());
System.out.println(name.getText());
fis.close();
}
用XPath只是操作起来更简单,因为底层封装了很多方法,效率并不会提高
6. Java生成XML
步骤:
1. 通过文档帮助器 (DocumentHelper) , 创建空的文档对象
Document doc = DocumentHelper.createDocument();
2. 通过文档对象, 向其中添加根节点
Element root = doc.addElement(“根节点名称”);
3. 通过根节点对象root , 丰富我们的子节点
Element e = root.addElement(“元素名称”);
4. 创建一个文件输出流 ,用于存储XML文件
FileOutputStream fos = new FileOutputStream(“要存储的位置”);
5. 将文件输出流, 转换为XML文档输出流
XMLWriter xw = new XMLWriter(fos);
6. 写出文档
xw.write(doc);
7. 释放资源
xw.close();
案例:
public static void main(String[] args) throws IOException {
//1. 通过文档帮助器 (DocumentHelper) , 创建空的文档对象
Document doc = DocumentHelper.createDocument();
//2. 通过文档对象,向其中添加根节点
Element Students = doc.addElement("Students");
//3. 向根节点中 丰富子节点
for (int i = 0; i < 100; i++) {
//向根节点中加入100个student节点
Element Student = Students.addElement("Student");
//向Student加入id属性
Student.addAttribute("id",1+i+"");
//向Student中加入name和age节点
Element name = Student.addElement("name");
Element age = Student.addElement("age");
name.setText("马保国"+1+i+"号");
age.setText("哈哈哈"+i);
}
//4. 创建文件的输入流
FileOutputStream fos = new FileOutputStream("E:\\Student1.xml");
//5. 将文件输出流转为XML文档输出流
XMLWriter xw = new XMLWriter(fos);
//6.写出文档
xw.write(doc);
//7. 释放资源
xw.close();
System.out.println("代码执行完毕");
}
7. XStream 的使用
作用:快速的将Java中的对象, 转换为 XML字符串
使用步骤:
1. 创建XStream 对象
XStream x = new XStream();
2. 修改类生成的节点名称 (默认节点名称为 包名.类名)
x.alias(“节点名称”,类名.class);
3. 传入对象 , 生成XML字符串
String xml字符串 = x.toXML(对象);
案例:
public static void main(String[] args) {
Student s1 = new Student("张三", 18);
Student s2 = new Student("Tom", 16);
Student s3 = new Student("老马", 58);
//1. 创建XStream对象
XStream x = new XStream();
//2. 修改生成的节点名称
x.alias("Student",Student.class);
//3.生成XML字符串
String xml = x.toXML(s1);
System.out.println(xml);
System.out.println("-----------------------------");
//生成一组对象的XML
List<Student> ss = new ArrayList<>();
x.alias("Students",List.class);
ss.add(s1);
ss.add(s2);
ss.add(s3);
String xml2 = x.toXML(ss);
System.out.println(xml2);
}
static class Student{
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
}
运行结果:
<Student>
<name>张三</name>
<age>18</age>
</Student>
-----------------------------
<Students>
<Student>
<name>张三</name>
<age>18</age>
</Student>
<Student>
<name>Tom</name>
<age>16</age>
</Student>
<Student>
<name>老马</name>
<age>58</age>
</Student>
</Students>
JSON:
简介:
JSON: JavaScript Object Notation JS对象简谱 , 是一种轻量级的数据交换格式。
百度搜索:"JSON在线视图查看工具",可以查看一个难以理解的JSON文本
eg:打开网址:sojson.com/json,然后复制JSON文本进去,就能层级显示JSON
1. 对象格式
一本书
- 书名
- 简介
java:
class Book{
private String name;
private String info;
get/set...
}
Book b = new Book();
b.setName(“金苹果”);
b.setInfo(“种苹果”);
...
js:
var b = new Object();
b.name = "金苹果";
b.info = "种苹果";
XML:
<book>
<name>金苹果</name>
<info>种苹果</info>
</book>
JSON:
{
"name":"金苹果",
"info":"种苹果"
}
一个对象, 由一个大括号表示
括号中 描述对象的属性 通过键值对来描述对象的属性
(可以理解为, 大括号中, 包含的是一个个的键值对.)
格式:
- 键与值之间使用冒号连接, 多个键值对之间使用逗号分隔.
- 键值对的键 应使用引号引住 (通常Java解析时, 键不使用引号会报错. 而JS能正确解析。)
- 键值对的值, 可以是JS中的任意类型的数据
2. 数组格式
在JSON格式中可以与对象互相嵌套
[元素1,元素2…]
3. 案例
{
"name":"马保国",
"age":58,
"friend":["张三","李四","王二","麻子",{
"name":"卢本伟",
"info":"老子从不开挂"
}],
"knife":{
"name":"大长刀",
"length":"40m"
}
}
4. Java对象与JSON相互转换
JSON解析器:
常见的解析器:Jsonlib,Gson,fastjson,jackson
1.Gson(谷歌)
最好使用最新jar包(百度搜索Gson然后去GitHub上找,或者Maven上也有)
1. JSON转为Java对象
1.引入JAR包
2. 创建Gson对象
- Gson g = new Gson();
调用" Object obj = g.fromJson(JSON字符串,对象类型.class) ";进行转换
创建一个Student类:
public class Student {
private int id;
private String name;
private int age;
public Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
实例:
public static void main(String[] args) {
//1. 创建Gson对象
Gson g = new Gson();
//2. 转换
String str = "{\"id\":1,\"name\":\"马保国\",\"age\":56}\n";
Student student = g.fromJson(str, Student.class);
System.out.println(student);
System.out.println("---------------------------");
//3.集合转换
String str2 = "{\"id\":1,\"name\":\"马保国\",\"age\":56,\"page\":[\"hello\",\"java\",\"hahaha\"]}\n";
HashMap data = g.fromJson(str2, HashMap.class);
List page = (List) data.get("page");//JSON中的数组转出来是ArrayList
System.out.println(page.get(1));
}
运行结果:
Student{id=1, name='马保国', age=56}
----------------------------------
java
2.Java对象转换JSON
-
1.引入JAR包
-
2. 创建Gson对象
- Gson g = new Gson();
-
3.调用" String json = g.toJSON(要转换的对象) "进行转换
实例:
public static void main(String[] args) {
//1. 创建Gson对象
Gson g = new Gson();
//2. 转换
Student student1 = new Student(1,"马保国",56);
String str = g.toJson(student1);
System.out.println(str);
System.out.println("--------------------------------------------");
//3. 多个对象转换
Student student2 = new Student(2,"卢本伟",28);
Student student3 = new Student(3,"蔡徐坤",15);
ArrayList<Student> students = new ArrayList<>();
students.add(student1);
students.add(student2);
students.add(student3);
String str2 = g.toJson(students);
System.out.println(str2);
}
运行结果:
{"id":1,"name":"马保国","age":56}
--------------------------------------------
[{"id":1,"name":"马保国","age":56},{"id":2,"name":"卢本伟","age":28},{"id":3,"name":"蔡徐坤","age":15}]
2. FastJson(阿里)
最好使用最新jar包(百度搜索Gson然后去GitHub上找,或者Maven上也有)
1. JSON转为Java对象
1.引入JAR包
2.在需要转换Java对象的位置, 编写如下代码:
- 类型 对象名=JSON.parseObject(JSON字符串, 类型.class);
- 或List<类型> list=JSON.parseArray(JSON字符串,类型.class);
实例:
public class Demo4 {
public static void main(String[] args) {
String str = "{\"id\":1,\"name\":\"马保国\",\"age\":56}";
Student student = JSON.parseObject(str, Student.class);
System.out.println(student);
}
}
运行结果:
Student{id=1, name='马保国', age=56}
2.Java对象转换JSON
1.引入JAR包
2.在需要转换JSON字符串的位置编写如下代码即可:
- String json=JSON.toJSONString(要转换的对象);
实例:
public static void main(String[] args) {
Student student1 = new Student(1,"马保国",56);
String str = JSON.toJSONString(student1);
System.out.println(str.length());
}
运行结果:
{"id":1,"name":"马保国","age":56}
注意:
FastJson是靠对象属性的get、Set方法生成josn文件的,没有get、set方法无法生成
3. JackSon
1. JSON转为Java对象
1.导入jackson的相关jar包
2.创建Jackson核心对象 ObjectMapper
3.调用ObjectMapper的相关方法进行转换
- readValue(json字符串数据,Class)
2. Java对象转换JSON
使用步骤:
1.导入jackson的相关jar包
2.创建Jackson核心对象 ObjectMapper
3.调用ObjectMapper的相关方法进行转换
-
1.转换方法:
writeValue(参数1,obj):
参数1:
File:将obj对象转换为JSON字符串,并保存到指定的文件中
Writer:将obj对象转换为JSON字符串,并将json数据填充到字符输出流中
OutputStream:将obj对象转换为JSON字符串,并将json数据填充到字节输出流中
writeValueAsString(obj):将对象转为json字符串 -
2.注解:
- @JsonIgnore:排除属性。
- @JsonFormat:属性值得格式化
@JsonFormat(pattern = “yyyy-MM-dd”)
-
3.复杂java对象转换
- List:数组
- Map:对象格式一致
-