XML
大约 7 分钟
此文章根据 慕课网 视频课程总结,仅用于本人知识库记录
简介
XML 全称:EXtensible Markup Language,可扩展标记语言
- 编写 XML 就是编写 标签,与 HTML 非常类似,
***.xml
- 有良好的人机可读性
- XML 没有预定义标签,HTML 存在大量预定义标签
- XML 重在保存与传输数据,HTML 用于显示信息
用途
Java 程序的配置描述文件
用于保存程序产生的数据
网络间的数据传输
文档结构
第一行必须是 XML 声明
<?xml version="1.0" encoding="utf-8" ?>
version
:版本号1.0
:初始版本1.1
:在初始版本上进行细节上的修改与升级
encoding
:设置字符集
有且只有一个根节点
XML 标签的书写规则与 HTML 相同
书写规则
合法的标签名
- 标签名要有意义
- 建议使用英文,小写字母,单词之间用
-
分割 - 多级标签之间不要存在重名的情况
适当的注释与缩进
- 提高文档可读性
合理使用属性
- 常用与描述标签不可或缺的信息
- 对标签分组或者为标签设置 ID 时常用属性表示
特殊字符与 CDATA 标签
- 标签体中,出现
<
、>
特殊字符,会破坏文档结构
解决方案 1:使用实体引用:适用于特殊符号比较少的情况
符号 | 说明 | 实体引用 |
---|---|---|
< | 小于 | < |
> | 大于 | > |
& | 和号 | & |
' | 单引号 | ' |
" | 双引号 | " |
解决方式 2:使用 CDATA 标签
用来表示不应由 XML 解析器进行解析的文本数据
语法:
<![CDATA[ 文本 ]]>
<lesson>
<content>
<![CDATA[
<body>
<a href="index.html">首页</a>
</body>
]]>
</content>
</lesson>
有序的子元素
- 在 XML 多层嵌套的子元素中,标签前后顺序应保持一致
语义约束
- XML 文档结构正确,但可能不是有效的
- XML 予以约束就是用于规定 XML 文档中允许出现哪些元素
定义方式
DTD
全称:Document Type Definition,文档类型定义
是一种简单易用的语义约束方式
以单独文件出现,扩展名:
***.dtd
用法
- 使用
<!ELEMENT>
标签定义 XML 文档中允许出现的节点及数量 - 使用
<ATTLIST>
标签定义 XML 文档中允许出现的属性- 书写格式:
<!ATTLIST 元素名称 属性名称 属性类型 默认值>
- 书写格式:
- 如某个子节点需要多次重复出现,则需要在子节点后增加响应的描述符
- 在 XML 中使用
<!DOCTYPE>
标签来引用 DTD 文件- 书写格式:
<!DOCTYPE 根节点 SYSTEM "dtd文件路径">
- 书写格式:
- 使用
<!-- 定义 hr 节点下只允许出现 1 个 employee 子节点 -->
<!ELEMENT hr(employee)>
<!-- 定义 hr 节点下最少出现 1 个 employee 子节点 -->
<!ELEMENT hr(employee+)>
<!-- 定义 hr 节点下最多出现 1 个 employee 子节点 -->
<!ELEMENT hr(employee?)>
<!-- 定义 hr 节点下最少出现 0 个或多个 employee 子节点 -->
<!ELEMENT hr(employee*)>
<!-- employee 节点下必须包含以下四个节点,且按顺序出现 -->
<!ELEMENT employee(name,age,salary,department)>
<!-- employee 节点下需要有 no 属性,默认值为 "" -->
<!ATTLIST employee no CDATA "">
<!-- 定义 name 标签体只能是文本,#PCDATA 代表文本元素 -->
<!ELEMENT name(#PCDATA)>
...
<!-- hr.xml -->
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE hr SYSTEM "hr.dtd">
<hr>
<employee no="3309">
<name>张三</name>
<age>30</age>
<salary>4000</salary>
<department>
<dname>会计部</dname>
<address>XX大厦-B103</address>
</department>
</employee>
<employee no="3310">
<name>李四</name>
<age>23</age>
<salary>3000</salary>
<department>
<dname>工程部</dname>
<address>XX大厦-B103</address>
</department>
</employee>
</hr>
<!-- hr.dtd -->
<?xml version="1.0" encoding="utf-8" ?>
<!ELEMENT hr (employee+)>
<!ELEMENT employee (name,age,salary,department)>
<!ATTLIST employee no CDATA "">
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT salary (#PCDATA)>
<!ELEMENT department (dname,address)>
<!ELEMENT dname (#PCDATA)>
<!ELEMENT address (#PCDATA)>
XML Schema
- 比 DTD 更为复杂,提供了更多功能
- 提供了数据类型、格式限定、数据范围等特性
- 是 W3C 标准
- 文件后缀名:
***.xsd
<?xml version="1.0" encoding="UTF-8"?>
<hr xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="hr.xsd">
<employee no="3309">
<name>张三</name>
<age>30</age>
<salary>4000</salary>
<department>
<dname>会计部</dname>
<address>XX大厦-B103</address>
</department>
</employee>
<employee no="3310">
<name>李四</name>
<age>23</age>
<salary>3000</salary>
<department>
<dname>工程部</dname>
<address>XX大厦-B104</address>
</department>
</employee>
</hr>
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema">
<element name="hr">
<!-- complexType标签含义是复杂节点,包含子节点时必须使用这个标签 -->
<complexType>
<sequence>
<element name="employee" minOccurs="1" maxOccurs="9999">
<complexType>
<sequence>
<element name="name" type="string"></element>
<element name="age">
<simpleType>
<restriction base="integer">
<minInclusive value="18"></minInclusive>
<maxInclusive value="60"></maxInclusive>
</restriction>
</simpleType>
</element>
<element name="salary" type="integer"></element>
<element name="department">
<complexType>
<sequence>
<element name="dname" type="string"></element>
<element name="address" type="string"></element>
</sequence>
</complexType>
</element>
</sequence>
<attribute name="no" type="string" use="required"></attribute>
</complexType>
</element>
</sequence>
</complexType>
</element>
</schema>
DOM
文档对象模型(Document Object Model),定义了访问和操作 XML 文档的标准方法,DOM 把 XML 文档当做树结构来查看,能够通过 DOM 树来读写所有元素
Dom4j
一个易用的、开源的库,用于解析 XML,应用于 Java 平台,具有性能优异、功能强大和极易使用的特点
- 将
XML
视为Document
对象 - XML
标签
被 Dom4j 定义为Element
对象
使用步骤
- 新建
lib
文件夹 - 将 Dom4j 拖入 lib 文件夹
- 右键
Dom4j
包,点击Build Path
读操作
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE hr SYSTEM "hr.dtd">
<hr>
<employee no="3309">
<name>张三</name>
<age>30</age>
<salary>4000</salary>
<department>
<dname>会计部</dname>
<address>XX大厦-B103</address>
</department>
</employee>
<employee no="3310">
<name>李四</name>
<age>23</age>
<salary>3000</salary>
<department>
<dname>工程部</dname>
<address>XX大厦-B103</address>
</department>
</employee>
</hr>
// Dom4j 读操作
// HrReader.java
package com.imooc.dom4j;
import java.util.List;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class HrReader {
public void readXml() {
String file = "/Users/sunzhenyang/eclipse-workspace/xml/src/hr.xml";
// SAXReader类 是读取 XML 文件的核心类,用于将 XML 解析后以 “树” 的形式保存在内存中
SAXReader reader = new SAXReader();
try {
Document document = reader.read(file);
// 获取 XML 文档的根节点,即 hr 标签
Element root = document.getRootElement();
// elements 方法用于获取指定的标签集合
List<Element> employees = root.elements("employee");
for (Element employee : employees) {
// element 方法用于获取唯一的子节点对象
Element name = employee.element("name");
// getText 方法用于获取标签文本
String emName = name.getText();
System.out.println(emName);
System.out.println(employee.elementText("age"));
System.out.println(employee.elementText("salary"));
Element department = employee.element("department");
System.out.println(department.elementText("dname"));
System.out.println(department.elementText("address"));
Attribute attr = employee.attribute("no");
System.out.println(attr.getText());
}
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
HrReader reader = new HrReader();
reader.readXml();
}
}
写操作
// Dom4j 写操作
// HrWriter.java.
package com.imooc.dom4j;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class HrWriter {
public void writeXml() {
String file = "/Users/sunzhenyang/eclipse-workspace/xml/src/hr.xml";
SAXReader reader = new SAXReader();
try {
Document document = reader.read(file);
Element root = document.getRootElement();
Element employee = root.addElement("employee");
employee.addAttribute("no", "3311");
Element name = employee.addElement("name");
name.setText("李铁柱");
employee.addElement("age").setText("37");
employee.addElement("salary").setText("3600");
Element department = employee.addElement("department");
department.addElement("dname").setText("人事部");
department.addElement("address").setText("XX大厦-B105");
Writer writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
document.write(writer);
writer.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
HrWriter hrWriter = new HrWriter();
hrWriter.writeXml();
}
}
XPath 路径表达式
- 是 XML 文档中查找数据的语言
- 可以极大提高在提取数据时的开发效率
- 学习 XPath 本质就是掌握各种形式表达式使用技巧
基本表达式
表达式 | 描述 |
---|---|
nodename | 选取子节点的所有子节点 |
/ | 从根节点选取 |
// | 从匹配选择的当前节点选择文档中的节点,而不考虑他们的位置 |
. | 选取当前节点 |
.. | 选取当前节点的父节点 |
@ | 选取属性 |
谓语表达式
路径表达式 | 结果 |
---|---|
/bookstore/book[1] | 选取属于 bookstore 子元素的第一个 book 元素 |
/bookstore/book[last()] | 选取属于 bookstore 子元素的最后一个 book 元素 |
/bookstore/book[last()-1] | 选取属于 bookstore 子元素的倒数第二个 book 元素 |
/bookstore/book[position()<3] | 选取前两个属于 bookstore 元素的 book 子元素 |
//title[@lang] | 选取所有拥有 lang 属性的 title 元素 |
//title[@lang='eng'] | 选取所有 lang 属性为 eng 的 title 元素 |
/bookstore/book[price>35.00] | 选取所有 bookstore 元素下的所有 price 元素值大于 35.00 的 book 元素 |
/bookstore/book[price>35.00]/title | 选取所有 bookstore 元素下所有 price 元素值大于 35.00 的 book 元素下的 title 元素 |
案例
路径表达式 | 结果 |
---|---|
bookstore | 选取 bookstore 元素的所有子节点 |
/bookstore | 选取根元素 bookstore,加入路径起始于正斜杠(/ ),则地路径始终代表到某元素的绝对路径 |
bookstore/book | 选取属于 bookstore 的子元素中的所有 book 元素 |
//book | 选取所有 book 子元素,而不管他们在文档中的位置 |
bookstore//book | 选取属于 bookstore 元素的后代中的所有 book 元素,而不管他们位于 bookstore 之下的什么位置 |
//@lang | 选取属性名为 lang 的所有元素 |