文章目录
1. 认识XML
1.1 什么是XML
全称:可扩展标记语言(Extensible Markup Language)。是一门标记语言。诞生于1996年(96年发行第一个版本1.0,到了04年更新为1.1版本,但是用的最多是1.0版本),html也是标记语言,xml跟html不同的是xml没有固定的标签,所有的标签都可以自定义。这也是为什么叫它可扩展的原因。什么是标记语言,就是由两对尖括号括起来的语言,<
和>
,学过html都知道。那么它就是用这么一个标记来描述数据的。可以把标记理解为标签。
1.2 XML被用来干什么
通常,xml被用于信息的记录(配置文件)和传递(网络上传输),而非显示数据(html才是显示数据的)。因此xml经常用于充当配置文件。像我们学习框架的时候,是不是会在xml里面写数据库的连接信息,把properties替换掉,阅读性比properties好,properties只是存一些简单的数据,复杂数据用xml存。一说到记录,就会想到数据库,但是数据库比较麻烦,比如我数据库里的数据要想导给你,得先从我电脑上的数据库软件导出一个文件,再把这个文件发给你,但前提是你得有一个数据库软件,再把我给你的文件导进去,而xml其实就是一个文本文件,一个文档。拿到即用,不用什么安装即可使用。
1.3 XML的格式
-
第一行必须声明文档信息,用于描述xml的版本和编码方式。必须是要顶格写,不能有空格回车。
<?xml version="1.0" encoding="UTF-8"?>
version是必须的属性,encoding是编码方式,默认是ISO-8859-1,告知解析引擎当前文档使用的字符集,用默认的去解码,上面的指示用utf-8,那么它就用utf-8去解码,否则编码跟解码不一样,就会乱码,所以还要注意你文件的编码是多少。以Notepad++为例,如下图:
所以,你用utf-8去编码,就要用utf-8去解码。但是idea编辑器会根据你的解码是utf-8,编码自动识别为utf-8,从编辑器的右下角就可以查看,如图:
它不单单有version,encoding属性,还有一个属性叫standalone:表示是否独立。如果是是的话,就是yes,
standalone="yes"
,表示这个文件是独立的,不依赖于其他文件。这个属性了解即可。
因为早期xml想要代替html来展示数据,所以它还可以引入css,这也是了解,如下代码:<?xml-stylesheet type="text/css" href="a.css"?>
-
xml有且只有一个根元素。什么是元素,元素,由三部分构成,开始标签+内容+结束标签,这一整个就是一个元素,所谓的根元素,就是这一元素外面没有被其它元素包围。声明信息不算。标签又叫元素,也叫节点。注意下面是错的,存在两个同级别的根元素:
<?xml version="1.0" encoding="UTF-8"?> <haha> </haha> <aaa> </aaa>
-
xml是大小写敏感的。比如
<a></A>
是错的。 -
标签是成对的,而且要正确嵌套。比如下面的代码是非法嵌套。
<a> <aa> </a> </aa>
-
属性值要加引号。
-
注释的写法:
<!-- 这里是注释 -->
-
DTD和XSD定义语义约束:DTD和XSD是用来规范xml的语法的,文件的格式。因为它过于灵活,想怎么写怎么写,就要有东西来规范一下,有个约束。后面会讲。注意一下:XSD约束其实是Schema约束,文件后缀是.xsd。
-
注意:xml的标签可以写中文,但不要这么做。
1.4 激活XML文件
只要是xml文件,都会在开头写上<?xml version="1.0" encoding="UTF-8"?>
这句话,打开编辑器比如idea,我们去新建一个xml文件,可能没有专门的xml文件,就会去新建File,然后取名为xxx.xml,但是这种建立,它的头并没有xml的版本声明以及编码的声明,每次建都要自己写,很麻烦,那有没有一种专门的xml文件,一新建它的头信息就已经写好了,我们就不用写了,答案是有的,以idea为例,首先点击idea左上角的File->Settings,如图:
点击,然后,如下图:
按照上面的步骤走,就好了,然后测试一下,点击项目右键,如图:
这样是不是就有了,去新建就自动有头信息了,就不用每次都去自己写了。
2. DTD和XSD定义语义约束
在讲它之前有个例子:
就是使用XML描述下表:
那么我们新建一个文件叫scores.xml。描述如下:
<?xml version="1.0" encoding="UTF-8"?>
<!--得有根元素-->
<scores>
<!--student你也可以写成stu,xml是一个很灵活的语言-->
<student id="1">
<name>小明</name>
<course>数学</course>
<score>77</score>
</student>
<student id="2">
<name>小美</name>
<course>语文</course>
<score>90</score>
</student>
<student id="3">
<name>小爱</name>
<course>英语</course>
<score>85</score>
</student>
<!--但是这种如果是团队开发,你写的标签名是student,别人写的是stu,都没错,但是当它们合并到一起,就显得有点乱,
取信息不好取,本来student和stu表示一个意思。所以,我们要对它进行约束,统一,比如,根元素必须是scores,
scores里面都是student标签,代表每一个学生对象,student必须有id属性,student标签里面有三个标签,分别是name,course,score。
按照这种格式写,标签名要统一,就是描述表格的时候要按我上面的来就是了。不管谁来写,最终写出来的效果就跟一个人写出来的是一样的。
-->
</scores>
浏览器打开如下:
因为xml文件写好后,我们需要用java技术来读取它,以后学习框架,框架就会自动的读取我们程序员写的配置文件进行解析,但是它的标签灵活,所以读取麻烦,那么就得用DTD来约束一下。
2.1 DTD
认识DTD
DTD:Document type definition(文档类型定义)
作用:约束文档格式,合法定义文档的结构。说白了,就是规定哪些标签是合法的,哪些是不合法的。
DTD分为外部DTD和内部DTD。内部DTD是在xml文件里定义的,外部DTD是单独的一个DTD文件,那么在xml文件中就要把外部的DTD引入进来,可以把约束文件理解为xml的说明文档。
内部DTD的使用
-
内部DTD的定义(内部的DOCTYPE声明):
语法:<!DOCTYPE 根元素 [元素声明] >
。DTD的约束会被包装到DOCTYPE的声明中。注意,这里的根元素不等于根节点,根节点(也叫文档节点)代表的是整个文档document,就是xml文件本身。而根元素(就是一个普通的元素节点)只是xml里面的一个根。注意区分。 -
元素声明语法:
<!ELEMENT 父元素名 (子元素[子元素...])>
括号里面的元素表示的是这个标签它里面可以出现哪些子标签,注意括号里面的是子标签,多个子标签用逗号隔开,但我们在xml中去使用它是,要注意顺序,比如约束文档中(name,age),那么你在xml文件中标签name就要写在age的前面。
-
数量词:限制元素出现几次
- +:表示出现1次或多次,至少一次。
- ?:出现0次或1次。
- *:表示出现任意次。
- 没有前三个修饰的标签表示这个标签必须出现一次。多了不行。
- |:比如:
<!ELEMENT 父标签 ((子标签1|子标签2))>
,这代表什么意思呢?表示这两个子标签必须有一个出现在父标签中,但是不能同时出现。
-
属性声明语法:
<!ATTLIST 元素名称 属性名称 属性类型 默认值>
属性类型如下:
CDATA表示字符类型,表示它是字符串。默认值参数有下列值:
比如我要保证student标签必须要有id属性,就是这么写,如下:<!ATTLIST student id CDATA #REQUIRED>
现在对上面写的代码进行约束,约束代码如下:
<!DOCTYPE scores [
<!ELEMENT scores (student+)>
<!ELEMENT student (name,course,score)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT course (#PCDATA)>
<!ELEMENT score (#PCDATA)>
<!ATTLIST student id CDATA #REQUIRED>
]>
注意上面的该空格要空格,不然没有效果。然后是PCDATA表示:意思是被解析的字符数据,可把字符数据想象为XML元素的开始标签与结束标签之间的文本,它没有子标签,就是一个纯粹的文本。完整代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE scores [
<!ELEMENT scores (student+)>
<!ELEMENT student (name,course,score)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT course (#PCDATA)>
<!ELEMENT score (#PCDATA)>
<!ATTLIST student id CDATA #REQUIRED>
]>
<scores>
<student id="1">
<name>小明</name>
<course>数学</course>
<score>77</score>
</student>
<student id="2">
<name>小美</name>
<course>语文</course>
<score>90</score>
</student>
<student id="3" >
<name>小爱</name>
<course>英语</course>
<score>85</score>
</student>
</scores>
ELEMENT是限制元素的,定义哪些标签合法。ATTLIST是限制属性的,定义哪些属性合法。
外部DTD的使用
-
创建一个独立的DTD文件。其实dtd文件也是一种特殊的xml文件,因为它有头信息。取名:scores.dtd,内容如下:
<?xml version="1.0" encoding="UTF-8"?> <!ELEMENT scores (student+)> <!ELEMENT student (name,course,score)> <!ELEMENT name (#PCDATA)> <!ELEMENT course (#PCDATA)> <!ELEMENT score (#PCDATA)> <!ATTLIST student id CDATA #REQUIRED>
我们发现写法其实跟内部的一样,只是外部的DTD不用写
<!DOCTYPE scores [
罢了。DOCTYPE 只存在于.xml的文件中。接下来就是在xml文件中去使用它。怎么使用呢,如下第2点。 -
格式:
<!DOCTYPE 根元素 SYSTEM "文件名">
所以只需要在xml文件中加上这句话:
<!DOCTYPE scores SYSTEM "scores.dtd">
在xml中引入dtd文件,就会对xml起到约束作用,那些该写,哪些不该写。这样 ,引入后,xml就会有提示了。到以后学习框架之类的就会明白。但是这种引入属于本地引入,SYSTEM表示system,就是系统的意思,代表本地,如果这个dtd文件在网络上,哪这样写就不对了,格式如下:
<!DOCTYPE 根元素 PUBLIC "dtd文件名字(随便写)" "dtd的网络路径url">
2.2 XSD(Schema约束)
XSD是DTD的升级版,替代者。不仅可以定义xml文档结构,还可以规范文档的内容(比如在xml有这么一个标签<sex>888</sex>,正常来说,sex应该表示性别,哪你写个数字888表示什么意思?我们是不是要对其内容进行限制?那么schema约束就可以完成这件事)。XSD本身也是xml文档,采用xml文档来定义语义约束,比DTD要复杂一点,但是功能强大很多。它是利用标签的父子关系来描述约束信息的。
- 支持丰富的数据类型。
- 允许开发者自定义数据类型。
- 可读性强。
- 可针对未来需求进行扩展。
注意你在mybatis看到如下的就是schema约束:
像上面这种,它属于在xml文件中引入Schema约束,注意是引入。还有注意,dtd约束和schema约束不能出现在同一个文档中。虽然像上面我们平时都是复制的,不是自己写,但是如果能够看懂,读懂,就行,所以,我们现在就来解读它。现在我有一个a.xml文件,如下图:
重点看上面,也就是根标签哪部分,像冒号,xmlns这些都是什么意思呢?用图说话。
有了上面的解释,我们来看看spring的配置文件Beans.xml ,如下:
一样,用图说话,如下:
接下来就是xsd文件的编写语法了,这里就直接粘贴上完整代码了,复制到你们的编辑器去看:
a.xml文件代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<cht:scores xmlns:cht="abc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="abc a.xsd">
<!--
abc是我们自己起的,可以随便写,但是想spring这些框架,都是写一个网址,这是因为网址是唯一的,不会重复的,所以,当我们定义多个schema约束时,别名能不能重复?
答案是肯定不能,这里一般会写公司的网址。
多个命名空间就有多个xmlns
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 声明当前的xml文件是Schema的一个实例(当前这是一个自定义的xml文件,是被某个Schema文件的约束)
不是一个Schema文件,如果是一个Schema文件,那么后面的instance就不要加上,你可以看看a.xsd文件它是不是没有instance
-->
<cht:student id="1">
<cht:name>小明</cht:name>
<cht:course>数学</cht:course>
<cht:score>77</cht:score>
</cht:student>
<cht:student id="2">
<cht:name>小美</cht:name>
<cht:course>语文</cht:course>
<cht:score>90</cht:score>
</cht:student>
<cht:student id="3">
<cht:name>小爱</cht:name>
<cht:course>英语</cht:course>
<cht:score>34.2</cht:score>
</cht:student>
</cht:scores>
a.xsd文件代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<cht:schema xmlns:cht="http://www.w3.org/2001/XMLSchema"
targetNamespace="abc"
elementFormDefault="qualified">
<!-- xmlns:cht表示引入了w3c规范,来规范当前约束文件的语法规则 。这句话是重点-->
<!-- targetNamespace="abc":表示文档中要定义的元素来自什么命名空间,对应xml里的xmlns:cht="abc"。这句话也能是重点
上面定义当中xmlns:cht和targetNamespace是重点
-->
<!-- elementFormDefault="qualified":表示要求xml文档的每一个元素都要有命名空间指定 -->
<!-- 主体部分 -->
<!-- 1.在Schema文件中使用element标签来定义xml中所有可以书写的标签名 -->
<cht:element name="scores">
<!-- 2,在scores这个根标签里,有name,course,score这三个子标签,但是不要直接在这里写element,要先分析,它是复杂标签
,还是简单标签。简单标签:如果一个标签没有子标签,也没有属性,这个标签是一个简单标签。
复杂标签:如果标签拥有属性或者拥有子标签,那么这个标签就是一个复杂标签。
那么根标签scores就是一个复杂标签,复杂标签就要用complexType来声明当前element(scores)是一个复杂标签
sequence:表示序列,使用这个标签来定义子标签之间的顺序
simpleType:来声明当前的element是一个简单标签,如下,但可以不写-->
<cht:complexType>
<cht:sequence>
<!-- minOccurs="1"表示最少出现1次 maxOccurs="unbounded"表示最多可以出现很多次 -->
<cht:element name="student" minOccurs="1" maxOccurs="unbounded">
<!-- student标签依然是复杂标签 -->
<cht:complexType>
<cht:sequence>
<cht:element name="name" type="cht:string"> <!-- type声明该元素的文本必须是字符串 -->
<!-- type的取值:cht:decimal,cht:integer,cht:boolean,cht:date,cht:time
element还有一个属性叫default,default就是默认值,fixed就是固定值
-->
<!-- <simpleType></simpleType> -->
</cht:element>
<cht:element name="course" type="cht:string"></cht:element>
<cht:element name="score" type="cht:double"></cht:element>
</cht:sequence>
<!-- 定义标签student的id属性 -->
<cht:attribute name="id" type="cht:string" use="required"></cht:attribute>
</cht:complexType>
</cht:element>
</cht:sequence>
</cht:complexType>
</cht:element>
</cht:schema>
把我上面的两个a.xml和a.xsd文件复制到你们的编辑器上去测试。
3. XML的解析技术(一种读取方式)
xml内容写好了,就要对xml进行解析。对xml文件进行操作,包括创建xml,对xml文件进行增删改查。所谓的解析,就是操作xml文档,将文档中的数据读取到内存中。
3.1 DOM(文档对象模型)解析
是官方(sun公司)提供的解析方式。它的特点是:基于xml树结构(在内存中形成一颗dom树),比较耗资源,适用于多次访问xml。它的读取方式是一次性将xml文档所有内容,加载到内存中,形成一个对象,而对象,肯定是耗内存的。所以它的缺点是浪费内存,优点是读取大量标签的时候,因为这些标签已经在内存中了,所以运行速度较快。它不仅可以处理xml,也可以处理html,比如在学js的时候,就会涉及dom操作,是不是会对里面的节点进行crud操作。
xml本身有许多节点,有元素节点,文本节点(包括回车空白),属性节点,注释节点,CDATA节点,文档节点。不要以为就只有元素叫节点。难以理解的就是CDATA节点,它的意思是避免内容里有特殊符号,比如尖括号这些,我们可以用<![CDATA[内容]]>
把内容包裹起来,如下:
<标签名><![CDATA[I like read <老人与海>]]></标签名>
如果不用CDATA,遇到<
,要用<
进行转义。
3.2 SAX解析
相对于上面是官方的,那么这就是民间的解析方式。它的特点是基于事件的解析。这种基于事件解析的消耗资源要少。这种读取方式,根据开发人员的需要,一次将若干个满足条件的标签加载到内存中,所以它可以节省内存。如果读取大量标签信息时,因为要经过多次io流,所以运行效率相当较低,并且它只能读取,不能增删改。
3.3 JDOM解析
它是一个工具,第三方提供,它开放源代码,比DOM更快,JDOM仅使用具体类而不使用接口。也就是说它提供了很多工具类,你可以拿它来解析。
3.4 JAXP解析
sun公司提供的解析器,支持dom和sax两种思想,此处了解即可。
3.5 DOM4J解析
注意,DOM4J的4是for,for就是为了的意思,不是4的英文four,是for,j是java的意思,其实就是一种为java提供解析方式的dom。它也是第三方提供的,开源免费,是JDOM的升级版。性能优异,功能强大,使用接口而不是实现类。像hibernate框架用它来解析xml配置文件。接下来我们使用dom4j来解析xml,如下:首先,创建一个项目,有xml和class类。
sorce.xml就是上面写的xml代码。
解析xml的入口,是需要拿到一个Document对象。用Document对象来表示xml文件。哪我们对xml文件的操作,就是对Document对象的操作。首先,我们要有dom4j的jar包,它不是jdk提供的,是第三方的,所以我们要去网上下载dom4j的jar包。下载网址:https://mvnrepository.com/artifact/dom4j/dom4j,选择1.6.1版本。然后在项目里新建lib文件夹,把jar包放进去。再对jar包build path,怎么build path?流程:File -> Project Structure -> Modules -> 选中要添加build path的项目 -> Dependencies -> 点击右边的小加号 -> 选择JARs or directories ->选择要添加的外部jar包
。
如果像这样,能将其展开,说明build path成功。我们主要用到两个类,它就在org目录下。
没错,就是DOMReader和SAXReader。DOM和SAX是不是很熟悉。接下来就是开始写代码了。如下代码:
package com.cht;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.util.Iterator;
public class TestXml {
public static void main(String[] args) throws DocumentException {
//1. 创建SAXReader对象,用于读写xml文件
SAXReader reader = new SAXReader();
//2. 读取xml文件,得到Document对象(这个对象代表整个xml文件,它拥有xml文件的所有信息)
File xmlFile = new File("src/sorce.xml");
Document document = reader.read(xmlFile);
//System.out.println(document);//org.dom4j.tree.DefaultDocument@6d311334 [Document: name file:///D:/Tinghuai Hotel/testxml/src/sorce.xml]
//3. 利用document获取xml文件里的每个学生的信息
//3.1 获取根元素
Element root = document.getRootElement();//元素类型
//上面是不是拿到根元素了,拿到根元素,哪我怎么获取它的名字呢?很简单,用root.getName()看看是不是scores
//System.out.println(root.getName());
//3.2 以根元素为出发点,循环遍历根元素下面的所有学生信息。
Iterator<Element> iterator = root.elementIterator();
while (iterator.hasNext()){
//取出元素
Element e = iterator.next();
System.out.println(e.getName());//打印3个student
//获取id属性,属性可以有多个,只不过我们这里只有一个属性,就是id。那么属性有没有迭代器,是有的。
//因为我们只有一个属性,所有先不用迭代
Attribute id = e.attribute("id");//注意,该方法有3个重载方法,参数分别是(int i),(String s),(QName qName)
//注意上面的,参数是int类型表示第几个属性,string类型表示属性名,QName不管
System.out.println(id.getName() +"="+id.getValue());
//获取student的子元素
Element name = e.element("name");
Element course = e.element("course");
Element score = e.element("score");
System.out.println(name.getName()+"="+name.getStringValue());
System.out.println(course.getName()+"="+course.getText());
System.out.println(score.getName()+"="+score.getStringValue());
//getStringValue()和getText()都可以
System.out.println("=====================================");
}
}
}
执行效果:
这样是不是成功的把xml信息拿到了呀!!!总结:首先,要拿到Document对象,拿到Document对象再通过该对象拿到根节点,拿到了根节点,就可以用迭代器把下面的元素迭代出来,该迭代的迭代,不用迭代的就不要迭代。
_dom4j_生成xml
上面呢我们是对xml读数据,现在我们是要写数据。把数据写进去,创建一个xml。首先,创建一个类,如下:
package com.cht;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
public class TestXml2 {
public static void main(String[] args) throws IOException{
// 1. 通过DocumentHelper生成一个Document对象
Document doc = DocumentHelper.createDocument();
// 2. 添加并得到根元素
Element root = doc.addElement("books");
// 3. 为根元素增加子元素
Element book = root.addElement("book");
// 4. 为book元素添加属性,它的返回值也是Element,代表book本身
book.addAttribute("id", "b01");
// 5. 为book添加子元素
Element name = book.addElement("name");
Element author = book.addElement("author");
Element price = book.addElement("price");
// 6. 为子元素添加文本,它的返回值也是Element,其实说白了就是方便去链式编程
name.addText("PHP from beginners to proficient");
author.addText("Tomorrow Technology");
price.addText("30");
// 7. 将doc输出到xml文件中即可
Writer writer = new FileWriter(new File("src/books.xml"));
doc.write(writer);
// 8. 关闭资源
writer.close();
}
}
但是这样输出生成的xml却在一行显示,如下:
那怎么办呢?这就需要一个XMLWinter类了。如下代码:
package com.cht;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import javax.sql.rowset.spi.XmlWriter;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
public class TestXml2 {
public static void main(String[] args) throws IOException{
// 1. 通过DocumentHelper生成一个Document对象
Document doc = DocumentHelper.createDocument();
// 2. 添加并得到根元素
Element root = doc.addElement("books");
// 3. 为根元素增加子元素
Element book = root.addElement("book");
// 4. 为book元素添加属性,它的返回值也是Element,代表book本身
book.addAttribute("id", "b01");
// 5. 为book添加子元素
Element name = book.addElement("name");
Element author = book.addElement("author");
Element price = book.addElement("price");
// 6. 为子元素添加文本,它的返回值也是Element,其实说白了就是方便去链式编程
name.addText("PHP 从入门到精通");
author.addText("明日科技");
price.addText("30");
//7 格式良好的输出
OutputFormat format = OutputFormat.createPrettyPrint();//美化格式
XMLWriter writer = new XMLWriter(new FileOutputStream(new File("src/books.xml")),format);
writer.write(doc);
// 8. 关闭资源
writer.close();
}
}
从数据库里获取数据写入到xml中
这个无非就是从数据库获取list类型的数据,还是一上面学生为例,但此时就不去访问数据库了,自己写一个list类型的数据模拟一下即可,我们要有一个实体类,和一个测试类,如下结构:
Student代码如下:
package com.cht;
public class Student {
private String id;
private String name;
private String course;
private String score;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCourse() {
return course;
}
public void setCourse(String course) {
this.course = course;
}
public String getScore() {
return score;
}
public void setScore(String score) {
this.score = score;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", course=" + course
+ ", score=" + score + "]";
}
}
TestStudent代码如下:
package com.cht;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
public class TestStudent {
public static void main(String[] args) throws IOException{
//1. 将这些数据备份为xml文件
//查询所有的数据为一个list集合,泛型Student
List<Student> list = selAll();
//System.out.println(list);
//[Student [id=1, name=小米, course=数学, score=76], Student [id=2, name=小美, course=语文, score=90]]
// 2. 将list中的数据输出到一个xml文件中
writeStudent(list);
}
private static void writeStudent(List<Student> list) throws IOException {
// TODO Auto-generated method stub
Document doc = DocumentHelper.createDocument();
Element root = doc.addElement("scores");
//循环根元素添加子元素
for (Student stu : list) {
Element e = root.addElement("student");
e.addAttribute("id", stu.getId());
Element name = e.addElement("name");
Element course = e.addElement("course");
Element score = e.addElement("score");
name.addText(stu.getName());
course.addText(stu.getCourse());
score.addText(stu.getScore());
}
//输出到文件中
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWriter xmlWriter = new XMLWriter(new FileOutputStream(new File("src/sorce1.xml")),format);
xmlWriter.write(doc);
xmlWriter.close();
}
//查询所有的学生
private static List<Student> selAll() {
// TODO Auto-generated method stub
//模拟数据库
List<Student> list = new ArrayList();
Student stu = new Student();
Student stu1 = new Student();
stu.setId("1");
stu.setName("小米");
stu.setCourse("数学");
stu.setScore("76");
stu1.setId("2");
stu1.setName("小美");
stu1.setCourse("语文");
stu1.setScore("90");
list.add(stu);
list.add(stu1);
return list;
}
}
执行main方法,就会在项目中看到scorce1.xml文件啦!
这样就成功的把数据库里的东西读出来了。以上就是了解,因为在开发过程中,解析xml文档不需要开发人员手动去写。比如框架,它会写好约束文档,并且会自动的封装xml的读取,我们只需要引入约束文档,然后把xml文件写出来即可。
3.6 Jsoup解析
jsoup不仅可以解析html,也可以解析xml,要用它,一样要导入jar包,去maven库搜索jsoup版本1.11.3即可。
package com.cht;
import java.io.File;
import java.io.IOException;
import java.net.URL;
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 {
//1. 获取Document对象(有三种方式)
String path = JsoupDemo.class.getClassLoader().getResource("a.xml").getPath();
//1.1 解析xml文档,加载文档进内存,形成dom树,形成的dom数就是Document对象。utf-8要与文件的编码一致
Document doc = Jsoup.parse(new File(path), "utf-8");
//System.out.println(doc); 打印的doc是字符串形式的html
//2. 获取元素(Element)对象
Elements elementsByTag = doc.getElementsByTag("cht:name");//获取标签为name的元素,返回的是Elements,是个复数,我们的xml中一共有3个name标签,那么
//这里面是不是有个name元素,把它当做ArrayList<Element>来使用
//System.out.println(elementsByTag.size());// 答案是3
//3. 获取第一个name的Element对象
Element element = elementsByTag.get(0);
//4. 获取数据
String name = element.text();
}
}
- Jsoup:
parse:解析html或xml,返回Document。
parse(File in,String charsetName)
parse(String html)
:解析html或xml字符串的。
parse(URL url,int timeoutMillis)
:通过网络路径获取指定的html或xml的文档对象,timeoutMillis是超时时间。 - Document: 可获取Element对象,它是继承于Element对象的。
getElementsByTag(String tagName)
:根据标签的名称获取元素对象的集合。
getElementsByAttribute(String key)
: 根据属性名称获取元素对象集合。
getElementsByAttributeValue(String key,String value)
: 根据属性名和属性值获取元素的集合。
getElementsById(String id)
: 根据id属性值获取唯一的element对象。 - Element: 元素对象。
用它获取子元素对象,所以像上面第2点里的4个方法都能用。
获取属性值:String attr(String key)
:根据属性名称获取属性值,这里的key不区分大小写。
获取文本内容:String text()
获取标签体的所以内容(包括子标签的字符串内容):String html()
。 - Node: 节点对象:是Document和Element的父类。
- 快捷查询方式之selector:选择器
Elements select(String cssQuery)
:cssQuery是css选择器,比如#id,[attr],*,这些都是css选择器,具体去网上查找。
快捷查询方式之XPath:是一门在xml文档中查找信息的语言。使用Jsoup的Xpath需要额外导入jar包(JsoupXpath-0.3.2.jar),XPath语法会有专门一章来说。
xml和html的区别
- xml重点是传输,存储数据,而html是展示数据的,作为网页的。因为xml的灵活可扩展性作为网页肯定不行,它通常是作为配置文件的,这样对于数据也非常清晰。
- html是一个事先约束好的文档语言,标签不能随便写。而xml的标签你爱写啥写啥。
- HTML标签对于英文字母的大小写是忽略不计的,而xml就会严格区分大小写。
- html标签中属性值可以有引号,也可以不用引号,但是xml的属性值必须要有引号(双单引号都行)。
- html标签你可以省略</p>或者</li>之类的结束标记,语法比较松散,在xml中,是绝对不能省略结束标记的,要么你自闭合,比如<br/>。语法比html严格。
- html和xml都遵循w3c规范,w3c翻译过来是世界万维网联盟,它是一个组织,像Schema文件的书写规则都是由W3C组织定义的。
- xml是html的一种补充,不是来替换html的(早期是,现在不是)。是先有html再有xml。
DTD约束和XSD约束的区别
- DTD约束xml的时候,不能对xml中的数据类型做详细的限定。而XSD比DTD更加的细致,比如对数字区间的限定,限定数字必须是1到100之间的。
- DTD约束有自己的语法,书写时必须遵守DTD的语法,而书写Schema文件的时候,它的语法跟写xml文件的一样,它本身也是xml文件。
- 一个xml文件中只能引入一个DTD文件约束,而无法通过多个DTD文件来约束同一个xml文件。但是可以引入多个Schema约束。