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>