概念:Extensible Markup Language 可扩展标记语言
一、特点及功能
-
功能:存储数据
- 配置文件
- 在网络中传输【现在流行使用json进行传输,省带宽;但是银行还是使用的xml】
-
xml与html的区别
- xml标签都是自定义的,html标签是预定义的【框架开发中可以自定义组件!】
- xml语法严格,html语法松散
- xml存数据,html展现数据。
二、语法
1.基本语法
- 后缀名
.xml
- 第一行必须定义为文档申明
- xml文档有且仅有一个根标签(vue中的template中也是必须有且仅有一个标签。)
- 属性值必须使用引号(单双引号均可)引起来
- 标签关闭匹配必须正确【双标签或者围堵标签】
- xml标签名区分大小写
如下:
<?xml version='1.0'?>
<users>
<user id="1">
<name>吴奇隆</name>
<age>30</age>
<gender>male</gender>
<br/>
</user>
<user id="2">
<name>刘诗诗</name>
<age>24</age>
<gender>female</gender>
</user>
</users>
2.组成部分分析
-
文档申明
- 格式
<?xml 属性列表 ?>
- 属性列表:
-
version
: 版本号,必写 -
encoding
: 编码方式,默认ISO-8859-1 -
standalone
:是否独立- 属性为
yes
: 不依赖其他文件 - 属性为
no
:依赖其他文件
- 属性为
-
- 格式
-
指令(了解),集合css控制xml标签元素的样式,但是不会这么干
- 写法如下:
<?xml-stylesheet type="text/css" href="a.css">
- 写法如下:
-
标签规则:
- 名称可以包含数字、字母、其他字符
- 不能以数字或者表单符号开始
- 不能以xml/XML/Xml等开始,
- 不能包含空格。
-
属性
-
id
属性值必须唯一!
-
-
文本
- 特殊字符需要转义,和html转义是一样的,例如。
<
--<
&&
--&&
等,可以使用CDATA区 - CDATA区:这个区域的字符原样展示
<![CDATA[ 数据 ]]>
- 特殊字符需要转义,和html转义是一样的,例如。
注释:与html注释是一样的
3.约束文档
概念,规定xml书写的规则,相当于自定义协议,是写框架作者的作者为了指导使用该框架需要书写的格式而写的一个约束文档
使用框架者就是能简单阅读约束文档。能够在xml中引入约束文档。
- 分类
- DTD:一种简单的约束技术
- Schema: 一种复杂的约束技术。
1. DTD约束技术【不推荐使用】
缺陷:无法规定标签内字符串的内容
- 内部dtd:将约束固定在xml文件中【了解】
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE students [
<!ELEMENT students (student+) >
<!ELEMENT student (name,age,sex)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT sex (#PCDATA)>
<!ATTLIST student number ID #REQUIRED>
]>
<students>
<student number="s001">
<name>小明</name>
<age>22</age>
<sex>男</sex>
</student>
</students>
- 引入外部dtd:将约束的规定定义在外部的dtd文件中
- 本地:
<!DOCTYPE 根标签名 SYSTEM "dtd文件的位置">
- 网路:
<!DOCTYPE 根标签名 PUBLIC "dtd文件名字,随便取" "dtd文件的位置url">
- 本地:
student.dtd
<!ELEMENT students (student+) > <!-- 标签student,里面可以包含【正则】1~n个student标签 -->
<!ELEMENT student (name,age,sex)> <!-- 包含三个标签,书写顺序不能变-->
<!ELEMENT name (#PCDATA)> <!-- 内容字符串 -->
<!ELEMENT age (#PCDATA)>
<!ELEMENT sex (#PCDATA)>
<!ATTLIST student number ID #REQUIRED> <!-- 属性值必须写-->
student.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE students SYSTEM "student.dtd">
<students>
<student number="s001">
<name>小明</name>
<age>22</age>
<sex>男</sex>
</student>
</students>
2.Schema约束技术【推荐,看懂即可】
- 后缀名:
.sxd
,约束里面的内容定义方式像是走递归过程一样!
student.sxd文件
<?xml version="1.0"?>
<xsd:schema xmlns="http://www.itcast.cn/xml" -- 默认命名空间?
xmlns:xsd="http://www.w3.org/2001/XMLSchema" -- 指定啥版本协议什么的
targetNamespace="http://www.itcast.cn/xml" elementFormDefault="qualified"> -- 命名空间什么鬼
<xsd:element name="students" type="studentsType"/> -- 指定根标签名字, 并指定复杂的自定义类型,类型在下面对应的地方指定
<xsd:complexType name="studentsType"> -- 定义studentsType这种自定义复杂类型所包含的属性
<xsd:sequence> -- 定义这中属性下要写啥,限定啥
<xsd:element name="student" type="studentType" minOccurs="0" maxOccurs="unbounded"/>
-- 又定义了一个标签,studentType自定义类型,下面会具体定义,可以写student标签0~无线个这么个意思
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="studentType"> -- 定义studentType自定义属性,下面又有哪些标签元素,
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/> -- 定义标签,指定规范的类型!
<xsd:element name="age" type="ageType" /> -- 定义标签,自定义类型
<xsd:element name="sex" type="sexType" /> -- 定义标签,自定义类型
</xsd:sequence>
<xsd:attribute name="number" type="numberType" use="required"/>
-- 定义了一个在student标签中必须要写的属性number,而且类型是自定义的!
</xsd:complexType>
<xsd:simpleType name="sexType"> -- 解释自定义的简单的类型
<xsd:restriction base="xsd:string">
<xsd:enumeration value="male"/> -- 枚举
<xsd:enumeration value="female"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ageType">
<xsd:restriction base="xsd:integer">
<xsd:minInclusive value="0"/>
<xsd:maxInclusive value="256"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="numberType">
<xsd:restriction base="xsd:string">
<xsd:pattern value="heima_\d{4}"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
student.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!--
1.填写xml文档的根元素
2.引入xsi前缀. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3.引入xsd文件命名空间. xsi:schemaLocation="http://www.itcast.cn/xml student.xsd"
4.为每一个xsd约束声明一个前缀,作为标识 xmlns="http://www.itcast.cn/xml"
-->
<students xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" -- 估计是某种规范协议吧
xsi:schemaLocation="http://www.itcast.cn/xml student.xsd -- 约束文件有哪些
http://www.itcast.cn/xml2 student2.xsd
"
xmlns="http://www.itcast.cn/xml" -- 前缀标识,说明来自哪个约束文件,不写前缀默认的约束
xmlns:a="http://www.itcast.cn/xml2" -- 前缀标识,对应的标签前要加东西,比如<a:student></a:student>
指定约束来源!
>
<student number="heima_0001">
<name>tom</name>
<age>18</age>
<sex>male</sex>
</student>
</students>
三、XML解析
操作xml文档,将文档在中的数据读取到内存中
操作xml文档
- 解析:将文档中的数据读取到内存中
- 写入:将内存中的数据保存代xml文档中。持久化的存储
常见的解析方式。
- DOM:【服务端】将标记语言文档一次性加载进内存,在内存中生成一颗dom树
- 优点:操作方便,CRUD操作(增删改查)
- 确定:占用内存
- SAX:【移动端】逐行读取,基于事件驱动(根据当前读的内容去触发一些事件),读一行,释放一行
- 优点:节省内存,适合手机
- 缺点:只能读取,不能增删改
常见的解析器【工具包】
- JASP:【基本没人用】sun公司提供的解析器,支持dom和sax两种思想,
- DOM4J:【自学】很优秀的解析器
- Jsop:【掌握】使用方便,Java的html解析器,可直接解析某个URL地址,HTML文本内容。可通过DOM,CSS以及类似于JQuery的操作方法;哎取出的操作数据。
- PULL: Android操作系统内置的解析器,sax方式的
四、Jsop解析器的使用
Jsop解析html的,也可以解析xml,很好用
1.使用步骤
- 导入jar包:
jsopu-1.11.2.jar
- 获取
Document
对象 - 获取对应的标签Element对象
- 获取数据
入门二案例:(src下有student.xml文件)
// 获取xml路径字符串
String url = Demo01.class.getClassLoader().getResource("student.xml").getPath();
// 获取Document对象
Document document = Jsoup.parse(new File(url),"utf8");
// 获取Elements对象
Elements elements = document.getElementsByTag("name");
// 获取Element对象
Element element = elements.get(0);
System.out.println(element.text());
2.Jsoup内常见的对象
-
Jsoup
:工具类,解析html或xml文档,返回Document-
parse
: 很多重载,解析html或xml文档,返回Document-
parse(File in, String charsetName)
:解析xml或者html文件 -
parse(URL url, int timeoutMillis)
:去匹配一个url,通过网络路径获取html或者xml的Document文档对象Jsup.parse(new URL("http://www.xxx.com/xx/xx.xml"), 5)
-
parse(String html)
:【不使用】解析html或者xml字符串
-
-
-
Document
: 【继承自Element对象】文档对象。代表内存中的dom树,继承自Element-
getElementById(String id)
: 根据id属性值获取唯一的Element对象 -
getElementsByTag(String tagName)
:根据标签名称获取Element对象集合。 -
getElementsByAttribute(String key)
:根据属性名称获取Element对象集合。 -
getElementsByAttributeValue(String key, String value)
:滚局对应的属性名和属性值获取元素对象集合
-
Elements
: 元素Element对象的集合。可以当做ArrayList<Element>来使用【继承的ArrayList<Element>】-
Element
: 【继承自Node】元素对象。-
获取子元素Element对象【与Document的一样】
-
getElementById(String id)
: 根据id属性值获取唯一的Element对象 -
getElementsByTag(String tagName)
:根据标签名称获取Element对象集合。 -
getElementsByAttribute(String key)
:根据属性名称获取Element对象集合。 -
getElementsByAttributeValue(String key, String value)
:滚局对应的属性名和属性值获取元素对象集合
-
-
获取属性值
-
String attr(String key)
: 根据属性名称获取属性值
-
-
获取文本内容
-
String text()
: 获取所有文本内容和子标签文本内容 -
String html()
: 获取标签题的所有内容(包括子标签的字符串内容)
-
-
-
Node
:节点对象【了解即可,可查API】:Document,Element的父类-
Element first()
:获得第一个Element。 -
Element lastI()
:获得最后一个。
-
3.快捷的查询方式
- selector:选择器
- xPath:
student.xml内容
<?xml version="1.0" encoding="UTF-8" ?>
<students>
<student number="s001">
<name id="nameOne">
<inner>tom</inner>
</name>
<age>20</age>
<sex>male</sex>
</student>
<student number="s002">
<name id="nameTwo">rose</name>
<age>18</age>
<sex>female</sex>
</student>
</students>
1.selector方式
通过Document的实例对象进行调用
- 使用的方法:
Elements select(String cssQuery)
- cssQuery语法:就是css的一些高低级选择器W3CSchool,参考Selector类中定义的方法【提供的API文档】;
// 获取xml路径字符串
String path = Demo01.class.getClassLoader().getResource("student.xml").getPath();
// 获取Document对象
Document document = Jsoup.parse(new File(path), "utf8");
获取Element列表【html中属性值不能加引号!】
Elements cssSelector = document.select("student[number='s002'] > sex");
System.out.println(cssSelector.get(0).text()); // female
2.xPath方式
xPath: xml路径语言,确定xml文档中莫部分位置的语言
在w3cSchool中有文档
- 使用步骤,【同样需要获取Document实例对象】
- 与Jsoup关系不大!使用Jsoup的xPath需要额为导包
JsoupXpath-0.3.2.jar
- 通过Jsoup获取Document实例对象,
Document Jsoup.parse(new File(String path), "utf8");
- 创建JXDocument对象:
JXDocument JXDocument(Document d);
- 结合xPath语法进行查询:
List<JXNode> jxDocument.selN("String pathLaguage")
- 与Jsoup关系不大!使用Jsoup的xPath需要额为导包
// 获取student.xml路径字符串
String path = Main.class.getClassLoader().getResource("student.xml").getPath();
// 获得Document对象
Document document = Jsoup.parse(new File(path), "utf8");
// Document对象创建JXDocument对象
JXDocument jxDocument = new JXDocument(document);
/*@_@ 根据xPath语法规则进行查询 @_@*/
// -- 查询所有student标签
List<JXNode> jxNodes1 = jxDocument.selN("//student");
// -- 查询所有student标签下的name标签
List<JXNode> jxNOdes2 = jxDocument.selN("//student/name");
// -- 查询student标签下带有id属性的name=标签
List<JXNode> jxNodes3 = jxDocument.selN("//student/name[@id]");
// -- 查询student标签下带有id属性的name="nameTwo"标签
List<JXNode> jxNodes4 = jxDocument.selN("//student/name[@id='nameTwo']");
五、DOM4J:很优秀的解析器
一、基本使用
- 导包:
dom4j-1.6.1.jar
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.util.List;
public class Dome01 {
public static void main(String[] args) throws DocumentException {
// 1. 创建对象
SAXReader sr = new SAXReader();
// 2.获取xml文件路径
String path = Dome01.class.getClassLoader().getResource("student.xml").getPath();
// 3.获取Document对象
Document read = sr.read(new File(path));
// Document read = reader.read(Dom4jXpath.class.getClassLoader().getResourceAsStream("student.xml"));
// 4.获取根元素
Element root = read.getRootElement();
// 5.获取某个元素下的子元素
Element son = root.element("student");
// 6.1获取元素的子元素集合
List<Element> list = son.elements();
// 6.2获取某个元素下的指定名字的子元素jihe
List<Element> list1 = son.elements("student");
// 7. 获取元素属性的值:
String val = son.attributeValue("number");
// 8. 获取元素的内容
String val2 = son.getText();
}
}
二、选择器使用,结合xPath语法
- 导包
dom4j-1.6.1.jar
jaxen-1.1-beta-6.jar
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.util.List;
public class Demo02 {
public static void main(String[] args) throws DocumentException {
SAXReader sr = new SAXReader();
String path = Demo02.class.getClassLoader().getResource("student.xml").getPath();
Document read = sr.read(new File(path));
// Document read = reader.read(Dom4jXpath.class.getClassLoader().getResourceAsStream("student.xml"));
// 获取单个节点
Element xin_element = (Element) document.selectSingleNode("//xing");
String xin_attributeValue = xin_element.attributeValue("fasd");
String xin_elementText = xin_element.getText();
// 1. 获取节点集合【结合】
List<Node> list = read.selectNodes("students/student/age");
for (Node node : list) {
// 2. 获取节点名称
String name = node.getName();
// 3.获取节点值
String text = node.getText();
}
System.out.println("-----------------------");
List<Node> list1 = read.selectNodes("students/student");
for (Node node : list1) {
// 4.获取节点的属性值
String s = node.valueOf("@number");
}
}
}