XML学习

XML

一、xml概述

开发中文网:https://www.w3school.com.cn/

1、概念

XML(Extensible Markup Language):可扩展标记语言 可扩展:标签都是自定义的。

2、发展历程

HTML 和 XML 都是 W3C(万维网联盟)制定的标准,最开始 HTML 的语法过于松散, 于是 W3C 制定了更严格的 XML 语法标准,希望能取代 HTML。但是程序员和浏览器厂商 并不喜欢使用 XML,于是现在的 XML 更多的用于配置文件及传输数据等功能。

3、xml和html的区别
  • xml语法严格,html语法松散
  • xml标签自定义,html标签预定义
4、xml基本语法
  • 文件的后缀名是.xml
  • 第一行必须是文档声明
  • 有且仅有一个根标签
  • 属性值必须用引号(单双都可)引起来
  • 标签必须正确关闭
  • 区分大小写

二、约束

1、什么是约束

约束是一个文件,可以规定xml文档的书写规则。我们作为框架的使用者,不需要会写约束文件,但是需要能读懂约束文档,xml有两种约束文件类型:DTD和Schema

2、DTD约束

DTD 是一种较简单的约束技术

引入:

  • 本地:
<!DCTYPE 根标签名 SYSTEM "dtd 文件的位置">
  • 网络:

    <!DCTYPE 根标签名 PUBLIC "dtd 文件的位置" "dtd文件路径">
    

3、Schema约束

引入:

(1)写 xml 文档的根标签

(2)引入 xsi 前缀:确定 Schema 文件的版本。

​ xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”

(3)引入 Schema 文件 xsi:schemaLocation=“Schema 文件定义的命名空间 Schema 文件的具体 路径”

(4)为 Schema 约束的标签声明前缀 xmlns:前缀=“Schema 文件定义的命名空间”

例如:

<students
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.dianfei.cn/xml student.xsd"
        xmlns="http://www.dianfei.cn/xml">

三、xml解析

xml解析即读写xml文档中的数据。框架开发者通过xml解析读取框架使用者配置的参数信息,开发者也可以通过xml解析读取网络传来的数据。

1、xml解析思想
  • DOM:将标记语言文档一次性加载进内存,在内存中形成一颗dom树
    • 有点:操作方便,可以对文档进行CRUD的操作
    • 确定:占内存,因为他是直接一下全部加载到内存中的,而且在java中他都是以对象的方式存储的
  • SAX:逐行读取,基于事件驱动的。
    • 优点:不占内存,一般用于手机app开发中读取xml
    • 缺点:只能读取,不能增删改

2、常见的解析器

  • JAXP:SUN 公司提供的解析器,支持 DOM 和 SAX 两种思想
  • DOM4J:一款非常优秀的解析器
  • Jsoup:Jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址、HTML 文 本内容。它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方 法来取出和操作数据
  • PULL:Android 操作系统内置的解析器,支持 SAX 思

四、Jsoup解析器

1、使用步骤
public static void main(String[] args) throws IOException {
        /*
        1、导入jar包
        
        2、加载xml文件使用Joupt.parse()加载
        
         */
        //获取当前类的类加载器
        ClassLoader classLoader = Demo01.class.getClassLoader();
        /*
        getResource获取指定资源
        getPath获得资源的绝对路径
         */
        String path = classLoader.getResource("xml/xsd/students.xml").getPath();
        
        //3、获取DOM树
        Document document = Jsoup.parse(new File(path), "utf-8");
        //document是获取了整个xml文档
        //System.out.println(document);
        
        //4、获得DOM节点
        Elements names = document.getElementsByTag("name");
        for (Element name:names) {
            String text = name.text();
            System.out.println(text);
        }

    }
2、常见对象
  • Jsoup:解析dom树对象。
    • 常用方法:
      • static Document parse(File in, String charsetName):解析本地文件
      • static Document parse(String html):解析 html 或 xml 字符串
      • static Document parse(URL url, int timeoutMillis):解析网页源文件
 public static void main(String[] args) throws IOException {
        //获取本地资源
        String path = Demo02.class.getClassLoader().getResource("xml/xsd/students.xml").getPath();
        Document document = Jsoup.parse(new File(path), "utf-8");
        System.out.println(document);
        System.out.println("____________________________________________");
        //获取字符串资源
        Document document1 = Jsoup.parse("<students\n" +
                "        xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
                "        xsi:schemaLocation=\"http://www.dianfei.cn/xml student.xsd\"\n" +
                "        xmlns=\"http://www.dianfei.cn/xml\">\n" +
                "    <student number=\"baizhan_0001\">\n" +
                "        <name>zhangsan</name>\n" +
                "        <age>20</age>\n" +
                "        <sex>male</sex>\n" +
                "    </student>\n" +
                "    <student number=\"baizhan_0002\">\n" +
                "        <name>lisi</name>\n" +
                "        <age>18</age>\n" +
                "        <sex>female</sex>\n" +
                "    </student>\n" +
                "</students>");
        System.out.println(document1);
        System.out.println("____________________________________________");

        //获取url网络资源
        //第一个参数是url第二个参数是等待时间,如果超出等待时间就会抛出等待超时异常
        Document document2 = Jsoup.parse(new URL("https://www.baidu.com"), 5000);
        System.out.println(document2);
    }
  • Document:xml 的 dom 树对象
    • 常用方法:
      • Element getElementById(String id):根据 id 获取元素
      • Elements getElementsByTag(String tagName):根据标签名获取元素
      • Elements getElementsByAttribute(String key):根据属性获取元素
      • Elements getElementsByAttributeValue(String key,String value):根据属性名=属性值获取元素
      • Elements select(String cssQuery):根据选择器获取元素
public static void main(String[] args) throws IOException {
        String path = Demo03.class.getClassLoader().getResource("xml/jsoup/student.xml").getPath();
        Document document = Jsoup.parse(new File(path), "utf-8");
        //通过id获取Document对象
        Element element1 = document.getElementById("age1");
        System.out.println(element1.text());
        System.out.println("------------------------------");
        //通过标签获取Document对象
        Elements elements = document.getElementsByTag("age");
        for (Element element:elements) {
            System.out.println(element.text());
        }
        System.out.println("------------------------------");
        //通过属性获取Document对象
        Elements number = document.getElementsByAttribute("number");
        System.out.println(number);
        System.out.println("------------------------------");
        //通过属性=value获取Document对象
        Elements element4 = document.getElementsByAttributeValue("number", "s001");
        System.out.println(element4.text());
        System.out.println("------------------------------");
        //通过属性css选择器获取Document对象
        Elements select = document.select("#age1");
        System.out.println(select.text());

        Elements select1 = document.select(".s");
        System.out.println(select1.text());

        Elements name = document.select("name");
        System.out.println(name.text());
    }
  • Element: 元素对象
    • 常用方法:
      • String text():获取元素包含的纯文本。
      • String html():获取元素包含的带标签的文本。
      • String attr(String attributeKey):获取元素的属性值。
 public static void main(String[] args) throws IOException {
        String path = Demo04.class.getClassLoader().getResource("xml/jsoup/student.xml").getPath();
        Document document = Jsoup.parse(new File(path), "utf-8");
        //text()获取文本节点
        Elements elements = document.getElementsByAttributeValue("number", "s001");
        System.out.println(elements.text());
        //html()获取包括文本节点中包括标签
        System.out.println(elements.html());
        //attr获取属性值
        System.out.println(elements.attr("number"));
    }
3、XPath解析

XPath即为XML路径语言,它是一种用来确定标记语言文档中某部分位置的语言。

表达式描述
节点名选取该标签的所有子节点(我没试成功但是文档是这样写的)
/从指定节点选取字节点
//从匹配的当前节点选取
.选取当前节点
选取当前节点的父节点
@选择属性

使用流程

 public static void main(String[] args) throws Exception {
        //1. 导入 Xpath 的 jar 包
        //2. 获取 Document 对象
        String path = Demo05.class.getClassLoader().getResource("xml/jsoup/student.xml").getPath();
        Document parse = Jsoup.parse(new File(path), "utf-8");
        //3. 将 Document 对象转为 JXDocument 对象
        JXDocument jxDocument = new JXDocument(parse);
        
        /**
         * 常用表示方法
         * 标签名    选取该标签的所有子节点(我没试成功但是文档是这样写的)
         * /    从指定节点选取字节点
         * //   从匹配的当前节点选取
         * .    选取当前节点
         * ..   选取当前节点的父节点
         * @    选择属性
         */
        
        //4. JXDocument 调用 selN(String xpath),获取 List<JXNode>对象。
        //获取student标签中number属性等于s001的标签
        List<JXNode> jxNodes = jxDocument.selN("student[@number='s001']");
        //5. 遍历 List<JXNode>,调用 JXNode 的 getElement(),转为 Element 对象。
        for (JXNode jxNode : jxNodes) {
            Element element = jxNode.getElement();
            //6. 处理 Element
            System.out.println(element);
        }

    }

五、XML爬虫案例

使用Jsoup了对中央气象局天气数据爬虫
  • 1、对网页进行循环爬取各个城市的天气数据,
    • 获取配置文件weather.xml中的编号数据
    • 对里面所有城市进行循环爬取天气数据输出到控制台中
      -
package xml.jsoup;

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.net.URL;
import java.util.List;

public class CrawlerWeather {
    public static void main(String[] args) throws Exception {
        //获取配置文件
        String path = CrawlerWeather.class.getClassLoader().getResource("xml/jsoup/weather.xml").getPath();
        Document parse = Jsoup.parse(new File(path), "utf-8");
        //  将Document对象转为JXDocument对象
        JXDocument jxDocument = new JXDocument(parse);
        //  通过selN获取节点
        List<JXNode> jxNodes = jxDocument.selN("//wn");
        //5、循环获取
        for (JXNode jxNode : jxNodes) {
            //JXDocument对象转换为Document对象
            Element wn = jxNode.getElement();
            try {
                //1、解析中央气象局天气页面
                Document document = Jsoup.parse(new URL("http://www.weather.com.cn/weather/" + wn.text() + ".shtml"), 1000);
                //System.out.println(document);
                if (!document.text().equals("")) {
                    //2、获取地区名称
                    Elements regionName = document.getElementsByAttributeValue("class", "crumbs fl");
                    System.out.println(regionName.text());
                    //3、获取未来七天天气
                    Elements sevenDayWeather = document.getElementsByAttributeValue("class", "t clearfix");
                    //4、获取未来七天天气集合
                    Elements dayWeather = sevenDayWeather.select("li");
                    for (Element weather : dayWeather) {
                        //输出每一天的天气
                        System.out.println("    " + weather.text());
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

  • 2、过滤编号没有相对应的城市,把对应有城市的编号存入配置文件weather.xml中,这样来达到不用每次请求都全部编号请求一遍;先拥有一个地区编号库,然后直接直接用配置文件获取就行了,这样大大的减少了运算量,一次获取长期使用。
package xml.jsoup;
/**
 * 循环获取有城市的编号写入weather配置文件中
 */

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import java.io.*;
import java.net.URL;

public class CrawlerWeatherNumber {
    public static void main(String[] args) throws IOException {
        //获取资源路径
        String path = CrawlerWeatherNumber.class.getClassLoader().getResource("xml/jsoup/weather.xml").getPath();
        System.out.println(path);

        FileOutputStream fos = new FileOutputStream(new File(path));//创建文件输出流
        BufferedOutputStream bos = new BufferedOutputStream(fos);//创建缓冲输入流
        String numberStr = "<wns>";//保存的字符串

        //循环获取
        for (int i = 101010100; i < 101999999; i+=10) {
            //解析中央气象局天气页面
            Document document = Jsoup.parse(new URL("http://www.weather.com.cn/weather/" + i + ".shtml"), 5000);
            //如果获取的不为空则保存编号
            if (!document.text().equals("")) {
                Integer number = i;
                numberStr += "<wn>" + number.toString() + "</wn>";//保存字符串
                //十个编号之后就保存
                if (numberStr.length() >= 90) {
                    bos.write(numberStr.getBytes());//把编号存入配置文件中
                    numberStr = "";//存入后把字符串制空
                    bos.flush();//刷新缓冲区
                }
            }
            char tag = new Integer(i).toString().charAt(4);
            //如果编号第5个数字为1-4是直辖市,直辖市少一个行政单位
            if (tag >= '1' && tag <= '4') {
                i += 100;
                i -= 10;
            }
            System.out.println(i);
        }
        numberStr += "</wns>";//根标签结束存入
        System.out.println(numberStr);
        bos.write(numberStr.getBytes());
        bos.close();
        fos.close();
    }
}

weather.xml文件

<wns>
    <wn>101010100</wn><wn>101010200</wn><wn>101010300</wn><wn>101010400</wn><wn>101010500</wn><wn>101010600</wn><wn>101010700</wn><wn>101010800</wn><wn>101010900</wn><wn>101011000</wn><wn>101011100</wn><wn>101011200</wn><wn>101011300</wn><wn>101011400</wn><wn>101011500</wn><wn>101011600</wn><wn>101011700</wn><wn>101020100</wn><wn>101020200</wn><wn>101020300</wn><wn>101020400</wn><wn>101020500</wn><wn>101020600</wn><wn>101020700</wn><wn>101020800</wn><wn>101020900</wn><wn>101021000</wn><wn>101021100</wn><wn>101021200</wn><wn>101021300</wn><wn>101021400</wn><wn>101021500</wn><wn>101021600</wn><wn>101021700</wn><wn>101030100</wn><wn>101030200</wn><wn>101030300</wn><wn>101030400</wn><wn>101030500</wn><wn>101030600</wn><wn>101030700</wn><wn>101030800</wn><wn>101030900</wn><wn>101031000</wn><wn>101031100</wn><wn>101031200</wn><wn>101031300</wn><wn>101031400</wn><wn>101031500</wn><wn>101031600</wn><wn>101031700</wn><wn>101033100</wn><wn>101040100</wn><wn>101040200</wn><wn>101040300</wn><wn>101040400</wn><wn>101040500</wn><wn>101040600</wn><wn>101040700</wn><wn>101040800</wn><wn>101040900</wn><wn>101041000</wn><wn>101041100</wn><wn>101041200</wn><wn>101041300</wn><wn>101041400</wn><wn>101041500</wn><wn>101041600</wn><wn>101041700</wn><wn>101041800</wn><wn>101041900</wn><wn>101042000</wn><wn>101042100</wn><wn>101042200</wn><wn>101042300</wn><wn>101042400</wn><wn>101042500</wn><wn>101042600</wn><wn>101042700</wn><wn>101042800</wn><wn>101042900</wn><wn>101043000</wn><wn>101043100</wn><wn>101043200</wn><wn>101043300</wn><wn>101043400</wn><wn>101043500</wn><wn>101043600</wn><wn>101043700</wn><wn>101043800</wn><wn>101043900</wn><wn>101044000</wn><wn>101044100</wn><wn>101050110</wn><wn>101050210</wn><wn>101050310</wn><wn>101050410</wn><wn>101050510</wn><wn>101050810</wn><wn>101050910</wn><wn>101051110</wn><wn>101060110</wn><wn>101060210</wn><wn>101070110</wn><wn>101070210</wn><wn>101080110</wn><wn>101080210</wn><wn>101080410</wn><wn>101080510</wn><wn>101080610</wn><wn>101080710</wn><wn>101080810</wn><wn>101080910</wn><wn>101081010</wn><wn>101081110</wn><wn>101081210</wn><wn>101090110</wn><wn>101090120</wn><wn>101090210</wn><wn>101090220</wn><wn>101090310</wn><wn>101090410</wn><wn>101090510</wn><wn>101090610</wn><wn>101090710</wn><wn>101090810</wn><wn>101090910</wn><wn>101091010</wn><wn>101100110</wn><wn>101100210</wn><wn>101100410</wn><wn>101100510</wn><wn>101100710</wn><wn>101100810</wn><wn>101101010</wn><wn>101101100</wn><wn>101101110</wn><wn>101110200</wn><wn>101110300</wn><wn>101161010</wn><wn>101180110</wn><wn>101180310</wn><wn>101180510</wn><wn>101180610</wn><wn>101180710</wn><wn>101180810</wn><wn>101180910</wn><wn>101181010</wn><wn>101181110</wn><wn>101181410</wn>
</wns>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值