相关链接
目录
All From 传智培训课程 + 后期自己整理补充内容
P19 【xml】CDATA、约束(dtd,schema)、解析(dom,sax)、Jsoup(爬虫)、selector、Xpath
- 今日要掌握的内容:
- 【理解】理解xml文件的作用
- 【应用】掌握xml文件的组成部分及如何编写
- 【理解】理解xml的两种约束格式
- 【应用】理解xml两种解析方式的原理
- 【应用】掌握Jsoup的常用方法
1 xml
1.1 xml概述
1.概念: xml语言是可扩展的标记语言(eXtensible Markup Language),它被设计的宗旨是描述数据,而非显示数据。
可扩展:标签都是自定义的 <user> <student>
xml设计之初用来代替html,失败后用来代替properties
2.作用:用来存储数据。(a.存储一对多的数据关系、b.当做配置文件存储数据、c.在网络中传输)
3.xml与html的区别:
a. xml使用自定义标签 。 HTML需要使用预定义标签 ;
b. xml的语法严格,html语法松散
c.xml是存储数据的,html是展示数据的
<!--properties实现存储-->
name=zhangsan
age=23
gender=nan
name=lisi
age=24
gender=nv
<!--xml实现存储-->
<users>
<user id='1'>
<name>zhangsan</name>
<age>23</age>
<gender>nan</gender>
</user>
<user id='2'>
<name>lisi</name>
<age>24</age>
<gender>nv</gender>
</user>
</users>
XML技术是W3C组织(World Wide Web Consortium万维网联盟)发布的,目前遵循的是W3C组织于2000年发布的XML1.0规范。
XML被广泛认为是继Java之后在Internet上最激动人心的新技术。
举例:
通过xml实现存储:
<?xml version='1.0' encoding='UTF-8' ?>
<中国>
<北京>
<海淀>1</海淀>
<丰台>2</丰台>
</北京>
<山东>
<济南>3</济南>
<青岛>4</青岛>
</山东>
<湖北>
<武汉>5</武汉>
<荆州>6</荆州>
</湖北>
</中国>
以上这种数据,如果通过我们学习的集合来存储的话, 需要通过多个集合的嵌套使用。那么很显然, 数据存储的过程就非常麻烦, 今天所学习的xml文件就可以实现 => 存储一对多的数据
另外, xml还有一些其他的应用方面:
之前学习过properties配置文件, 通过这种配置文件, 可以使代码的编写更加灵活。但是这种配置文件也只能存储一个键值对的映射关系, 如果需要存储多个呢?没错, 可以使用xml , 所以xml的另一方面应用就展示出来了 => 用来当做配置文件存储数据。
xml技术用于解决什么问题
xml语言出现的根本目的在于描述像上图出现的那种有关系的数据。
xml是一种通用的数据交换格式。
xml语言中,允许用户自定义标签。一个标签用于描述一段数据;一个标签可分为开始标签和结束标签,在起始标签之间,又可以使用其他标签描述其他数据,一次来实现数据关系的描述。
xml中的数据必须通过软件程序来解析执行或显示,如IE;这样的解析程序称之为Parser(解析器)。
xml常见应用
在Java开发中,传统的配置文件是*.properties属性文件(key=value),而xml标示的数据更为丰富。
xml技术除用于描述有关的数据外,还经常用作软件配置文件,以描述程序模块之间的关系。(Struts、Spring、Hibernate框架都是基于XML作为配置文件的)
在一个软件系统中,通过xml配置文件可以提高系统的灵活性。即程序的行为是通过xml文件来配制的,而不是硬编码
xml是怎样存储数据的?
答: 以标签的形式存储
例: <name>Java<name>
1.2 xml语法
基本语法
1. xml 文档后缀名.xml
2. xml第一行必须定义文档声明
3. xml 有且只有一个根标签
4. 元素的属性值必须使用引号(单双都可)引起来
5. 标签必须正确关闭 => <name>a</name>
或自闭和标签<br/>
6. xml标签名区分大小写
1.3 xml组成部分
1.3.1 文档声明
* 在编写XML文档时,需要先使用文档声明来声明XML文档。且必须出现在文档的第一行
a.格式:<?xml 属性列表 ?>
b.属性列表:
* version:版本号,必填
* encoding:编码方式,告知解析引擎,当前文档使用的字符集;默认:IOS-8859-1;选填
* standalone:是否独立,一般省略不填;选填
* 取值:
* yes:不依赖其他文件
* no:依赖其他文件
<?xml version="1.0" encoding="utf-8" standalone='yes' ?>
<users></users>
1.3.2 指令(了解)
* 案例需求:xml引用css样式,所有name标签渲染字体为红色
* xml文件
* xml文件
<?xml version="1.0" encoding="utf-8" standalone='yes' ?>
<?xml-stylesheet type="text/css" href="a.css" ?>
<users></users>
* css文件
name{
color:red
}
1.3.3 标签
* 概念:xml的元素叫做标签,标签名称是自定义的
* 规则:
1. 名称可以包含字母、数字以及其他字符
2.名称不能以数字或标点符号开始
3. 名称不能以字母 xml(或者XML、Xml 等等)开始
4.名称不能包含空格、制表符
5. 严格区分大小写;<p>与<P>
6. 名称字符之间不能使用冒号 : (有特殊用途)
* 分类:
包含标签体: 尖括号全部成对出现,所有数据用一对尖括号存储
<student>
<name>zhangsan</name>
<age>18</age>
</student>
不包含标签体: 只有最外层的一个尖括号,括号用/标识结束,内部的数据都用属性来编写
<student
name='zhangsan'
age='18'
/>
1.3.4 属性
* 1. 一个元素可以有多个属性,每个属性都有它自己的名称(K)和取值(V)。
* 2. 属性值一定要用引号(单引号或双引号)引起来。
* 3. 属性名称的命名规范与元素的命名规范相同
* 4. 元素中的属性不允许重复的
* 5. 在XML技术中,标签属性所代表的信息也可以被改成用子元素的形式来描述
<?xml version='1.0' encoding='UTF-8'?>
<students>
<student name='zhangsan' age='18' />
<!-- 在XML技术中,标签属性所代表的信息也可以被改成用子元素的形式来描述 -->
<student>
<name>zhangsan</name>
<age>18</age>
</student>
</students>
1.3.5 文本 CDATA区
详见1.4
* CADATA区:在该区域中的数据会被原样展示
* 格式:<![CDATA[ 数据 ]]>
1.3.6 注释
<!--注释内容-->
1.3.7 PI
处理指令(PI:Processing Instruction)
1.4 xml特殊符号处理
1.4.1 CDATA区
为什么要使用CDATA区?
如果我们在标签中写入的内容,想要带有标签的标记符号的话,就需要对这段内容进行转义。
就好比java中的打印语句,想要打印出”这个字符就必须用\进行转义。
标签也是一样,想要将<itheima>当做内容存储的话,就需要对他进行转义。
<![CDATA[ ... ]]>
如何转义?
特殊字符 | 替代符号 |
---|---|
& | & |
< | < |
> | > |
" | " |
’ | ' |
注意:
这种转义可以达到效果,但是如果操作的数据过多,编写起来会非常痛苦,所以,可以使用CDATA区来解决此问题。
1.4.2 CDATA示例
案例代码一 xml特殊符号的处理
<?xml version='1.0' encoding='UTF-8'?>
<!--
@introduction xml特殊符号处理
如果有一个包含标签体的标签,
他的标签体是一个普通文本,不是子标签,
而普通文本中包含了一个标签,那这样可以吗?
xml特殊符号有两种实现方式
1.CDATA区
2.转义
-->
<students>
<student>
<name>zhangsan</name>
<!--1.CDATA区方式-->
<url>
<![CDATA[
<itheima>www.itheima.com</itheima>
<itcast>www.itcast.cn</itcast>
]]>
</url>
</student>
<student>
<name>zhangsan</name>
<!--2.转义方式-->
<url>
<itheima>www.itheima.com</itheima>
</url>
</student>
</students>
1.5 xml约束
1.5.1 xml约束概述
约束: 规定xml文档的书写规则
* 作为框架的使用者(程序员)
1. 能够在xml中引入约束文档
2. 能够简单读懂约束文档(IDEA也会给出智能提示)
* 分类
1. DTD:一种简单的约束技术
2. Schema:一种复杂的约束技术
* DTD:
* 引入dtd文档到xml文档中
* a. 内部dtd:将约束规则定义在xml文档中
* b. 外部dtd:将约束规则定义外部的dtd文件中
* 本地:<!DOCTYPE 根标签名称 SYSTEM "dtd文件的位置"
* 网络:<!DOCTYPE 根标签名称 PUBLIC "dtd文件名字" "dtd文件的位置URL"
1.5.2 xml约束-dtd
1.5.2.1 外部DTD(本地)
DTD约束文档 student.dtd
<!ELEMENT students (student*)>
<!ELEMENT student (name,age,gender)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT gender (#PCDATA)>
<!ATTLIST student number ID #REQUIRED>
XML文档(外部引入DTD) student.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE students SYSTEM "student.dtd">
<students>
<student number="s001">
<name>zhangsan</name>
<age>23</age>
<gender>male</gender>
</student>
<student number="ccc">
<name>lisi</name>
<age>24</age>
<gender>female</gender>
</student>
</students>
DTD约束文档说明 student.dtd
<!--声明一个标签,标签名称为students-->
<!--students可以存放student子标签-->
<!--量词符号*表示student可以出现0次或多次,如果是+则表示1次或多次-->
<!ELEMENT students (student*)>
<!--student标签可以出现 name age gender三种子标签,各个子标签需要按顺序出现-->
<!--没有量词符号表示各个子标签只能出现一次-->
<!ELEMENT student (name,age,gender)>
<!--#PCDATA 表示数据内容是字符串-->
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT gender (#PCDATA)>
<!--ATTLIST 表示student标签有属性,属性名字为number-->
<!--ID 表示number属性必须唯一,且非空-->
<!--#REQUIRED 表示number属性必须出现-->
<!ATTLIST student number ID #REQUIRED>
XML文档(如何引入路径的)
1.5.2.1 内部DTD(本地)
XML文档(内部引入DTD) student.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE students [
<!ELEMENT students (student+)>
<!ELEMENT student (name,age,gender)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT gender (#PCDATA)>
<!ATTLIST student number ID #REQUIRED>
]>
<students>
<student number="s001">
<name>zhangsan</name>
<age>23</age>
<gender>male</gender>
</student>
<student number="ccc">
<name>lisi</name>
<age>24</age>
<gender>female</gender>
</student>
</students>
1.5.3 xml约束-shcema(.xsd)
XML文档(使用空前缀) student.xml
<?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">
<xsd:sequence>
<xsd:element name="student" type="studentType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="studentType">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="age" type="ageType"/>
<xsd:element name="gender" type="genderType"/>
</xsd:sequence>
<xsd:attribute name="number" type="numberType" use="required"/>
</xsd:complexType>
<xsd:simpleType name="genderType">
<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:maxExclusive 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>
XML文档(使用前缀) student2.xml
<?xml version="1.0" ?>
<!--使用前缀的方式,这种方式可以引用多个约束
空前缀和使用前缀两种方式可以同时使用
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"
-->
<a:students xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.itcast.cn/xml student2.xsd"
xmlns:a="http://www.itcast.cn/xml"
>
<!--<student number="abc"> 报错-->
<a:student number="heima_0001">
<a:name>zhangsan</a:name>
<a:age>23</a:age>
<!--<gender>nan</gender> 报错-->
<a:gender>male</a:gender>
</a:student>
<a:student number="heima_0002">
<a:name>lisi</a:name>
<a:age>11</a:age>
<a:gender>female</a:gender>
</a:student>
</a:students>
schema约束文档 student.xsd
<?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">
<xsd:sequence>
<xsd:element name="student" type="studentType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="studentType">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="age" type="ageType"/>
<xsd:element name="gender" type="genderType"/>
</xsd:sequence>
<xsd:attribute name="number" type="numberType" use="required"/>
</xsd:complexType>
<xsd:simpleType name="genderType">
<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:maxExclusive 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>
schema约束文档说明 student.xsd
<?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">
<!--sequence:按顺序出现student元素-->
<xsd:sequence>
<!--type:studentType student元素类型为 studentType类型-->
<!--minOccurs=“0” 最少出现0次-->
<!--maxOccurs="unbounded" 最多出现无数次-->
<xsd:element name="student" type="studentType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="studentType">
<!--sequence 按name,age,gender顺序出现student属性-->
<xsd:sequence>
<!--xsd:string 字符串类型-->
<xsd:element name="name" type="xsd:string"/>
<!--type="ageType" 自定义类型,在下方 <xsd:simpleType name="ageType"> 中有详细定义-->
<xsd:element name="age" type="ageType"/>
<!--type="genderType" 自定义类型,在下方 <xsd:simpleType name="genderType"> 中有详细定义-->
<xsd:element name="gender" type="genderType"/>
</xsd:sequence>
<xsd:attribute name="number" type="numberType" use="required"/>
</xsd:complexType>
<xsd:simpleType name="genderType">
<!--restriction 元素定义对 simpleType、simpleContent 或 complexContent 定义的约束。-->
<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:maxExclusive value="256"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="numberType">
<xsd:restriction base="xsd:string">
<!--numberType数据格式: heima_四位数字-->
<xsd:pattern value="heima_\d{4}"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
2 解析xml文件
解析: 操作xml文档,将文档中的数据读取到内存中
* 操作xml文档
* 1. 解析(读取):将文档中的数据读取到内存中
* 2. 写入:将内存中的数据保存到xml文档中。持久化的存储
2.1 XML解析(2种方式)
* 解析xml的方式
* 1. DOM:将标记语言文档一次性加载进内存,在内存中会形成一颗dom树
* 优点:操作方便,可以对文档进行CURD的所有操作
* 缺点:比较占内存
* 2. SAX:逐行读取,基于事件驱动的。
* 优点:不占内存,适用小内存设备,比如:手机
* 缺点:只能读取,不能增删改;且代码编写难度会更大(需要判断各种标签的处理逻辑)。
2.2 xml常见的解析器
* 1. JAXP:sun公司提供的解析器,支持dom和sax两种思想。(官方提供,性能低,代码复杂,基本没人用)
* 2. DOM4J:一款非常优秀的解析器,支持dom,sax和jaxp。
* 3. Jsoup:是HTML解析器,可直接解析某个URL地址、HTML文本内容。可通过dom,css以及类似于jQuery的操作方法操作数据。
* 4. PULL:Android操作系统内置的解析器,sax方式。
3 Jsoup(可用于爬虫)
3.1 Jsoup快速入门
* 步骤
1. 导入jar包(pom.xml中添加依赖)
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.2</version>
</dependency>
2. 获取Document对象
3. 获取对应的标签Element对象
4. 获取数据
案例代码四 Jsoup快速入门 【student.xml】
maven项目放到resources目录下,普通java项目直接放到src目录下
<?xml version="1.0" ?>
<students>
<student number="heima_0001">
<name>zhangSan</name>
<age>23</age>
<gender>male</gender>
</student>
<student number="heima_0002">
<name>liSi</name>
<age>11</age>
<gender>female</gender>
</student>
</students>
案例代码四 Jsoup快速入门 【测试类】
package com.groupies.base.day19.Demo04;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.File;
import java.io.IOException;
import java.net.URL;
/**
* @author GroupiesM
* @date 2021/06/16
* @introduction Jsoup快速入门
*
* 步骤
*
* 1. 导入jar包(pom.xml中添加依赖)
* <dependency>
* <groupId>org.jsoup</groupId>
* <artifactId>jsoup</artifactId>
* <version>1.11.2</version>
* </dependency>
* 2. 获取Document对象
* 2.1 根据xml文档获取
* 2.2
* 2.3
* 3. 获取对应的标签Element对象
* 4. 获取数据
*/
public class JsoupLearn {
public static void main(String[] args) throws IOException {
//2.1 获取Document对象(根据xml文档获取)
//2.1.1 获取student.xml的path
ClassLoader classLoader = JsoupLearn.class.getClassLoader();
URL resource = classLoader.getResource("student.xml");
String path = resource.getPath();
//2.1.2 解析xml文档,加载文档进内存,获取dom树--->Document对象 (编码方式要和student.xml编码一致)
Document document = Jsoup.parse(new File(path), "utf-8");
//3 获取元素对象
/* Elements父类
Elements extends ArrayList<Element>
*/
Elements nameList = document.getElementsByTag("name");
System.out.println(nameList.size());
//3.1 获取第一个name的Element对象
Element element = nameList.get(0);
/*
<name>
zhangSan
</name>
*/
System.out.println(element);
//3.2获取数据
String name = element.text();
System.out.println(name);//zhangSan
}
}
3.2 Jsou对象
* 对象的使用
* 1. Jsoup:工具类,可以解析html或xml文档,返回Document;
* 1. parse:工具类,可以解析html或xml文档,返回Document;
* parse(File in,String charsetName):解析xml或html文件的
* parse(String html):解析xml或html字符串
* parse(URL url,int timeoutMillis): 通过网络路径获取指定的htmlo或xml文档对象,可用于爬虫
* 2. Document:文档对象。代表内存中的dom树;(Document extends Element)
* 2.1 返回Elements
* getElementsByTag(String tagName):根据标签名称获取元素集合
* getElementsByAttribute(String key):根据属性名称获取元素对象集合
* getElementsByAttributeValue(String key,String value):根据对应的属性名和属性值获取元素对象集合
* 2.2 返回Element
* getElementsById(String id):根据id属性值获取惟一的元素对象
(xml中不常用此方法,xml可以自定义标签。在html中id是预定义标签,表示主键)
* 3. Elements:元素Element对象的集合。可以当做ArrayList<Element>来使用(Element extends Node);
* 4. Element:元素对象;
* 4.1返回子标签Element
* getElementsById(String id):根据id属性值获取惟一的子标签元素对象
(xml中不常用此方法,xml可以自定义标签。在html中id是预定义标签,表示主键)
* 4.2 返回子标签Elements
* getElementsByTag(String tagName):根据标签名称获取子标签元素对象集合
* getElementsByAttribute(String key):根据属性名称获取子标签元素对象集合
* getElementsByAttributeValue(String key,String value):根据对应的属性名和属性值获取子标签元素对象集合
* 4.3 返回String
* attr(String key):根据属性名称获取属性值
* text():获取子标签的纯文本内容
* html():获取标签体的所有内容(包括子标签的标签和文本内容)
* 4.3 修改属性值
* 5. Node:节点对象,是Document和Element的父类;
* 返回Node
* childNode(int index):返回指定索引的子节点对象
* 返回ListNode
* childNodes():返回所有子节点对象
* 返回boolean
*hasAttr(String attributeKey):判断元素有没有属性
* 无返回值
*remove():从dom树删除此节点
3.2.1 Jsoup 工具类
* 1. Jsoup:工具类,可以解析html或xml文档,返回Document;
* 1. parse:工具类,可以解析html或xml文档,返回Document;
* parse(File in,String charsetName):解析xml或html文件的
* parse(String html):解析xml或html字符串
* parse(URL url,int timeoutMillis): 通过网络路径获取指定的htmlo或xml文档对象,可用于爬虫
- 静态成员方法
//方式1 解析xml或html文件的
parse(File in,String charsetName)
//方式2 解析xml或html字符串
parse(String html)
//方式3 通过网络路径获取指定的htmlo或xml文档对象,可用于爬虫
parse(URL url,int timeoutMillis)
案例代码五 Jsoup工具类 【student.xml】
maven项目放到resources目录下,普通java项目直接放到src目录下
<?xml version="1.0" ?>
<students>
<student number="heima_0001">
<name>zhangSan</name>
<age>23</age>
<gender>male</gender>
</student>
<student number="heima_0002">
<name>liSi</name>
<age>11</age>
<gender>female</gender>
</student>
</students>
案例代码五 Jsoup工具类 【测试类】
package com.groupies.base.day19.Demo05;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import java.io.File;
import java.io.IOException;
import java.net.URL;
/**
* @author GroupiesM
* @date 2021/06/16
* @introduction Jsoup工具类
*
* //方式1 解析xml或html文件的
* parse(File in,String charsetName)
*
* //方式2 解析xml或html字符串
* parse(String html)
*
* //方式3 通过网络路径获取指定的htmlo或xml文档对象,可用于爬虫
* parse(URL url,int timeoutMillis)
*/
public class JsoupObject {
public static void main(String[] args) throws IOException {
//获取student.xml的path
ClassLoader classLoader = JsoupObject.class.getClassLoader();
URL resource = classLoader.getResource("student.xml");
String path = resource.getPath();
//方式1:parse(File in,String charsetName):解析xml或html文件的
// 加载文档进内存,获取dom树---> Document对象 (编码方式要和student.xml编码一致)
Document document1 = Jsoup.parse(new File(path), "utf-8");
/*
<!--?xml version="1.0" ?-->
<html>
<head></head>
<body>
<students>
<student number="heima_0001">
<name>
zhangSan
</name>
<age>
23
</age>
<gender>
male
</gender>
</student>
<student number="heima_0002">
<name>
liSi
</name>
<age>
11
</age>
<gender>
female
</gender>
</student>
</students>
</body>
</html>
*/
System.out.println(document1);
System.out.println("===================");
//方式2:parse(String html):解析xml或html字符串
Document document2 = Jsoup.parse("<?xml version=\"1.0\" ?>\n" +
"<students>\n" +
" <student number=\"heima_0001\">\n" +
" <name>zhangSan</name>\n" +
" <age>23</age>\n" +
" <gender>male</gender>\n" +
" </student>\n" +
" <student number=\"heima_0002\">\n" +
" <name>liSi</name>\n" +
" <age>11</age>\n" +
" <gender>female</gender>\n" +
" </student>\n" +
"</students>");
//同上
System.out.println(document2);
System.out.println("===================");
//方式3:parse(URL url,int timeoutMillis): 通过网络路径获取指定的htmlo或xml文档对象
URL url = new URL("https://baike.baidu.com/item/jsoup/9012509");//代表网络中的一个资源路径
Document document3 = Jsoup.parse(url, 10000);
/*
<!doctype html>
<!--STATUS OK-->
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="referrer" content="always">
<meta name="description" content="jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。...">
<title>jsoup_百度百科</title>
......略
*/
System.out.println(document3);
}
}
3.2.2 Document 文档对象(dom树对象)
* 2. Document:文档对象。代表内存中的dom树;(Document extends Element)
* 2.1 返回Element
* getElementsById(String id):根据id属性值获取惟一的元素对象
(xml中不常用此方法,xml可以自定义标签。在html中id是预定义标签,表示主键)
* 2.2 返回Elements
* getElementsByTag(String tagName):根据标签名称获取元素集合
* getElementsByAttribute(String key):根据属性名称获取元素对象集合
* getElementsByAttributeValue(String key,String value):根据对应的属性名和属性值获取元素对象集合
案例代码六 Document文档对象 【student2.xml】
maven项目放到resources目录下,普通java项目直接放到src目录下
<?xml version="1.0" ?>
<students>
<student number="heima_0001">
<name id="itcast">zhangSan</name>
<age>23</age>
<gender>male</gender>
</student>
<student number="heima_0002">
<name>liSi</name>
<age>11</age>
<gender>female</gender>
</student>
</students>
案例代码六 Document文档对象 【测试类】
package com.groupies.base.day19.Demo07;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.File;
import java.io.IOException;
import java.net.URL;
/**
* @author GroupiesM
* @date 2021/06/16
* @introduction Element文档对象
*
* 2. Document:文档对象。代表内存中的dom树;(Document extends Element)
*
* 返回Element
* //方式1:根据id属性值获取惟一的元素对象(xml中不常用,在html中id是预定义标签,表示主键)
* getElementsById(String id)
*
* 返回Elements
* //方式2:根据标签名称获取元素集合
* getElementsByTag(String tagName)
*
* //方式3:根据属性名称获取元素对象集合
* getElementsByAttribute(String key)
*
* //方式4:根据对应的属性名和属性值获取元素对象集合
* getElementsByAttributeValue(String key,String value)
*/
public class JsoupObjectElement {
public static void main(String[] args) throws IOException {
//获取student.xml的path
ClassLoader classLoader = JsoupObjectElement.class.getClassLoader();
URL resource = classLoader.getResource("student2.xml");
String path = resource.getPath();
//获取Document对象
Document document = Jsoup.parse(new File(path), "utf-8");
//1.获取元素对象
//1.1 获取id为为itcast的对象集合
//方式1:getElementsById(String id) 根据id属性值获取惟一的元素对象(xml中不常用,在html中id是预定义标签,表示主键)
Element element1 = document.getElementById("itcast");
/* zhangSan */
System.out.println(element1.text());
System.out.println("===================");
//1.2 获取所有Student对象
//方式2:getElementsByTag(String tagName) 根据标签名称获取元素集合
Elements element2 = document.getElementsByTag("student");
for (Element element : element2) {
/*zhangSan 23 male
liSi 11 female*/
System.out.println(element.text());
}
System.out.println("===================");
//1.3 获取属性名为id的元素对象集合
//方式3:getElementsByAttribute(String key) 根据属性名称获取元素对象集合
Elements element3 = document.getElementsByAttribute("id");
for (Element element : element3) {
/* zhangSan */
System.out.println(element.text());
}
System.out.println("===================");
//1.4 获取number属性值为heima_0001的元素对象
//方式4:getElementsByAttributeValue(String key,String value) 根据对应的属性名和属性值获取元素对象集合
Elements element4 = document.getElementsByAttributeValue("number", "heima_0001");
for (Element element : element4) {
/* zhangSan 23 male */
System.out.println(element.text());
}
}
}
3.2.3 Elements 元素对象集合
Elements extends ArrayList<Element>
* 3. Elements:元素Element对象的集合。可以当做ArrayList<Element>来使用(Element extends Node);
3.2.4 Element 元素对象
* 4. Element:元素对象;
* 4.1 返回子标签Elements
* getElementsByTag(String tagName):根据标签名称获取子标签元素对象集合
* getElementsByAttribute(String key):根据属性名称获取子标签元素对象集合
* getElementsByAttributeValue(String key,String value):根据对应的属性名和属性值获取子标签元素对象集合
* 4.2 返回子标签Element
* getElementsById(String id):根据id属性值获取惟一的子标签元素对象
(xml中不常用此方法,xml可以自定义标签。在html中id是预定义标签,表示主键)
* 4.3 返回String
* attr(String key):根据属性名称获取属性值
* text():获取所有子标签的纯文本内容
* html():获取标签体的所有内容(包括子标签的标签和文本内容)
* 4.4 修改属性值
案例代码七 Element元素对象 【student3.xml】
maven项目放到resources目录下,普通java项目直接放到src目录下
<?xml version="1.0" ?>
<students>
<student number="heima_0001">
<name id="itcast" class="5">
<firstName>张</firstName>
<secondName>三</secondName>
</name>
<age>23</age>
<gender>male</gender>
</student>
<student number="heima_0002">
<name id="itheima">liSi</name>
<age>11</age>
<gender class="6">female</gender>
</student>
</students>
案例代码七 Element元素对象 【测试类】
package com.groupies.base.day19.Demo07;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.File;
import java.io.IOException;
import java.net.URL;
/**
* @author GroupiesM
* @date 2021/06/16
* @introduction Element元素对象
*
* 4.1 返回子标签Elements
* //方式1 根据标签名称获取子标签元素对象
* getElementsByTag(String tagName)
*
* //方式2 根据属性名称获取子标签元素对象
* getElementsByAttribute(String key)
*
* //方式3 根据对应的属性名和属性值获取子标签元素对象
* getElementsByAttributeValue(String key,String value)
*
* 4.2 返回子标签Element
* //方式4 根据id属性值获取惟一的子标签元素对象(xml中不常用此方法,xml可以自定义标签。在html中id是预定义标签,表示主键)
* getElementsById(String id):
*
* 4.3 返回String
* //方式5 根据属性名称获取属性值
* attr(String key)
*
* //方式6 获取所有子标签的纯文本内容
* text()
*
* //方式7 获取标签体的所有内容(包括子标签的标签和文本内容)
* html()
*/
public class JsoupObjectElement {
public static void main(String[] args) throws IOException {
//获取student.xml的path
ClassLoader classLoader = JsoupObjectElement.class.getClassLoader();
URL resource = classLoader.getResource("student3.xml");
String path = resource.getPath();
//获取Document对象
Document document = Jsoup.parse(new File(path), "utf-8");
Element element_0 = document.getElementsByTag("name").get(0);
Element element_1 = document.getElementsByTag("name").get(1);
//获取name标签
//通过Document对象获取name标签,获取所有的name标签,可以获取到2个
Elements elements = document.getElementsByTag("name");
/* 2 */
System.out.println(elements.size());
System.out.println("elements===================");
//方式1 getElementsByTag(String tagName) 根据标签名称获取子标签元素对象集合
Elements element_0_2 = element_0.getElementsByTag("name");
Elements element_1_2 = element_1.getElementsByTag("name");
/* 1 */
System.out.println(element_0_2.size());
System.out.println("element_0_2===================");
/* 1 */
System.out.println(element_1_2.size());
System.out.println("element_1_2===================");
//方式2 getElementsByAttribute(String key) 根据属性名称获取子标签元素对象集合
Elements element_0_3 = element_0.getElementsByAttribute("id");
Elements element_1_3 = element_1.getElementsByAttribute("id");
/* 张 三 */
System.out.println(element_0_3.text());
System.out.println("element_0_3===================");
/* lisi */
System.out.println(element_1_3.text());
System.out.println("element_1_3===================");
//方式3 getElementsByAttributeValue(String key,String value) 根据对应的属性名和属性值获取子标签元素对象集合
Elements element_0_4 = element_0.getElementsByAttributeValue("class", "5");
Elements element_1_4 = element_1.getElementsByAttributeValue("class", "6");
/* 张 三 */
System.out.println(element_0_4.text());
System.out.println("element_0_4===================");
/* */
System.out.println(element_1_4.text());
System.out.println("element_1_4===================");
//方式4 getElementsById(String id) 根据id属性值获取惟一的子标签元素对象(xml中不常用此方法,xml可以自定义标签。在html中id是预定义标签,表示主键)
Element element_0_1 = element_0.getElementById("itcast");
Element element_1_1 = element_1.getElementById("itcast");
/* 张 三 */
System.out.println(element_0_1.text());
System.out.println("element_0_1===================");
/* null */
System.out.println(element_1_1);
System.out.println("element_1_1===================");
//方式5 attr(String key) 根据属性名称获取属性值(不区分大小写)
String str_0_5 = element_0.attr("ID");
String str_1_5 = element_1.attr("ID");
/* itcast */
System.out.println(str_0_5);
System.out.println("str_0_5===================");
/* itheima */
System.out.println(str_1_5);
System.out.println("str_1_5===================");
//方式6 text() 获取文本内容
String str_0_6 = element_0.text();
String str_1_6 = element_1.text();
/* 张 三 */
System.out.println(str_0_6);
System.out.println("str_0_6===================");
/* liSi */
System.out.println(str_1_6);
System.out.println("str_1_6===================");
//方式7 html() 获取标签体的所有内容(包括自定义子标签字符串内容)
String str_0_7 = element_0.html();
String str_1_7 = element_1.html();
/* <firstname>
张
</firstname>
<secondname>
三
</secondname> */
System.out.println(str_0_7);
System.out.println("str_0_7===================");
/* liSi */
System.out.println(str_1_7);
System.out.println("str_1_7===================");
}
}
3.2.5 Node 节点对象
* 5. Node:节点对象,是Document和Element的父类;
* 返回Node
* childNode(int index):返回指定索引的子节点对象
* 返回ListNode
* childNodes():返回所有子节点对象
* 返回boolean
*hasAttr(String attributeKey):判断元素有没有属性
* 无返回值
*remove():从dom树删除此节点
Node对象不常用,了解即可
3.3 快速查询方式
如果想获取【张】=> 需要获取student标签 下的name标签下的firstName标签下的内容,比较麻烦
String path = JsoupObjectElement1.class.getClassLoader().getResource("student3.xml").getPath();; Document document = Jsoup.parse(new File(path), "utf-8"); Elements student = document.getElementsByTag("student"); Elements name = student.get(0).getElementsByTag("name"); Elements firstName = name.get(0).getElementsByTag("firstName"); System.out.println(firstName.text());//张
现在有更快速的查询方式
* 快速查询方式
* 1. selector:选择器
* 所在类:Element、Document(Element子类)
* 返回值:Elements
* 使用的方法:select(String cssQuery)
* 参数cssQuery:css选择器
* 语法:参考Selector类中定义的语法
* 2. Xpath:路径语言
* 2.1 使用Jsoup的Xpath需要额外导入jar包 maven
<dependency>
<groupId>cn.wanghaomiao</groupId>
<artifactId>JsoupXpath</artifactId>
<version>2.3.2</version>
</dependency>
* 2.2 构造方法
JXDocument jxDocument = new JXDocument(document);
* 2.3 成员方法
* Object selOne(String xpath)
* List sel(String xpath)
* List selN(String xpath)
* JXNode selNOne(String xpath)
3.3.1 selector选择器
概述:
jsoup elements对象支持类似于CSS(或jquery)的选择器语法,来实现非常强大和灵活的查找功能。
这个select
方法在Document
, Element
,或Elements
对象中都可以使用。且是上下文相关的,因此可实现指定元素的过滤,或者链式选择访问。
Select方法将返回一个Elements
集合,并提供一组方法来抽取和处理结果。
* selector:选择器
* 所在类:Element、Document(Element子类)
* 返回值:Elements
* 使用的方法:select(String cssQuery)
* 参数cssQuery:css选择器
* 语法:参考Selector类中定义的语法
案例代码八 快速查询方式1-selector选择器 【student3.xml】
maven项目放到resources目录下,普通java项目直接放到src目录下
<?xml version="1.0" ?>
<students>
<student number="heima_0001">
<name id="itcast" class="5">
<firstName>张</firstName>
<secondName>三</secondName>
</name>
<age>23</age>
<gender>male</gender>
</student>
<student number="heima_0002">
<name id="itheima">liSi</name>
<age>11</age>
<gender class="6">female</gender>
</student>
</students>
案例代码八 快速查询方式1-selector选择器 【测试类】
package com.groupies.base.day19.Demo08;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import java.io.File;
import java.io.IOException;
/**
* @author GroupiesM
* @date 2021/06/16
* @introduction 快速查询方式1-selector选择器
*/
public class JsoupSelector {
public static void main(String[] args) throws IOException {
//获取student.xml的path
String path = JsoupElementSelector.class.getClassLoader().getResource("student3.xml").getPath();
//获取Document对象
Document document = Jsoup.parse(new File(path), "utf-8");
//1.查询name标签
/* css选择器
div{
}
*/
Elements elements1 = document.select("name");
/* 张 三 liSi */
System.out.println(elements1.text());
System.out.println("===================");
//2.查询id值为itcast的元素
Elements elements2 = document.select("#itcast");
/* 张 三 */
System.out.println(elements2.text());
System.out.println("===================");
//3.获取number=heima_0001的student下的age标签的值
//3.1 获取number=heima_0001的student
Elements element3_1 = document.select("student[number='heima_0001']");
/* 张 三 23 male */
System.out.println(element3_1.text());
System.out.println("===================");
//3.2 获取student下的age标签的值
Elements element3_2 = element3_1.select("age");
/* 23 */
System.out.println(element3_2.text());
System.out.println("===================");
//3.2 直接获取student下的age标签的值
Elements element3_3 = document.select("student[number='heima_0001'] > age");
/* 23 */
System.out.println(element3_3.text());
System.out.println("===================");
}
}
3.3.1 Xpath路径语言
概述:
XPath 是一门在 XML 文档中查找信息的路径语言。
XPath 可用来在 XML 文档中对元素和属性进行遍历,确定XML文档中某部分位置。
XPath 是 W3C XSLT 标准的主要元素,并且 XQuery 和 XPointer 都构建于 XPath 表达之上。因此,对 XPath 的理解是很多高级 XML 应用的基础。
案例代码九 快速查询方式1-Xpath路径语言 【student3.xml】
maven项目放到resources目录下,普通java项目直接放到src目录下
<?xml version="1.0" ?>
<students>
<student number="heima_0001">
<name id="itcast" class="5">
<firstName>张</firstName>
<secondName>三</secondName>
</name>
<age>23</age>
<gender>male</gender>
</student>
<student number="heima_0002">
<name id="itheima">liSi</name>
<age>11</age>
<gender class="6">female</gender>
</student>
</students>
案例代码九 快速查询方式1-Xpath路径语言 【测试类】
package com.groupies.base.day19.Demo09;
import cn.wanghaomiao.xpath.model.JXDocument;
import cn.wanghaomiao.xpath.model.JXNode;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import java.io.File;
import java.io.IOException;
import java.util.List;
/**
* @author GroupiesM
* @date 2021/06/16
* @introduction 快速查询方式2-Xpath路径语言
*/
public class JsoupXpath {
public static void main(String[] args) throws IOException {
//获取student.xml的path
String path = JsoupXpath.class.getClassLoader().getResource("student3.xml").getPath();
//获取Document对象
Document document = Jsoup.parse(new File(path), "utf-8");
//1.根据document对象创建JXDocument对象
JXDocument jxDocument = new JXDocument(document);
//2.结合xpath语法查询
//2.1 查询所有student标签
List<JXNode> jxNodes1 = jxDocument.selN("//student");
for (JXNode jxNode : jxNodes1) {
/*
张 三 23 male
liSi 11 female
*/
System.out.println(jxNode.getElement().text());
}
System.out.println("========================");
//2.2 查询所有student标签下的name标签
List<JXNode> jxNodes2 = jxDocument.selN("//student/name");
for (JXNode jxNode : jxNodes2) {
System.out.println(jxNode.getElement().text());
}
System.out.println("========================");
//2.3 查询student标签下带有class属性的name标签
List<JXNode> jxNodes3 = jxDocument.selN("//student/name[@class]");
for (JXNode jxNode : jxNodes3) {
/* 张 三 */
System.out.println(jxNode.getElement().text());
}
System.out.println("========================");
//2.4 查询student标签下带有id属性的name标签,且id属性值为itheima
List<JXNode> jxNodes4 = jxDocument.selN("//student/name[@id='itheima']");
for (JXNode jxNode : jxNodes4) {
/* liSi */
System.out.println(jxNode.getElement().text());
}
System.out.println("========================");
}
}
4 Dom4J
略 ,与Jsoup功能类似,会一种即可
21/06/18
M