一、XML
1、概念
Extensible Markup Language可扩展标记语言
可扩展
标签都是自定义的 只要符合命名规范
功能
存储文件
(1)配置文件 properties文件存储简单数据
(2)在网络中传输
与html的区别
都是w3c(万维网)开发的
早期只有html,但浏览器之间的恶性竞争使得html的语法十分松散,怎么写都不会报错
于是开发了xml,但xml的语法太严格,竞争不过html,转而用来存储数据
使用标签存储数据结构很清晰,哪个属性属于哪个用户很明确
<user id='1'>
<name>zhangsan</name>
<age>22</age>
</user>
<user id='2'>
<name>lisi</name>
<age>33</age>
</user>
(1)xml标签都是自定义的,html的标签都是预定义的
(2)xml的语法严格,html的语法松散
(3)xml是存储数据的,html是展示数据的
语法
xml文档可以被大部分浏览器解析,只要将其拖进浏览器,没有报错则没有写错
基本语法
后缀名.xml
第一行必须定义为文档声明 不能空着第一行
xml文档中有且仅有一个根标签
属性值必须使用引号
围堵标签必须有结束标签,自闭合标签必须有/
xml标签名区分大小写
快速入门
<?xml version='1.0'?>
<users>
<user id="1">
<name>zhangsan</name>
<age>22</age>
<gender>male</gender>
<br/>
</user>
<user id="2">
<name>lisi</name>
<age>33</age>
<gender>female</gender>
</user>
</users>
组成部分
文档声明
格式:<?xml 属性列表?> ?和<>以及xml之间不能有空格
属性列表
version 版本号 1.0是主流版本 必须的属性
encoding 编码格式 告知解析引擎当前文档使用的字符集 默认ISO-8859-1
若与文档真实编码格式不一致,则会报错,ANSI是GBK
idea可以自己识别encoding的值,自动修改文档真实编码
standalone 是否独立,是否依赖于其它文件 大多数情况下不设置这个属性,
即使设置了yes也可以依赖于其它文件
yes 不依赖
no 依赖
指令(了解)
结合css来控制标签样式
加上<?xml-stylesheet type='text/css' href='a.css'?>之后浏览器就会解析所有标签来展示标签
内的数据
标签
名称自定义
规则:可以包含字母 数字和其它字符
不能以数字或标点符号开始
不能以xml XML Xml等开始
不能包含空格
属性
id属性值唯一
文本内容
CDATA区
该区域中数据会被原样展示
格式:<![CDATA[数据]]>
约束
概念
xml文档作为软件的配置文档,由用户来编写,由软件来解析
这里的软件指的是半成品软件,即框架,其用户是程序员
软件为xml文档的编写提供了一个说明文档,规定xml文档的书写规则,
该说明文档即为约束文档
我们只需要
(1)能在xml中引入约束文档
(2)能简单地读懂约束文档
分类
DTD 一种简单的约束技术
组成:通过ELEMENT定义标签
ATTLIST定义属性
引入:
内部dtd 将约束规则定义在xml文档中
外部dtd 将约束规则定义在外部的dtd文件中
本地
网络
缺点:
字符串内容没有约束 如age可以写为aaa
Schema 一种复杂的约束技术
引入
users.xml
<?xml version='1.0'?>
<!--<?xml-stylesheet type='text/css' href='a.css'?>-->
<users>
<user id="1">
<name>张三</name>
<age>22</age>
<gender>male</gender>
<br/>
</user>
<user id="2">
<name>lisi</name>
<age>33</age>
<gender>female</gender>
<code>
<![CDATA[
if(a > b && a > c) {}
]]>
</code>
</user>
</users>
student.dtd
<!--根标签students中包含0个或多个student标签-->
<!ELEMENT students (student*) >
<!--student标签中包含name age sex3个标签,且个数均为1 要按照顺序定义-->
<!ELEMENT student (name,age,sex)>
<!--#PCDATA指标签内容为字符串-->
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT sex (#PCDATA)>
<!--student标签有属性number 为ID类型,值唯一 #REQUIRED指该属性是必须的-->
<!ATTLIST student number ID #REQUIRED>
student.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE students SYSTEM "student.dtd">
<students>
<student number="itcast_0001">
<name>tom</name>
<age>18</age>
<sex>male</sex>
</student>
</students>
students.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!--外部引入-->
<!--<!DOCTYPE students SYSTEM "student.dtd">-->
<!--内部引入-->
<!DOCTYPE students [
<!--根标签students中包含0个或多个student标签-->
<!ELEMENT students (student*) >
<!--student标签中包含name age sex3个标签,且个数均为1 要按照顺序定义-->
<!ELEMENT student (name,age,sex)>
<!--#PCDATA指标签内容为字符串-->
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT sex (#PCDATA)>
<!--student标签有属性number 为ID类型,值唯一 #REQUIRED指该属性是必须的-->
<!ATTLIST student number ID #REQUIRED>
]>
<!--先输入<才会有代码补全-->
<students>
<student number="s001">
<name>zhangsan</name>
<age>33</age>
<sex>male</sex>
</student>
<student number="s002">
<name>lisi</name>
<age>22</age>
<sex>female</sex>
</student>
</students>
2、XML解析
操作xml文档,将文档中的数据读取到内存中
操作xml文档
解析 将文档中的数据读取到内存中
写入 将内存中的数据写入到xml文档中,持久化地存储
解析XML的方式
DOM
将标记语言文档一次性加载进内存中,在内存中形成一棵DOM树
优点
操作方便,可以对文档进行CRUD的所有操作
缺点
占内存 一般树所占内存是文档的1000到10000倍左右
不适用于内存小的设备
SAX
逐行读取,基于事件驱动
读一行释放一行,内存中只有一行
对于标签的读取 是先读取开始标签 再读取文本内容 最后读取结束标签
为了判断文本内容属于这个标签,需要基于事件驱动,
读到什么标签就触发一些事件
优点:
不占内存,适用于内存小的设备
缺点:
只能读取,不能增删改
在服务器端一般使用DOM 在移动端一般使用SAX
常见解析器
JAXP SUN公司 支持DOM和SAX思想
DOM4J 常用于移动端
JSOUP 一款Java的HTML解析器,可直接解析某个url地址、html文本内容
PULL Android操作系统内置解析器 SAX方式
二、JSOUP
1、快速入门
(1)导入jar包 将jar包复制到项目中 然后右键Add As Library…
(2)获取Document对象 其代表DOM树
(3)获取对应的标签Element对象
(4)获取数据
students.xml
<?xml version="1.0" encoding="UTF-8" ?>
<students>
<student number="heima_0001">学生1
<name id="1">张三</name>
<age>18</age>
<sex>male</sex>
</student>
<student number="heima_0002">
<name>李四</name>
<age>19</age>
<sex>female</sex>
</student>
</students>
测试类
public class Demo01Jsoup {
public static void main(String[] args) throws IOException {
//2、获取Document对象,根据xml文档获取
//2.1 获取文件对象之前先获取文件路径
String path = Demo01Jsoup.class.getClassLoader().getResource("students.xml").getPath();
//2.2 解析xml文档,加载文档进内存,获取DOM树,即Document对象
Document doc = Jsoup.parse(new File(path), "utf-8");
//3、获取标签对象 ctrl+alt+v自动生成变量 Elements继承了ArrayList,泛型是Element
Elements elements = doc.getElementsByTag("name");
for (Element element : elements) {
System.out.println(element);//<name>
//张三
//</name>
//<name>
//李四
//</name>
//获取标签内容
System.out.println(element.text());//张三
//李四
}
}
}
2、Jsoup对象的使用
Jsoup 工具类,可以解析html或xml文档,返回Document
parse 解析html或xml文档,返回Document
parse(File in, String charsetName);解析xml或html文件的
parse(String html);解析xml或html字符串
parse(URL url, int timeoutMillis);通过网络路径获取指定的html或xml文档 常用于爬虫
Document 文档对象,代表内存中的DOM树
Elements 元素Element对象的集合,可以当作ArrayList来使用
Element 元素对象
Node 节点对象,是上面3个对象的父亲
public class Demo02JsoupObject {
public static void main(String[] args) throws IOException {
//Jsoup对象
//获取Document对象
//parse(File in, String charsetName);解析xml或html文件的
String path = Demo02JsoupObject.class.getClassLoader().getResource("students.xml").getPath();
Document doc1 = Jsoup.parse(new File(path), "utf-8");
System.out.println(doc1);
/*
<!--?xml version="1.0" encoding="UTF-8" ?-->
<html>
<head></head>
<body>
<student number="heima_0001">
<name>
张三
</name>
<age>
18
</age>
<sex>
male
</sex>
</student>
<student number="heima_0002">
<name>
李四
</name>
<age>
19
</age>
<sex>
female
</sex>
</student>
</body>
</html>
*/
//parse(String html);解析xml或html字符串
String str = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
"<students>\n" +
" <student number=\"heima_0001\">\n" +
" <name>张三</name>\n" +
" <age>18</age>\n" +
" <sex>male</sex>\n" +
" </student>\n" +
" <student number=\"heima_0002\">\n" +
" <name>李四</name>\n" +
" <age>19</age>\n" +
" <sex>female</sex>\n" +
" </student>\n" +
"</students>";
Document doc2 = Jsoup.parse(str);
System.out.println(doc2);
//parse(URL url, int timeoutMillis);通过网络路径获取指定的html或xml文档
URL url = new URL("https://www.baidu.com");
Document doc3 = Jsoup.parse(url, 10000);
System.out.println(doc3);//打印出网页的html文档
}
}
3、Document对象 继承了Element对象
获取Element对象
getElementById(String id);根据id属性值获取唯一的Element对象
getElementsByTag(String tagName);根据标签名获取元素对象集合
getElementsByAttribute(String key);根据属性名获取元素对象集合
getElementsByAttributeValue(String key, String value);根据对应的属性名和属性值获取元素对象集合
public class Demo03DocumentObject {
public static void main(String[] args) throws IOException {
//获取xml文件路径
String path = Demo03DocumentObject.class.getClassLoader().getResource("students.xml").getPath();
Document doc = Jsoup.parse(new File(path), "utf-8");
//获取所有的student对象
Elements student = doc.getElementsByTag("student");
//System.out.println(student);
//获取属性名为id的元素
Elements idEle = doc.getElementsByAttribute("id");
//System.out.println(idEle);
//获取属性number为heima_0001的元素
Elements numberEle = doc.getElementsByAttributeValue("number", "heima_0001");
//System.out.println(numberEle);
//获取属性id为1的元素
Element elementById = doc.getElementById("1");
System.out.println(elementById);
}
}
4、Element元素对象
获取Element对象,这里是获取子元素
getElementById(String id);根据id属性值获取唯一的Element对象
getElementsByTag(String tagName);根据标签名获取元素对象集合
getElementsByAttribute(String key);根据属性名获取元素对象集合
getElementsByAttributeValue(String key, String value);根据对应的属性名和属性值获取元素对象集合
获取属性值
String attr(String attributeKey);根据属性名获取属性值 不区分大小写
获取文本内容
String text();
String html();获取标签体的所有内容
public class Demo04ElementObject {
public static void main(String[] args) throws IOException {
//获取xml文件的路径
String path = Demo04ElementObject.class.getClassLoader().getResource("students.xml").getPath();
//获取Document对象
Document doc = Jsoup.parse(new File(path), "utf-8");
//通过Document对象获取元素,是获取所有的name标签,有2个
Elements elementsByTag = doc.getElementsByTag("name");
System.out.println(elementsByTag.size());//2
//通过Element获取子元素 获取的是第一个student标签内的name标签,只有1个
//先获取Element对象
Elements student = doc.getElementsByTag("student");
Element stu1 = student.get(0);
Elements elementsByTag1 = stu1.getElementsByTag("name");
System.out.println(elementsByTag1.size());//1
//获取属性值
String number = stu1.attr("number");
System.out.println(number);//heima_0001
//获取文本内容
String text = stu1.text();//获取标签体的所有文本内容
System.out.println(text);//学生1 张三 18 male
String html = stu1.html();//获取标签体的所有内容
System.out.println(html);//学生1
//<name id="1">
//张三
//</name>
//<age>
//18
//</age>
//<sex>
//male
//</sex>
}
}
5、快捷查询方式-selector 选择器
Element select(String cssQuery);
参数参考Selector类中定义的语法
public class Demo05QuickQuery {
public static void main(String[] args) throws IOException {
//获取xml文件的路径
String path = Demo05QuickQuery.class.getClassLoader().getResource("students.xml").getPath();
Document doc = Jsoup.parse(new File(path), "utf-8");
//虽然select方法是在Element对象中定义的,但Document对象继承自Element对象,一般使用Document对象调用该方法
//查询name标签
Elements name = doc.select("name");
//System.out.println(name);
//查询id值为1的元素
Elements id1 = doc.select("#1");
//System.out.println(id1);
//获取属性number为heima_0001的student标签下的age标签
Elements select = doc.select("student[number='heima_0001'] age");
System.out.println(select);
}
}
6、快捷查询方式-XPath
用来确定XML文档中某部分位置的语言
使用Jsoup的XPath需要独立导入jar包
查询w3cschool参考手册,使用XPath的语法完成查询
public class Demo06XPath {
public static void main(String[] args) throws IOException, XpathSyntaxErrorException {
//获取xml文档的路径
String path = Demo06XPath.class.getClassLoader().getResource("students.xml").getPath();
//获取Document对象
Document doc = Jsoup.parse(new File(path), "utf-8");
//创建JXDocument对象 其支持XPath的语法
JXDocument jxdoc = new JXDocument(doc);
//结合XPath语法查询
//查询所有student标签 //student获取所有student标签,不考虑位置
List<JXNode> jxNodes1 = jxdoc.selN("//student");
for (JXNode jxNode : jxNodes1) {
//System.out.println(jxNode);
//将jxNode转换为Element对象,就可以很方便地获取属性值和文本内容了
Element element = jxNode.getElement();
}
//查询所有student标签下的name标签
List<JXNode> jxNodes2 = jxdoc.selN("//student/name");
for (JXNode jxNode : jxNodes2) {
//System.out.println(jxNode);
}
//查询student标签下带id属性的name标签
List<JXNode> jxNodes3 = jxdoc.selN("//student/name[@id]");
for (JXNode jxNode : jxNodes3) {
//System.out.println(jxNode);
}
//查询student标签下带id属性的name标签,且id=1
List<JXNode> jxNodes4 = jxdoc.selN("//student/name[@id='1']");
for (JXNode jxNode : jxNodes4) {
System.out.println(jxNode);
}
}
}