【Java EE】Day12 XML、约束(DTD、Schema)、解析方式、Jsoup、选择器(Selector、XPath)

一、XML介绍

1、概述

  • Extensible Markup Language--可扩展标记语言
    • 标记语言 :标签构成
    • 可扩展:可以自定义标签

2、功能

  • 存储数据
  • 作为配置文件使用
  • 作为数据载体在网络中传输

3、与HTML的关系 

  • w3c(World Wide Web Consortium)万维网发布了HTML和XML技术标准
  • 与properties竞争 
  • 区别:
    • XML标签自定义,HTML标签预定义
    • XML语法严格,HTML语法松散 
    • XML用于存储,HTML用于显示

4、语法 

  • 基本语法:
    • 后缀名为xml
    • 第一行进行文档声明:<?xml version='1.0' ?>
    • 有且只有一个根标签
    • 属性值加引号
    • 标签必须正确被关闭(自闭和或围堵标签)
    • 标签名区分大小写 
    • 判断:浏览器打开正常显示缩进
<?xml version='1.0' ?>
<users>
    <user id='1'>
        <name>zhangsan</name>
        <age>23</age>
        <gender>male</gender>
    </user>
    <user id='2'>
        <name>lisi</name>
        <age>18</age>
        <gender>female</gender>
    </user>
</users>
  • 组成
    • 文档声明:<?xml 属性列表 ?>
      • version:必须包含,1.0
      • encoding:默认值:ISO-8859-1【IDEA根据此值修改文件编码】
      • standalone:是否独立(不依赖于其他文件)
    • 指令(了解):结合css,<?xml-stylesheet type="text/css" href="a.css" ?>
    • 标签:自定义标签
      • 不能以数字和符号开头
      • 不能以xml等字符开头
      • 不能包括空格
    • 属性
    • 文本内容:<![CDATA[   数据   ]]>被原样展示的数据
    • 约束     

二、约束

1、概述

  • 通过约束,规定xml文档的书写规则
  • 需要:在xml中引入约束文档&读懂约束文档
  • 约束文档分类
    • DTD:简单
    • Schema:复杂 

2、DTD

  • 将dtd文档引入到xml文档中
  • 内部dtd:将约束定义在xml中
  • 外部dtd:将约束定义在外部dtd文件中
    • 本地:<!DOCTYPE 根标签名 SYSTEM "dtd文件的位置">
    • 网络:<!DOCTYPE 根标签名 PUBLIC "dtd文件的名字" "dtd文件的URL位置">
<?xml version="1.0" encoding="UTF-8" ?>
<!--<!DOCTYPE students SYSTEM "student.dtd">-->

<!--内部DTD-->
<!DOCTYPE students [
        <!ELEMENT students (student*) >
        <!--*表示0次或多次,+表示一次或多次-->
        <!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>23</age>
        <sex>male</sex>
    </student>
    <student number="s002">
        <name>李四</name>
        <age>18</age>
        <sex>female</sex>
    </student>
</students>

外部dtd:

<!ELEMENT students (student*) >
<!--*表示0次或多次,+表示一次或多次-->
<!ELEMENT student (name,age,sex)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT sex (#PCDATA)>
<!ATTLIST student number ID #REQUIRED>

3、Schema(xsd

  • 原因:DTD不能对内容进行限制
<?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="sex" type="sexType" />
        </xsd:sequence>
        <xsd:attribute name="number" type="numberType" use="required"/>
    </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> 

使用

<?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"
             xmlns="http://www.itcast.cn/xml"

>
    <!--可以加前缀xmlns:a,适用于多个xsd明明空间起名
        xsi:schemaLocation="http://www.itcast.cn/xml  student.xsd"
        xsi:schemaLocation="http://www.itcast.cn/xml1  student1.xsd"
    -->
    <student number="heima_0001">
        <name>zhangsan</name>
        <age>23</age>
        <sex>male</sex>
    </student>
    <student number="heima_0002">
        <name>lisi</name>
        <age>18</age>
        <sex>female</sex>
    </student>
 </students>

三、解析

1、概念

  • 解析/读取:将文档数据读取到内存
  • 写入:内存数据持久化在xml文档中

2、解析方式及思想

  • DOM思想
    • document object model,用于服务器端
    • 将标记语言文档一次性加载到内存,形成一颗DOM树
    • 特点:方便CRUD,消耗内存,不适用小内存设备
  • SAX思想
    • 根据指针逐行读取,设置监听器判断标签,用于移动端
    • 特点:不占内存,只能读,不能增删改

3、XML的常见的解析器

  • JAXP:SUN公司提供的解析器,支持dom和sax两种思想,性能差,代码麻烦
  • DOM4J:一款非常优秀的解析器,基于dom实现
  • Jsoup:是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。【也可以用来解析xml】
  • PULL:安卓Android内置解析器,sax思想

四、Jsoup

1、快速入门

  • 步骤:
    • 导包
    • 获取document对象
    • 获取标签的Element对象
    • 获取数据
public static void main(String[] args) throws IOException {
        //2.获取document对象,根据xml文档获取
        //2.1获取student.xml的path,通过类加载器
        String path = JsoupDemo1.class.getClassLoader().getResource("student.xml").getPath();
        //2.解析xml文档,加载文档进内存,获取dom树--->Documenr
        Document document = Jsoup.parse(new File(path), "utf-8");
        //3.获取元素对象Element标签对象,需求:获取name下的tom值
        Elements elements = document.getElementsByTag("name");//当做arraylist
        System.out.println(elements.size());
        //3.1 获取第一个name的Element对象,可以通过索引拿到
        Element element = elements.get(0);
        //3.2 获取数据
        String name = element.text();
        System.out.println(name);
    }

2、组成

  • Jsoup:工具类,解析html文档或xml文档,返回Document
  • Document:文档对象:代表内存中的dom树
  • Elements:元素Element对象的集合,可以当做ArrayList<Element>来使用
  • Element:元素对象,获取名称属性或文本
  • Node:节点对象,是上述对象的父类
    • 是Document和Element的父类

3、Jsoup对象

  • parse的重载,返回document对象
  • 文件
  • 链接
  • 字符串
package cn.itcast.xml.jsoup;

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;

/**
 * Jsoup对象功能
 */
public class JsoupDemo2 {
    public static void main(String[] args) throws IOException {
        //2.获取document对象,根据xml文档获取
        //2.1获取student.xml的path,通过类加载器
        String path = JsoupDemo2.class.getClassLoader().getResource("student.xml").getPath();
        //2.解析xml文档,加载文档进内存,获取dom树--->Documenr
        /*Document document = Jsoup.parse(new File(path), "utf-8");
        System.out.println(document);*/
        //第二种方式static Document    parse(String html) 解析字符串

        /* String str="<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
                 "\n" +
                 "<students>\n" +
                 "\t<student number=\"heima_0001\">\n" +
                 "\t\t<name>zhangsan</name>\n" +
                 "\t\t<age>23</age>\n" +
                 "\t\t<sex>male</sex>\n" +
                 "\t</student>\n" +
                 "\t<student number=\"heima_0002\">\n" +
                 "\t\t<name>lisi</name>\n" +
                 "\t\t<age>18</age>\n" +
                 "\t\t<sex>female</sex>\n" +
                 "\t</student>\n" +
                 " </students>";
        Document document = Jsoup.parse(str);
        System.out.println(document);*/
        //第三种方式static Document    parse(URL url, int timeoutMillis) 通过网络路径获取指定的html文档或xml文档
        //可以进行爬虫
        URL url = new URL("https://baike.baidu.com/item/jsoup/9012509?fr=aladdin");//代表网络中的资源路径
        Document document = Jsoup.parse(url, 5000);
        System.out.println(document);
    }
}

4、Document对象

  • 代表文档中的dom树
  • 用于获取Element对象
  • 常用方法
package cn.itcast.xml.jsoup;
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;
/**
 * Document/Element对象功能
 */
public class JsoupDemo3 {
    public static void main(String[] args) throws IOException {
        //1获取student.xml的path,通过类加载器
        String path = JsoupDemo3.class.getClassLoader().getResource("student.xml").getPath();
        //2.获取Document对象
        Document document = Jsoup.parse(new File(path), "utf-8");
        //3.获取元素对象
        //3.1获取所有student对象
        Elements elements = document.getElementsByTag("student");
        System.out.println(elements);
        System.out.println("_________");
        //3.2获取属性名为id的元素对象们
        Elements elements1 = document.getElementsByAttribute("id");
        System.out.println(elements1);
        System.out.println("_________");
        //3.3获取number属性值为heima_0001的元素对象
        Elements elements2 = document.getElementsByAttributeValue("number", "heima_0001");
        System.out.println(elements2);
        //3.3获取id属性值的元素对象
        Element itcast = document.getElementById("itcast");
        System.out.println(itcast);
    }
}

5、Element对象

  • 功能
    • 获取子元素对象
    • 获取属性值
    • 获取文本内容
package cn.itcast.xml.jsoup;
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;

/**
 * Element对象功能
 */
public class JsoupDemo4 {
    public static void main(String[] args) throws IOException {
        //1获取student.xml的path,通过类加载器
        String path = JsoupDemo4.class.getClassLoader().getResource("student.xml").getPath();
        //2.获取Document对象
        Document document = Jsoup.parse(new File(path), "utf-8");
        /*
         功能
            获取子元素对象【子标签】
                Elements    getElementsByTag(String tagName):根据标签名称获取元素对象集合
                Elements    getElementsByAttribute(String key):根据属性名称获取元素对象集合
                Elements    getElementsByAttributeValue(String key, String value):根据对应的属性名和属性值获取元素对象集合
                Element    getElementById(String id):根据id属性值获取唯一的Element对象
            获取属性值
                public String attr(String attributeKey):根据属性名称获取属性值
            获取文本内容
                String text():获取文本内容
                String    html():获取标签提的所有内容,包括子标签的字符串内容
        * */
        //通过document对象获取name标签 ,获取所有的name标签
        Elements elements = document.getElementsByTag("name");
        System.out.println(elements.size());
        System.out.println("____________________________");
        //通过Element对象获取子标签对象
        Element element_student = document.getElementsByTag("student").get(0);
        Elements ele_name = element_student.getElementsByTag("name");
        System.out.println(ele_name.size());
        //获取属性,如number的属性值
        String number = element_student.attr("NUMBER");
        System.out.println(number);
        //获取name标签的文本内容
        String text = ele_name.text();
        String html = ele_name.html();
        System.out.println(text);
        System.out.println(html);
    }
}

五、选择器查询

1、常用的选择器

  • jsoup提供的快捷查询方式
  • selector选择器,使用select方法
  • XPath快捷查询语法

2、selector

  • 选择器,是Element对象的方法
  • 方法:Elements select(String cssQuery)
  • 简化css代码书写
package cn.itcast.xml.jsoup;
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;
/**
 * 选择器查询
 */
public class JsoupDemo5 {
    public static void main(String[] args) throws IOException {
        //1获取student.xml的path,通过类加载器
        String path = JsoupDemo5.class.getClassLoader().getResource("student.xml").getPath();
        //2.获取Document对象
        Document document = Jsoup.parse(new File(path), "utf-8");
        //3.查询name标签
        /*
            之前:
            div{
                }
        * */
        Elements elements = document.select("name");
        System.out.println(elements);
        System.out.println("====================");
        //4.查询id值为 itcast的元素
        /*
            之前:
            #itcast{
                }
        * */
        Elements elements1 = document.select("#itcast");
        System.out.println(elements1);
        System.out.println("====================");
        //5.获取student标签且number属性值为heima_0001的age子标签
        Elements elements2 = document.select("student[number='heima_0001'] > age");
        System.out.println(elements2);
    }
}

3、XPath

  • w3c提供的快捷查询语法,可以查询w3cschool的参考手册
  • 是XML路径语言,(XML Path Language)
  • 用于确定XML中的某部分位置
  • 需要额外导包:JsoupXpath-0.3.2
package cn.itcast.xml.jsoup;
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.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.File;
import java.io.IOException;
import java.util.List;
/**
 * XPath查询
 */
public class JsoupDemo6 {
    public static void main(String[] args) throws IOException, XpathSyntaxErrorException {
        //1获取student.xml的path,通过类加载器
        String path = JsoupDemo6.class.getClassLoader().getResource("student.xml").getPath();
        //2.获取Document对象
        Document document = Jsoup.parse(new File(path), "utf-8");
        //3.根据Document对象,创建JXDocument对象
        JXDocument jxDocument = new JXDocument(document);
        //4.结合xpath语法查询
        //4.1查询所有的student标签
        List<JXNode> jxNodes = jxDocument.selN("//student");
        for (JXNode jxNode : jxNodes) {
            System.out.println(jxNode);
            //Element element = jxNode.getElement();
        }
        System.out.println("=======================");
        //4.2查询所有student标签下的name标签
        List<JXNode> jxNodes2 = jxDocument.selN("//student/name");
        for (JXNode jxNode : jxNodes2) {
            System.out.println(jxNode);
            //Element element = jxNode.getElement();
        }
        System.out.println("=======================");
        //4.3查询student下带id的name标签
        List<JXNode> jxNodes3 = jxDocument.selN("//student/name[@id]");
        for (JXNode jxNode : jxNodes3) {
            System.out.println(jxNode);
            //Element element = jxNode.getElement();
        }
        System.out.println("=======================");
        //4.4查询student下带id的name标签,并且id属性值为itcast
        List<JXNode> jxNodes4 = jxDocument.selN("//student/name[@id='itcast']");
        for (JXNode jxNode : jxNodes4) {
            System.out.println(jxNode);
            //Element element = jxNode.getElement();
        }
    }
}

 

posted @ 2021-06-13 22:41  哥们要飞  阅读(91)  评论(0编辑  收藏  举报