XML & JSON
1、 XML
1.1 XML 介绍
1.1.1 What is it?
什么是 XML? |
---|
XML 指可扩展标记语言(EXtensible Markup Language ) |
XML 是一种标记语言,很类似 HTML |
XML 的设计宗旨是传输数据,而非显示数据 |
XML 标签没有被预定义,需要自行定义标签 |
XML 被设计为具有自我描述性(平台无关性) |
1.1.2 名词解释
-
可拓展性标记语言
在电子计算机中,标记指计算机所能理解的信息符号,通过此种标记,计算机之间可以处理包含各种的信息比如文章等。它可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。
-
自我描述性
是
XML
是独立于其他平台定义的,例如XML
定义了一个结构,不同之间平台交换数据,XML
结构不需要依赖任何平台的结构,而是自己定义的XSD
或者DTD
,其余平台只要按照这个去解析XML
就可以了。 -
数据传输
XML
文件包含了发送者和接受者的信息,同时拥有标题以及消息主体。 但是,这个XML
文档仍然没有做任何事情,仅仅是包装了XML
标签中的纯粹的信息。我们需要编写软件或者程序,才能传送、接收和显示出这个文档。
1.2 XML 语法格式
XML
的语法格式很简单,和 HTML
类似,但也不同(例如 XML
的标签必须闭合)
1.2.1 文档声明
声明写在文件的第一行,表明当前的文档是 XML
格式的文件,不写不影响读取,但是写上最好。
-
语法格式
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
version
表示当前文件的版本,encoding
表示文件所使用的的字符编码,standalone
表示是否依赖其他的文件(默认是yes
)
1.2.2 元素标记
XML
文件中的元素以 <标记名称
> 标记内容 </标记名称
> 形式出现,由开发者自行定义内容。
自定义名称,必须遵循以下命名规则
规则 |
---|
1.名称可以含字母、数字以及其他的字符 |
2名称不能以数字或者标点符号开始 |
3.名称不能以字符 “xml”(或者 XML、Xml)开始 |
4.名称不能包含空格,不能包含冒号(:) |
5.名称区分大小写 |
-
语法格式
<books> <book> <name>金苹果</name> <info>讲述了吃苹果的过程</info> </book> </books>
标记内部还可以有属性字段,由 属性名 = “属性值” 组成(属性值必须有引号进行修饰)。
-
语法格式
<books> <book id="1001"> <name>金苹果</name> <info>讲述了吃苹果的过程</info> </book> <book id="1002"> <name>银苹果</name> <info>无</info> </book> </books>
1.2.3 内容解析
有些情况下我们需要在内容中定义一些和 XML
语法类型结构的特殊字符,但是不希望被解析,就需要用
CDATA
进行修饰, CDATA
部分中的所有内容都会被解析器忽略。
-
例如 像
"<"
和"&"
字符在XML
元素中都是非法的。问题 "<"
会产生错误,因为解析器会把该字符解释为新元素的开始。"&"
会产生错误,因为解析器会把该字符解释为字符实体的开始。 -
错误示范
<books> <book> <name><金苹果></name> <info>讲述了你 & 他吃苹果</info> </book> </books>
上述格式会报错
![](https://i-blog.csdnimg.cn/blog_migrate/5312fe5855ede3df457a91a39bb86432.png)
-
正确格式
<books> <book> <name><![CDATA[[<金苹果>]]></name> <info><![CDATA[[讲述了你 & 他吃苹果]]></info> </book> </books>
1.2.4 内容注释
和大多数的语言一样,XML
提供注释格式,由<!--
注释内容 -->
表示, 注释不能写在文档文档声明前,也不能嵌套注释。
-
语法格式
<books> <book> <!--这是一个书名--> <name>金苹果</name> </book> </books>
1.3 XML 注意问题
1.3.1 根标记唯一
标标记可重复定义,但是最外层的标记只能存在一个。
-
错误示范
<books> <book> <name>金苹果</name> </book> </books> <--!多个根标记将会报错--> <books> <book> <name>金苹果</name> </book> </books>
上述文件将会报错
![](https://i-blog.csdnimg.cn/blog_migrate/84d629da640bd5b093ad709ad1b0ff5b.png)
1.3.2 标记不可交叉
标记可以 嵌套 ,但是不允许标记间 交叉,标记的开始和结束都是成对出现的。
-
错误示范
<books> <book> <name>金苹果 </book> </name> </books>
上述文件将会报错
![](https://i-blog.csdnimg.cn/blog_migrate/dcbe8bc182fcb70ded395039d33f605c.png)
1.4 XML 解析方式
1.4.1 SAX解析
解析方式是事件驱动机制 !逐行读取XML文件解析,每当解析到一个标签的开始 结束 内容 属性时,触发事件。 我们可以编写程序在这些事件发生时,进行相应的处理。
-
优点
优点 分析能够立即开始,而不是等待所有的数据被处理。 逐行加载,节省内存,有助于解析大于系统内存的文档。 有时不必解析整个文档,它可以在某个条件得到满足时停止解析。 -
缺点
缺点 单向解析,无法定位文档层次,无法同时访问同一文档的不同部分数据(因为逐行解析,当解析第n行是,第n-1行已经被释放了,无法再进行操作了)。 无法得知事件发生时元素的层次,只能自己维护节点的父/子关系。 只读解析方式,无法修改XML文档的内容。
1.4.2 DOM解析
是用与平台和语言无关的方式表示 XML
文档的官方W3C标准,分析该结构通常需要加载整个文档和内存中建立文档树模型。程序员可以通过操作文档树,来完成数据的 获取 修改 删除 等.
-
优点
优点 文档在内存中加载, 允许对数据和结构做出更改。 访问是双向的,可以在任何时候在树中双向解析数据。 -
缺点
缺点 文档全部加载在内存中 , 消耗资源大。
1.4.3 JDOM解析
目的是成为 Java
特定文档模型,它简化与XML
的交互并且比使用 DOM
实现更快。由于是第一 个 Java
特定模型,JDOM
一直得到大力推广和促进。
JDOM
文档声明其目的是 使用20%(或更少)的精力解决80%(或更多)Java/XML问题
-
优点
优点 使用具体类而不是接口,简化了DOM的API。 大量使用了Java集合类,方便了Java开发人员。 -
缺点
缺点 没有较好的灵活性。 性能不是那么优异。
1.4.4 DOM4J解析
它是 JDOM
的一种智能分支。它合并了许多超出基本 XML
文档表示的功能,包括集成的 XPath
支持、XML Schema
支持以及用于大文档或流化文档的基于事件的处理。
它还提供了构建文档表示的选项, DOM4J
是一个非常优秀的 Java XML API
,具有性能优异、功能强大和极端易用使用的特点,同时它也是一 个开放源代码的软件。
如今可以看到越来越多的 Java
软件都在使用 DOM4J
来读写 XML
。 目前许多开源项目中大量采用 DOM4J
, 例如:Hibernate
2、 XML 解析 & 生成
2.1 几个对象及方法
2.1.1 文档对象 Document
指的是加载到内存的整个 XML
文档.。
常用方法: |
---|
通过文档对象,获取 XML 文档中的根元素对象 Element root = doc.getRootElement(); |
添加根节点 Element root = doc.addElement(“根节点名称”); |
2.1.2 元素对象 Element
指的是 XML
文档中的单个节点.。
常用方法: |
---|
获取节点名称 String getName(); |
获取节点内容 String getText(); |
设置节点内容 String setText(); |
根据子节点的名称,获取匹配名称的第一个子节点对象 Element element(String 子节点名称); |
获取所有的子节点对象 List elements(); |
获取节点的属性值 String attributeValue(String 属性名称); |
获取子节点的内容 String elementText(String 子节点名称); |
添加子节点 Element addElement(String 子节点名称); |
添加属性 addAttribute(String 属性名,String 属性值); |
2.2 DOM4J 解析
2.2.1 解析本地文件
没有啥可以描述的,直接按照步骤进行即可。
-
代码测试
public static void main(String[] args) throws IOException, DocumentException { // 1、 引入dom4j-1.6.1.jar包 // 2、 xml 文件的读入流 FileInputStream inputStream = new FileInputStream("resources/test.xml"); // 3、 创建 xml 读取工具对象 SAXReader reader = new SAXReader(); // 4、 读取输入流得到文档对象 Document document = reader.read(inputStream); // 5、 通过文档对象读取数据 Element root = document.getRootElement(); // 读取节点的名称 System.out.println(root.getName()); // 获取根节点下的所有子节点 List<Element> list = root.elements(); // 遍历节点读取数据 for (Element element: list) { List<Element> nodes = element.elements(); for (Element node: nodes) { // 取出节点内容 System.out.println(node.getText()); } } }
输出结果
![](https://i-blog.csdnimg.cn/blog_migrate/97fbc686577dd07dea8140076d3df05a.png)
2.2.2 解析网络文件
和解析本地文件方法类似,只是读取文件的方法不同。
-
代码测试
String url = "http://..."; URL url = new URL(url); // 连接 url 地址得到连接后拿到输入流对象 URLConnection conn = url.openConnection(); InputStream is = conn.getInputStream(); // 后面的步骤和本地文件的方法一致
2.3 XPATH 解析
2.3.1 路径表达式
通过路径快速的查找一个或一组元素
路径表达式 |
---|
/ : 从根节点开始查找 |
// : 从发起查找的节点位置 查找后代节点 |
. : 查找当前节点 |
.. : 查找父节点 |
@ : 选择属性 |
-
选择属性的使用方法
[@属性名=‘值’] [@属性名>‘值’] [@属性名<‘值’] [@属性名!=‘值’]
2.3.2 解析文件
-
两种方法获取节点
// 根据路径表达式, 查找匹配的单个节点 Element e = selectSingleNode("路径表达式");
// 根据路径表达式, 查找匹配的所有节点 List<Element> es = selectNodes("路径表达式");
-
代码测试
public static void main(String[] args) throws IOException, DocumentException { // 2、 xml 文件的读入流 FileInputStream inputStream = new FileInputStream("resources/test.xml"); // 3、 创建 xml 读取工具对象 SAXReader reader = new SAXReader(); // 4、 读取输入流得到文档对象 Document document = reader.read(inputStream); // 5、 读取所有匹配节点 List<Node> names = document.selectNodes("//name"); List<Node> info = document.selectNodes("//info"); for(int i = 0; i < names.size(); i++) { System.out.println(names.get(i).getName() + ":" + names.get(i).getText()); System.out.println(info.get(i).getName() + ":" + info.get(i).getText()); } }
输出结果
![](https://i-blog.csdnimg.cn/blog_migrate/8813fb5cc42b67906016139d6ad13677.png)
-
属性查找
public static void main(String[] args) throws IOException, DocumentException { // 2、 xml 文件的读入流 FileInputStream inputStream = new FileInputStream("resources/test.xml"); // 3、 创建 xml 读取工具对象 SAXReader reader = new SAXReader(); // 4、 读取输入流得到文档对象 Document document = reader.read(inputStream); // 5、 获取属性 ID 为 1001 的 book 标签下的 name 标签节点 Node node = document.selectSingleNode("//book[@id='1001']//name"); System.out.println(node.getText()); }
2.4 XML 文件生成
2.4.1 Document对象
通过往 Document
文档中添加节点和相应的节点名称和内容来丰富 XML
文件信息,最终输出到本地磁盘。
-
代码测试
public static void main(String[] args) throws IOException, DocumentException { // 1、 创建一个文档对象 Document document = DocumentHelper.createDocument(); // 2、 添加节点后会返回当前添加的节点 Element books = document.addElement("books"); Element name = books.addElement("name"); // 3、 设置节点信息 name.setText("金苹果"); Element info = books.addElement("info"); info.setText("吃苹果"); // 4、 添加节点属性 books.addAttribute("id", "1001"); // 5、 输出流转换 XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("resources/test.xml")); xmlWriter.write(document); xmlWriter.close(); }
输出结果
![](https://i-blog.csdnimg.cn/blog_migrate/cd55268cb89897c492988bf0a5857402.png)
2.4.2 XStream 对象
通过 XStream
对象可以直接将一个对象以符合 XML
语法标准的形式转换。
-
代码测试
public static void main(String[] args) throws IOException, DocumentException { FileOutputStream outputStream = new FileOutputStream("resources/test.xml") ; Person person = new Person("张三", 18, null); // 1、 创建 XStream 对象 XStream xStream = new XStream(); // 2、 修改节点名为 person xStream.alias("person", Person.class); // 3、 将对象转为 XML 字符串并写入到输出流 xStream.toXML(person, outputStream); outputStream.close(); }
输出结果
![](https://i-blog.csdnimg.cn/blog_migrate/278b1280e31929c1f75d5c7ff4f2adbe.png)
3、 JSON 文件
3.1 JSON 介绍
JSON ( JavaScript Object Notation
) 是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,是理想的数据交换格式。 同时,JSON是 JavaScript
原生格式,这意味着在 JavaScript
中处理 JSON数据不须要任何特殊的 API 或工具包。
3.1.1 格式
json
文件中一个{}
就表示一个对象, 括号中描述对象的属性,通过键值对来描述对象的属性。
属性格式 |
---|
键与值之间使用冒号连接,多个键值对之间使用逗号分隔。 |
键值对的键应使用引号引住 (通常Java解析时,,键不使用引号会报错, 而JS能正确解析) |
键值对的值,可以是 JS 中的任意类型的数据 |
-
代码格式
{ "name":"金苹果", "info":"种苹果" }
-
对象可嵌套
{ "name":"伟杰老师", "age":18, "heihei":{ "name":"大长刀", "length":"40m" } }
-
数组表示
{ "name":"伟杰老师", "age":18, "paoyou":["张三","李四","王二","麻子"], }
3.2 java 和 json 互转
Gson
和 FastJson
提供转换函数们只需要将其对应的 jar
文件引入就可以使用。
3.2.1 Gson
Google
提供的转换工具。
-
java 对象转 JSON 字符串
public static void main(String[] args) throws IOException, DocumentException { Person person = new Person("张三", 18, new String[]{"抽烟","喝酒","烫头"}); // 获取转换的对象 Gson gson = new Gson(); String s = gson.toJson(person); System.out.println(s); }
-
JSON 字符串转 java对象
public static void main(String[] args) throws IOException, DocumentException { String json = "{\"name\":\"张三\",\"age\":18,\"hobby\":[\"抽烟\",\"喝酒\",\"烫头\"]}"; Gson gson = new Gson(); // 转换为对应对象 Person person = gson.fromJson(json, Person.class); System.out.println(person); // 转换为 map 集合,以键值对形式对数据进行存储 HashMap map = gson.fromJson(json, HashMap.class); for (Object str:map.keySet()) { System.out.println(map.get(str)); } }
输出结果
![](https://i-blog.csdnimg.cn/blog_migrate/3efbd82c7ffa1619ae6006775008b4e6.png)
3.2.2 FastJson
阿里
提供的转换工具。
-
java 对象转 JSON 字符串
public static void main(String[] args) throws IOException, DocumentException { Person person = new Person("张三", 18, new String[]{"抽烟","喝酒","烫头"}); // 对象转为 json 字符串 String s = JSON.toJSONString(person); System.out.println(s); }
-
JSON 字符串转 java对象
public static void main(String[] args) throws IOException, DocumentException { String json = "{\"age\":18,\"hobby\":[\"抽烟\",\"喝酒\",\"烫头\"],\"name\":\"张三\"}"; // json 字符串转换为 java 对象 Person p = JSON.parseObject(json, Person.class); System.out.println(p); // json 数组转换后为 ArrayList 对象 List list = JSON.parseArray("[\"抽烟\",\"喝酒\",\"烫头\"]", String.class); System.out.println(list.getClass()); }
输出结果
![](https://i-blog.csdnimg.cn/blog_migrate/ce6f278a95c3fbd16bda46c4c66539a3.png)