XML学习总结 一、什么是XML 二、定义XML 三、约束 四、解析 五、Jsoup解析教程 六、一些高端玩法

XML学习总结

xml的最先接触是学习Android时的activity_main.xml,在xml里写android布局,今天接触了JavaWeb的XML,记下一些心得和体验。


1、简单认识

XML ---Extensible Markup Language 可扩展标记语言 , 可配置文件、可网络传输。

看两个简单的图便可以理解

首先是一段简单的.xml代码

XML学习总结
一、什么是XML
二、定义XML
三、约束
四、解析
五、Jsoup解析教程
六、一些高端玩法

其DOM图

XML学习总结
一、什么是XML
二、定义XML
三、约束
四、解析
五、Jsoup解析教程
六、一些高端玩法

二、定义XML

1、简单声明

version: 解析这个xml的时候,使用什么版本的解析器解析
	<?xml version="1.0" ?>
 
encoding: 解析xml中的文字的时候,使用什么编码来解析
	<?xml version="1.0" encoding="UTF-8" ?>
 
standalone: no - 该文档会依赖关联其他文档,yes-- 这是一个独立的文档
	<?xml version="1.0" encoding="UTF-8" standalone="no" ?>

2、简单语法

		(1)、xml文档的后缀名 .xml
		(2)、xml第一行必须定义为文档声明
		(3)、xml文档中有且仅有一个根标签
		(4)、属性值必须使用引号(单双都可)引起来
		(5)、标签必须正确关闭
		(6)、xml标签名称区分大小写

3、CDATA区

在该区域中的数据会被原样展示
格式: <![CDATA[ 数据 ]]>

三、约束

规定xml文档的书写规则(了解即可)

1、DTD约束

DTD一种简单的约束

DTD:
	引入dtd文档到xml文档中
			* 内部dtd:将约束规则定义在xml文档中
			* 外部dtd:将约束的规则定义在外部的dtd文件中
				* 本地:<!DOCTYPE 根标签名 SYSTEM "dtd文件的位置">
				* 网络:<!DOCTYPE 根标签名 PUBLIC "dtd文件名字" "dtd文件的位置URL">

一个简单的例子

<!ELEMENT stus (stu)>  : stus 下面有一个元素 stu  , 但是只有一个
<!ELEMENT stu (name , age)>  stu下面有两个元素 name  ,age  顺序必须name-age
<!ELEMENT name (#PCDATA)> 
<!ELEMENT age (#PCDATA)>
<!ATTLIST stu id CDATA #IMPLIED> stu有一个属性 文本类型, 该属性可有可无
 
元素的个数:
	+  一个或多个   例如:stus(stu+)
	*   零个或多个
	?   零个或一个
 
属性的类型定义:
	CDATA : 属性是普通文字
	ID : 属性的值必须唯一
 
<!ELEMENT stu (name , age)>		按照顺序来 
<!ELEMENT stu (name | age)>     两个中只能包含一个子元素

2、Schema约束

Schema一种复杂的约束

Schema:
	引入:
		(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"
				xmlns="http://www.itcast.cn/xml"
				xsi:schemaLocation="http://www.itcast.cn/xml  student.xsd">

这个认识一下,要注意一点: 一个xml 可以引用多个Schema约束,但是只能引用一个DTD约束。

四、解析

操作xml文档,将文档中的数据读取到内存中

1、解析的方式

(1)、DOM

DOM:将整个XML文件读取到内存,然后形成树状的结构。整个文档橙称之为document对象,每个元素称之为element对象,每个属性称之为attribute对象,以上所有的对象称之为Node节点。
			* 优点:操作方便,可以对文档进行CRUD的所有操作
			* 缺点:占内存

(2)、SAX

SAX:逐行读取,基于事件驱动的,读取一行,解析一行,不会造成内存溢出。
			* 优点:不占内存。
			* 缺点:只能读取,不能增删改
DOM解析 SAX解析
原理:一次性加载xml文档,不适合大容量文件读取 原理:加载一点,读取一点,处理一点。适合大容量
任意CRUD 只能读取
任意读取任何位置的数据,甚至回读 只能从上向下,按顺序
DOM面向对象(Node,Element,Attribute) 对于Java开发不太友好

2、几个常见的解析器

(1)、JAXP:sun公司提供的解析器,支持dom和sax两种思想

(2)、DOM4J:一款非常优秀的解析器

(3)、Jsoup:jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。

(4)、PULL:Android操作系统内置的解析器,sax方式的。

3、导入解析包

因为以上常见的解析器需要导包,这里以IDEA为例子简要教一下。

(1)、导入需要的jar包

首先File->Project Structure->Modules->点击一旁的+号,添加你已经下载好jar包(可自行在网上下载)

XML学习总结
一、什么是XML
二、定义XML
三、约束
四、解析
五、Jsoup解析教程
六、一些高端玩法

(这里以Jsoup为例)

(2)、导出可执行的jar包

其次同样的界面里Artifacts->"+",选jar,选择from modules with dependencies,后有配置窗口出现,配置完成后,勾选include in project build >ok保存

XML学习总结
一、什么是XML
二、定义XML
三、约束
四、解析
五、Jsoup解析教程
六、一些高端玩法

(3)、 导出jar包

菜单:Build->build artfacts,导出jar包

XML学习总结
一、什么是XML
二、定义XML
三、约束
四、解析
五、Jsoup解析教程
六、一些高端玩法

完成解析包的导入,这时候我们就可以去import了

五、Jsoup解析教程

Jsoup是一款Java的HTML解析器,主要用来对HTML解析。 Jsoup中文文档

1、简单使用

对student.xml解析

分析步骤:

(1)、导入jar包

(2)、获取Document对象

(3)、获取对应的标签Element对象

(4)、获取数据

import java.io.IOException;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class JsoupDemo {
    public static void main(String[] args) throws IOException {
        //获取student.xml的path
      String path =JsoupDemo.class.getClassLoader().getResource("student.xml").getPath();
        //解析xml文档,加载文档进内存,获取dom树--->Document
        Document document = Jsoup.parse(new File(path),"uft-8");
        //获取元素对象 Element
        Elements elements = document.getElementsByTag("name");
        System.out.println(elements.size());
        //获取第一个name的Element对象
        Element e = elements.get(0);
        //获取数据
        String name = e.text();
        System.out.println(name);
    }
}

2、对象的使用

1. 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的文档对象

2. Document:文档对象。代表内存中的dom树
			* 获取Element对象
				* getElementById(String id):根据id属性值获取唯一的element对象
				* getElementsByTag(String tagName):根据标签名称获取元素对象集合
				* getElementsByAttribute(String key):根据属性名称获取元素对象集合
				* getElementsByAttributeValue(String key, String value):根据对应的属性名和属性值获取元素对象集合

3. Elements:元素Element对象的集合。可以当做 ArrayList<Element>来使用

4. Element:元素对象
			1. 获取子元素对象
				* getElementById(String id):根据id属性值获取唯一的element对象
				* getElementsByTag(String tagName):根据标签名称获取元素对象集合
				* getElementsByAttribute(String key):根据属性名称获取元素对象集合
				* getElementsByAttributeValue(String key, String value):根据对应的属性名和属性值获取元素对象集合

			2. 获取属性值
				* String attr(String key):根据属性名称获取属性值
			3. 获取文本内容
				* String text():获取文本内容
				* String html():获取标签体的所有内容(包括字标签的字符串内容)

5. Node:节点对象
			* 是Document和Element的父类

3、快捷查询方式

1. selector:选择器
			* 使用的方法:Elements	select(String cssQuery)
			* 语法:参考Selector类中定义的语法

2. XPath:XPath即为XML路径语言,它是一种用来确定XML(标准通用标记语言的子集)文档中某部分位置的语言
			* 使用Jsoup的Xpath需要额外导入jar包。
			* 查询w3cshool参考手册,使用xpath的语法完成查询

仍对student.xml解析

package 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 java.io.File;
import java.io.IOException;
import java.util.List;

public class JsoupDemo5 {
    public static void main(String[] args) throws IOException, XpathSyntaxErrorException {
        //获取student.xml的path
        String path = JsoupDemo5.class.getClassLoader().getResource("student.xml").getPath();
        //获取Document对象
        Document document = Jsoup.parse(new File(path), "utf-8");
        //获取JXDocument对象
        JXDocument jxDocument = new JXDocument(document);
        //xpath语法查询
        //所有student标签
        List<JXNode> jxNodes = jxDocument.selN("//student");
        for (JXNode jxNode : jxNodes
        ) {
            System.out.println(jxNode);
        }
        //查询所有student标签下的name标签
        List<JXNode> jxNodes2 = jxDocument.selN("//student/name");
        for (JXNode jxNode : jxNodes2) {
            System.out.println(jxNode);
        }
        //查询student标签下带有id属性的name标签
        List<JXNode> jxNodes3 = jxDocument.selN("//student/name[@id]");
        for (JXNode jxNode : jxNodes3) {
            System.out.println(jxNode);
        }
        //查询student标签下带有id属性的name标签 并且id属性值为IT
        List<JXNode> jxNodes4 = jxDocument.selN("//student/name[@id='IT']");
        for (JXNode jxNode : jxNodes4) {
            System.out.println(jxNode);
        }
    }
}

六、一些高端玩法

这些都是在网上看的,不会违法吧emmmm,仅限娱乐,玩玩就好~

1、采集开源中国项目信息

package XML;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

    public class Main {

        public static void main(String[] args) throws IOException {
            // write your code here
            Set<String> setUrls = new HashSet<>();
            for(int i = 1; i <= 5; i++)
            {
                String strUrl = "https://www.oschina.net/project/list?company=0&sort=score&lang=0&recommend=false&p=="+i;
                setUrls.add(strUrl);
            }

            Set<String> setProjUrls = new HashSet<>();
            for(String stringUrl : setUrls)
            {
                Document document = Jsoup.connect(stringUrl)
                        .userAgent("Mozilla/5.0 (Windows NT 6.1; rv:30.0) Gecko/20100101 Firefox/30.0")
                        .get();
                  System.out.println(document);
                Elements elements = document.select("div.box.item");
                for(Element element : elements)
                {
                    Elements eleUrl = element.select("div.box-aw a");
                    String strPrjUrl = eleUrl.attr("href");
                    setProjUrls.add(strPrjUrl);
                      System.out.println(strPrjUrl);
                    Elements eleTitle = eleUrl.select(".title");
                    String strTitle = eleTitle.text();
                     System.out.println(strTitle);
                    Elements eleSummary = eleUrl.select(".summary");
                    String strSummary = eleSummary.text();
                      System.out.println(strSummary);
                }
            }

            for(String stringUrl : setProjUrls)
            {
                Document document = Jsoup.connect(stringUrl)
                        .userAgent("Mozilla/5.0 (Windows NT 6.1; rv:30.0) Gecko/20100101 Firefox/30.0")
                        .get();
                Elements elements = document.select("div.box-aw a h1");

                String strTitle = elements.text();
                System.out.println("标题:" + strTitle);

                Elements elementsSection = document.select("section.list");

                int nSize = elementsSection.get(0).children().size();

                if(nSize == 0)
                    continue;

                Element elementProtocol = elementsSection.get(0).child(0);
                Elements elesPro = elementProtocol.select("span");
                String strPro = elesPro.text();
                System.out.println("开源协议:" + strPro);

                nSize--;
                if(nSize == 0)
                    continue;

                Element elementLan = elementsSection.get(0).child(1);
                Elements elesLan = elementLan.select("span").get(0).children();
                StringBuilder strlan = new StringBuilder();
                for(Element ele : elesLan)
                {
                    String strLanTemp = ele.text();
                    if(strLanTemp.indexOf("查看源码")>=0)
                        break;
                    strlan.append(strLanTemp+",");
                }
                if(elesLan.size()>0)
                {
                    String strLanguage = strlan.toString().substring(0,strlan.length()-1);
                    System.out.println("开发语言:" + strLanguage);
                }


                nSize--;
                if(nSize == 0)
                    continue;

                Element elementOS = elementsSection.get(0).child(2);
                Elements elesOS = elementOS.select("span");
                String strOS = elesOS.text();
                System.out.println("操作系统:" + strOS);

                nSize--;
                if(nSize == 0)
                    continue;

                Element elementAuthor = elementsSection.get(0).child(3);
                Elements elesAuthor = elementAuthor.select("a.link");
                String strAuthor= elesAuthor.text();
                System.out.println("软件作者;" + strAuthor);

                System.out.println("---------------------");
            }

        }
    }

2、爬取腾讯首页全部图片

package XML;

import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;

    public class Main{
        /**
         * 下载图片到指定目录
         *
         * @param filePath 文件路径
         * @param imgUrl   图片URL
         */
        public static void downImages(String filePath, String imgUrl) {
            // 若指定文件夹没有,则先创建
            File dir = new File(filePath);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            // 截取图片文件名
            String fileName = imgUrl.substring(imgUrl.lastIndexOf('/') + 1, imgUrl.length());

            try {
                // 文件名里面可能有中文或者空格,所以这里要进行处理。但空格又会被URLEncoder转义为加号
                String urlTail = URLEncoder.encode(fileName, "UTF-8");
                // 因此要将加号转化为UTF-8格式的%20
                imgUrl = imgUrl.substring(0, imgUrl.lastIndexOf('/') + 1) + urlTail.replaceAll("\+", "\%20");

            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            // 写出的路径
            File file = new File(filePath + File.separator + fileName);

            try {
                // 获取图片URL
                URL url = new URL(imgUrl);
                // 获得连接
                URLConnection connection = url.openConnection();
                // 设置10秒的相应时间
                connection.setConnectTimeout(10 * 1000);
                // 获得输入流
                InputStream in = connection.getInputStream();
                // 获得输出流
                BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
                // 构建缓冲区
                byte[] buf = new byte[1024];
                int size;
                // 写入到文件
                while (-1 != (size = in.read(buf))) {
                    out.write(buf, 0, size);
                }
                out.close();
                in.close();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

        public static void main(String[] args) {
            // 利用Jsoup获得连接
            Connection connect = Jsoup.connect("http://www.qq.com");
            try {
                // 得到Document对象
                Document document = connect.get();
                // 查找所有img标签
                Elements imgs = document.getElementsByTag("img");
                System.out.println("共检测到下列图片URL:");
                System.out.println("开始下载");
                // 遍历img标签并获得src的属性
                for (Element element : imgs) {
                    //获取每个img标签URL "abs:"表示绝对路径
                    String imgSrc = element.attr("abs:src");
                    // 打印URL
                    System.out.println(imgSrc);
                    //下载图片到本地
                    Main2.downImages("d:/img", imgSrc);
                }
                System.out.println("下载完成");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

3、采集悟空问答某问题的评论

哪些电视剧小时候看时觉得很经典,现在看却质疑剧的三观?为什么?

package XML;

import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.*;

    public class Main {

        public static void main(String[] args) {
            // 利用Jsoup获得连接
Connection connect=Jsoup.connect("https://www.wukong.com/question/6677402779574599943/");
            try {
                // 得到Document对象
                Document document = connect.get();

                Elements elements = document.select(".question-name");
                System.out.println(elements.get(0).text());

                Elements elements2 = document.select(".answer-item");
                for(Element element : elements2)
                {
                    Elements elements3  = element.select(".answer-user-avatar img");
                    System.out.println(elements3.attr("abs:src"));

                    elements3  = element.select(".answer-user-name");
                    System.out.println(elements3.text());

                    elements3  = element.select(".answer-user-tag");
                    System.out.println(elements3.text());

                    elements3  = element.select(".answer-text");
                    System.out.println(elements3.text());
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }