XML解析原理,以及用Jsoup进行XML解析

1. XML解析概述

1.1 XML解析

读取XML文件中所有的元素和数据,封装成JavaBean,或者在java中使用这些数据

1.2 解析方式
  • DOM解析

Document Object Model 文档对象模型,在内存中创建一颗DOM树。可以对这棵树进行查询,修改,删除和添加。

优点:可以方便的操作XML中任何一个节点,可以进行增删改查的操作。

缺点:如果这个XML文件很大的时候,可能会出现内存泄漏的风险。

  • SAX解析

事件驱动型解析方式,读取一行解析一行。

优点:理论上可以解析任意大小的XML文件。

缺点:不能对XML文件进行修改,只能读取。读取完毕之后不能再访问之前已经访问过的页面。

1.3 常见的XML解析开发包
开发工具包说明
JAXPOracle官方提供的API,同时支持DOM和SAX的开发
JDOMJDOM是一个开源项目,它基于树型结构,利用纯JAVA的技术对XML文档实现解析、生成、序列化以及多种操作。
Dom4j是JDOM的升级品,用来读写XML文件的。具有性能优异、功能强大和极其易使用的特点,它的性能超过sun公司官方的dom技术,同时它也是一个开放源代码的软件,Hibernate也用它来读写配置文件。
Jsoupjsoup 是一款Java 的HTML和XML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。

2. DOM解析原理和结构模型

  • 解析原理

​ XML DOM 和 HTML DOM一样,XML DOM将整个XML文档加载到内存,生成一个DOM树,并获得一个Document对象,通过Document对象可以对DOM进行操作。

  • 结构模型

在这里插入图片描述

3. 使用Jsoup

  • 导包

在这里插入图片描述

3.1 获取Document对象

​ 由于DOM方式解析XML文档所有都是节点,所有节点又都被封装到Document对象中,所以解析的重点就是获取Document对象。

  • 根据文档字符串获取Document

static Document parse(String html): 通过给定的html字符串内容获取文档对象

package com.zmysna.xml;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.junit.Test;

/**
 * 得到Document对象的三种方式
 */
public class Demo1Document {

    /**
     * 方式一:通过html的内容创建一个文档对象
     */
    @Test
    public void testDoc1() {
        //创建字符串,包含html文件内容
        String html = "<a href=\"#\">首页</a><a href=\"#\">门票</a>";
        //根据html文档字符串获取Document对象
        Document document = Jsoup.parse(html);
        //输出document,注:输出的document会自动加上html中其它的标签。
        System.out.println(document);
    }
}
  • 根据文件获取Document

static Document parse(File in, String charsetName)根据文件和字符集获取文档对象。

/**
 * 方式二:解析已经存在的html文件
 */
@Test
public void testDoc2() throws IOException {

    //得到类路径下URL对象
    URL url = Demo1Document.class.getResource("/index.html");
    //通过URL对象得到文件的真实地址
    String path = url.getPath();
    //创建文件对象
    File file = new File(path);
    //通过文件对象和字符集得到Document对象
    Document document = Jsoup.parse(file, "utf-8");
    //输出Document对象的内容
    System.out.println(document);
}
  • 通过 url 获取文档对象
  1. static Connection connect(String url)通过url地址创建一个连接对象。

  2. Document get()通过Connection连接对象获得一个Document文档对象

/**
 * 方式三:通过连接对象得到文档对象
 */
@Test
public void testDoc3() throws IOException {
    //定义一个具体html网页的url,如:http://www.itcast.cn
    String url = "http://www.itcast.cn";
    //调用connect()方法,创建一个连接对象
    Connection connection = Jsoup.connect(url);
    //调用连接对象的get()方法,得到一个文档对象
    Document document = connection.get();
    System.out.println(document);
}
3.2 通过GET方法获取ELement元素对象
getElementById(String id)通过id得到一个元素
getElementsByTag(String tagName)通过标签名得到一组元素
getElementsByClass(String className)通过类名得到一组元素
getElementsByAttribute(String key)通过属性名得到一组元素
package com.zmysna.xml;

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;

/**
 * 使用GET方法得到元素
 */
public class Demo2Get {

    public static void main(String[] args) throws IOException {
        //获取资源文件index.xml路径地址
        String path = Demo2Get.class.getResource("/index.html").getPath();
        //获取的资源文件对象
        File file = new File(path);
        //解析资源文件并获取Document对象
        Document document = Jsoup.parse(file, "utf-8");
        //通过id得到home元素
        Element home = document.getElementById("home");
        //System.out.println(home);
        //获取index.html中所有h3标签名称的元素列表并打印输出
        Elements h3 = document.getElementsByTag("h3");
        //h3.forEach(System.out::println);
        //获取index.html中所有元素含有class属性值为item并打印输出
        Elements item = document.getElementsByClass("item");
        //item.forEach(System.out::println);
        //获取所有包含type属性的元素并输出
        Elements type = document.getElementsByAttribute("type");
        type.forEach(System.out::println);
    }
}
3.3 通过CSS选择器得到元素
//作用:通过CSS选择器得到一组元素
select(String cssQuery)		
//作用:通过CSS选择器得到一个元素,如果匹配到多个,只返回第一个元素。
selectFirst(String cssQuery)
描述语法
根据id获取元素,id前面使用#符号#ID
根据元素class属性获取元素.类名
根据元素名称获取元素标签名
利用属性值来查找元素[属性名=‘属性值’]
package com.zmysna.xml
    
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;

/**
 * 使用CSS选择器查询元素
 */
public class Demo3CssQuery {

    public static void main(String[] args) throws IOException {
        //1)	获取资源文件index.html路径地址
        String path = Demo3CssQuery.class.getResource("/index.html").getPath();
        //获取的资源文件对象
        File file = new File(path);
        //解析资源文件并获取Document对象
        Document document = Jsoup.parse(file, "utf-8");
        //获取id="footer"元素并输出元素名称
        Element footer = document.selectFirst("#footer");
        //System.out.println(footer);
        //2)	含有class属性值为item并打印输出元素体内容
        Elements items = document.select(".item");
        //items.forEach(System.out::println);
        //3)	获取index.html中所有h3标签名称的元素列表并打印输出元素名称
        Elements h3 = document.select("h3");
        //h3.forEach(System.out::println);
        //4)	获取index.html中属性type值为"text"的所有元素列表并打印输出元素名称
        Elements elements = document.select("[type='text']");
        elements.forEach(System.out::println);
    }
}
3.4 ELement中的方法
Element对象的方法说明
String attr("属性名")得到指定的属性值
Element children()得到当前元素的所有子元素
String tagName()得到当前元素的标签名
String text()得到当前元素主体内容
String html()得到当前元素中的Html()

4. JsoupXPath

​ XPath 路径表达式的作用:DOM树中每个元素都有一个路径,可以通过这个路径来快速地找到某个指定的元素。不仅仅用在Jsoup中,其它的XML的DOM解析工具也是可以使用的,语法规则相同。

​ JsoupXpath 是一款纯Java开发的使用xpath解析HTML的解析器,JsoupXpath不是jsoup的一部分,是在jsoup基础上进行的扩展。

  • 需要导包

1543974298465)

4.1 核心类JXDocument和JXNode
  • JXDocument
核心方法说明
JXDocument(Document doc)创建JXDocument对象
参数是:document对象
List<JXNode> selN(String xpath)通过xpath得到一组节点,节点是元素,属性,文本父类
JXNode selNOne(String xpath)通过xpath得到一个节点
  • JXNode
方法描述
List<JXNode> sel(String xpath)在某个节点的基础上再次使用xpath,
再得到一组节点。相对路径的写法
Element getElement()通过节点对象得到元素对象
4.2 四种Xpath语法
  1. 绝对路径
  2. 相对路径
  3. 全文搜索
  4. 条件筛选
4.2.1 绝对路径
package com.zmysna.xml;

import cn.wanghaomiao.xpath.exception.XpathSyntaxErrorException;
import cn.wanghaomiao.xpath.model.JXDocument;
import cn.wanghaomiao.xpath.model.JXNode;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.junit.Before;
import org.junit.Test;

import java.io.File;
import java.io.IOException;
import java.util.List;

/**
 * 使用Xpath查询元素
 */
public class Demo4XPath {

    JXDocument jxDocument;   //它可以使用xpath

    @Before
    public void init() throws IOException {
        //得到文件对象
        File file = new File(Demo4XPath.class.getResource("/index.html").getPath());
        //通过文件对象得到文档对象
        Document document = Jsoup.parse(file, "utf-8");
        //通过文档对象得到JXDocument对象
        jxDocument = new JXDocument(document);
    }

    //使用绝对路径
    @Test
    public void testAbsolute() throws XpathSyntaxErrorException {
        //定义Xpath表达式 /body/div/ul/li/a
        String xpath = "/body/div/ul/li/a";
        //使用jxDocument对象selN方法执行xpath获取元素节点列表
        List<JXNode> jxNodes = jxDocument.selN(xpath);
        //遍历输出每个节点
        jxNodes.forEach(System.out::println);
    }
}
4.2.2 相对路径
//使用相对路径
@Test
public void testRelative() throws XpathSyntaxErrorException {
    //先采用jxDocument绝对路径的方式获取body节点
    JXNode body = jxDocument.selNOne("/body");
    //定义相对路径查找body下面一级的div节点列表
    //JXNode中的sel()方法使用的是当前元素下的相对路径
    List<JXNode> div = body.sel("/div/ul");
    //打印输出所有的节点
    div.forEach(System.out::println);
}
4.2.3 全文搜索路径
语法说明
//li查询所有的li
//div/a/img查询所有div下面的a下面img
//div//img/@src查询所有div下面img下src的属性
//link/@href查询所有link下href属性
//全文搜索
@Test
public void testGlobalSearch() throws XpathSyntaxErrorException {
    //直接全文搜索所有的li元素列表并打印
    List<JXNode> list1 = jxDocument.selN("//li");
    //list1.forEach(System.out::println);
    //直接全文搜索所有的div,再逐层级搜索下面的a元素下的img元素列表并打印
    List<JXNode> list2 = jxDocument.selN("//div/a/img");
    //list2.forEach(System.out::println);
    //搜索任何一级div下的所有子孙img的src的属性值
    List<JXNode> list3 = jxDocument.selN("//div//img/@src");
    //list3.forEach(System.out::println);
    //直接获取link元素里面href属性的值,注意属性要用@符号
    List<JXNode> list4 = jxDocument.selN("//link/@href");
    list4.forEach(System.out::println);
}
4.2.4 条件筛选
//条件过滤
@Test
public void testFilter() throws XpathSyntaxErrorException {
    //搜索li,属性为class="nav-active"的元素并打印
    List<JXNode> list1 = jxDocument.selN("//li[@class='nav-active']");
    //list1.forEach(System.out::println);
    //搜索li,属性为data-slide-to大于0的元素,再查询data-slide-to的属性值
    List<JXNode> list2 = jxDocument.selN("//li[@data-slide-to>0]/@data-slide-to");
    //list2.forEach(System.out::println);
    //搜索a标签,属性为href="login.html"的元素,得到它的文本。
    List<JXNode> list3 = jxDocument.selN("//a[@href='login.html']/text()");
    //list3.forEach(System.out::println);
    //搜索a标签,属性为href="index.html"的元素,得到它的HTML。
    List<JXNode> list4 = jxDocument.selN("//a[@href='index.html']/html()");
    list4.forEach(System.out::println);
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值