XML
XML概述
-
“XML”全称:Extensible Markup Language,可扩展的标记语言
语言:它是一门独立的语言,有自己的语法
标记:也叫“标签”,他是使用一对尖括号括起来的一个“名字”----可以看做:给“数据”起的名字。 -
XML它是一个“纯文本文件”,记录大量数据的时候,使多个数据比较有层次感,比较易读,容易管理。
例子:之前一个“类”的配置文件:classes.txt
className = com.demo01.Student
methodName=study
这种配置文件如果要记录多个类名,多个方法名,就不好记录了。
我们可以采用XML文件记录:classes.xml
会使数据更加“立体”,“有层次”。
这种“标签+数据”的存储方式,使文档更加:容易读,容易管理,尤其是在存储大量数据时。
<classes>
<class>
<className>com.demo01.Student</className>
<methodName>show1</methodName>
<methodName>show2</methodName>
</class>
<class>
<className>com.demo01.Student</className>
<methodName>study</methodName>
</class>
</classes>
XML的应用方向
- 存储数据:我们以前存储Student信息时,使用的纯文本文件,就可以使用xml文件代替,但以后会使用“数据库”。
- 做配置文件:后期各大框架都是使用XML做配置文件,用的比较多
总体上看XML文件的作用:就是一个纯文本文件,存储数据
XML语法
XML语法总述:
- XML作为一门独立的语言,有自己特有的语法。
- XML的语法构成:
- 文档声明;
- 标签
- 属性
- 注释
- 转义字符
- CDATA区
XML语法-文档声明:
- XML的“文档声明”:是写在“XML文档”的第一行,格式:
格式说明:
1. 以“<?xml”开头,这五个字符之间不能有空格
2. 以“?>”结尾,这2个符号之间不能有空格
3. 只能有两个属性:
1. version=“1.0/1.1”:表示此XML文档使用XML语法的版本,通常是1.0
2. encoding=“UTF-8”:表示此XML文件使用编码。如果有中文,通常使用UTF-8
2. 文档声明的作用:它不是用来存储数据的,而是给XML文件编辑器,解析器看的,告诉他们这个XML文档使用的什么“版本”,“编号”方式,有利于对此文档进行编辑,解析
3. 注意:
1. “文档声明”对于一个XML文档不是必须的,可以没有,不影响解析
2. 在一个XML文件中,最多只能有一个“文档声明”,而且必须要此XML文档0行,0列的位置,之前不能有空格,空行,注释。
XML语法—元素(标签)
- 由于XML文件是:标签+数据的形式存储,所以“标签”是XML中的重要组成部分。
- “标签”的“名字”是由我们程序员自己定义的,但是也有语法要求
语法规则:
1. 名字中可以包含:字母(包括中文),数字,四个符号(_-:.)
2. 不能以:数字,-符号,.符号开头
3. 名字中间不能有“空格”。 - “标签"的分类:
1. 完整标签:有开始标签,也有结束标签,子标签的名字可以重复
张三
18
2. 单标签:只有开始标签,同时也是结束标签。它可以通过“属性”来记录数据,但属性名不能重复
- 注意:
“标签名”是区分大小写的:
这种标签在一个XML文档中可以同时出现,也可以被正常解析
XML语法-属性:
- 任何标签都可以定义“属性”,也是用来存储数据的。
例如:
例如:
show1
- 格式说明:
- 每个属性是:属性名=“值”
- 多个属性之间使用“空格”隔开
- 多个属性,不能“同名”
- 属性的“值”必须要使用一对“双引号”或者一对“单引号”括起来
XML-注释
- XML中只有一种注释:
- 注意:
- 以“<!–”开头,4个符号之间不能有“空格”;
- 以“–>”结尾,3个符号之间不能有“空格”
- 注释不能“嵌套”使用:<!-- 注释内容–>,错误格式
XML语法-转义字符
- 在XML文件中,有些符号是作为“格式符号”使用的,例如:><’"等…如果用户的数据中出现这些符号,不能直接存储,否则在解析时可能会有问题:例如:
a < b
,错误!!! - XML中定义了一些“转义字符”,来替代这些格式符号:
XML语法CDATA区
- 如果用户数据中包含了“大量的转义字符”:
例如:要存储以下数据:
<code>
String str = “fjekoeTEWjfekTEWe”;
int count = 0;
for(int i = 0;i < str.length(); i++){
char c = str.charAt(i);
if(c >= ‘A’ && c <= ‘Z’){
count++;
}
}
System.out.println(“count = “ + count);
</code>
使用“转义字符”: (代替大量的格式符号,可读性差,编写困难)
<code>
String str = "fjekoeTEWjfekTEWe";
int count = 0;
for(int i = 0;i < str.length(); i++){
char c = str.charAt(i);
if(c >= 'A' && c <= 'Z'){
count++;
}
}
System.out.println("count = " + count);
</code>
- 这时可以使用CDATA区:当XML解析器解析这个XML文档时,如果时CDATA区中的内容,全部作为“数据”处理了。
<code>
<![CDATA[
String str = “fjekoeTEWjfekTEWe”;
int count = 0;
for(int i = 0;i < str.length(); i++){
char c = str.charAt(i);
if(c >= ‘A’ && c <= ‘Z’){
count++;
}
}
System.out.println(“count = “ + count);
]]>
</code>
XML约束的概念及其作用
- XML的标签是由程序员自己定义的,可以定义任何名称。但如果我们做一个项目,需要记录一些数据,采用XML的方式,通常只希望这个XML文件中记录我们程序中需要的数据,尤其是“标签”都是跟业务数据相关的,相对是固定的,这时就不希望这个XML文件中出现与业务无关的其他标签。
- XML也可以定义一些“约束文件”,来约束这个XML文档:
1. 可以约束这个文档:可以出现哪些标签;
2. 可以出现标签的包含关系;
3. 约束标签的“出现顺序”,“出现的次数”
4. 还可以约束标签中可以包含的属性
… - XML的约束有两种:
- DTD约束:比较简单,可以对一些要求不是很严格的小型的xml文件做约束
- Schema约束:比较复杂,可以对要求很严格的中,大型xml文件做非常细致的约束
DTD约束:
- DTD约束是一个比较简单的约束,有自己独立的语法格式。
- DT约束使用的位置:
- XML文档内部
- XML文档外部:本地【本次演示】
- XML文档外部:网络
- 演示步骤:
- 创建一个DTD文件:XXX.dtd
- 创建一个XML文件:XXXX.xml,并且在内部引入XXX.dtd文件:
示例代码:
books.dtd
<!ELEMENT 书架 (书+)><!--对"书架"元素进行约束,表示:书架中只能有"书"子元素可以出现1到多次-->
<!ELEMENT 书 (书名,作者,售价)><!--约束元素书的子元素必须为书名、作者、售价,而且必须按这个顺序-->
<!ELEMENT 书名 (#PCDATA)><!--表示:书名元素中只能包含数据-->
<!ELEMENT 作者 (#PCDATA)>
<!ELEMENT 售价 (#PCDATA)>
books.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE 书架 SYSTEM "books.dtd">
<书架>
<书>
<书名>aaa</书名>
<作者>bbb</作者>
<售价>ccc</售价>
</书>
<书>
<书名>aaa</书名>
<作者>bbb</作者>
<售价>ccc</售价>
</书>
</书架>
代码图解
Schema约束
- Schema约束要比DTD约束更复杂,可以进行更细致的约束
- 演示步骤:
- 创建一个Schema约束文件:xxx.xsd,它内部是一个标准的XML格式
- 创建一个XML文件,来引入xxx.xsd约束文件:
代码演示:
books.xml
<?xml version="1.0" encoding="UTF-8" ?>
<书架 xmlns="hehe"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="hehe books.xsd"
>
<书>
<书名></书名>
<作者></作者>
<售价>88.8</售价>
</书>
<书>
<书名></书名>
<作者></作者>
<售价>99</售价>
</书>
</书架>
books.dtd
<?xml version="1.0" encoding="UTF-8" ?>
<!--
传智播客DTD教学实例文档.将注释中的以下内容复制到要编写的xml的声明下面
复制内容如下:
<书架 xmlns="http://www.itcast.cn"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.itcast.cn bookshelf.xsd"
>
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="hehe"
elementFormDefault="qualified">
<xs:element name='书架' ><!--对<书架>标签进行约束-->
<xs:complexType><!--表示复合类型,下面要定义:子元素、或者是属性-->
<xs:sequence maxOccurs='unbounded' minOccurs="1" ><!--约束下面的子元素必须按顺序出现-->
<xs:element name='书' >
<xs:complexType>
<xs:sequence>
<xs:element name='书名' type='xs:string' />
<xs:element name='作者' type='xs:string' />
<xs:element name='售价' type='xs:double' />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
代码图解:
XML解析
三种解析方式介绍:
- 由于XML文件内部是:“标签 + 数据”的形式,所以如果使用IO流自己解析这样比较麻烦。
- 有很多公司提供了专门解析XML文件的软件包。
- 常用的三种解析方式:
- DOM解析:一次性将XML文件内容全部读取到内存,并封装对象,在对象中完全保留XML文档结构信息
优点:对象内部保留XML文件层次结构,可以对元素进行增删操作。
缺点:比较占用内存 - SAX解析:一次只能解析一行,而且解析一行丢掉一行
优点:不读取所有内容,所以不占太多内存。快
缺点:不保留XML文档内部结构,不能对元素进行增删操作。 - PULL解析:Android内置的XML解析方式,类似SAX
- DOM解析:一次性将XML文件内容全部读取到内存,并封装对象,在对象中完全保留XML文档结构信息
几种解析工具介绍
1. JAXP:SUN公司提供支持DOM和SAX开发包。
2. Dom4j:比较简单的解析开发包【我们学习使用的】
3. JDom:与Dom4j类似
4. Jsoup:功能强大DOM方式的XML解析开发包,尤其对HTML解析更加方便
解析原理及其DOM模型
- XML的DOM解析及DOM模型:
DOM4J的使用步骤及其常用方法:
DOM4J是一个第三方软件包,专门用于解析XML文件的
使用步骤请移步第三方jar包的导入步骤
Element的常用方法:
- public String getName():获取当前Element对象的标签名;
- public Document read(File file):读取XML文件,生成DOM树(具体介绍自行查询)
- public Element getRootElement():获取Document对象的根元素;
- public List elements():获取此Element对象的所有子元素;
- public List elements(String tagName):获取此Element对象的所有的tagName的子元素;
- public String attributeValue(String attName):获取此Element对象的attName属性的值;
- public String elementText(String tagName):获取此Element对象的tagName子元素的值;
- public String getText():获取当前Element元素的值;【自己测试】
代码演示
public static void main(String[] args) throws Exception {
//1.创建SAXReader对象
SAXReader reader = new SAXReader();
//2.读取XML文件,生成DOM树
Document dom = reader.read(new FileReader("books.xml"));
//3.获取根元素
Element root = dom.getRootElement();
System.out.println("标签名:" + root.getName());
//4.获取它的所有子元素
// List<Element> es = root.elements();//获取root的所有子元素
List<Element> es = root.elements("book");//获取root的所有的<book>子元素
for (Element e : es) {
//e就是<book>元素
//1.获取id属性
String id = e.attributeValue("id");
System.out.println("id = " + id);
//2.获取e的<name>子元素的"值"
String name = e.elementText("name");
System.out.println("name = " + name);
String author = e.elementText("author");
System.out.println("author = " + author);
String sale = e.elementText("sale");
System.out.println("sale = " + sale);
}
}
DOM4J结合Xpath解析XML
- 刚刚我们使用DOM4J解析XML文件,从Document对象开始,到“根元素”,再到根元素的“子元素”,再到“孙元素”…
要获取某个元素的值,都要从“根元素”开始。这样如果层次比较深,就比较麻烦。 - Xpath工具包,它可以使用类似于Windows的“路径”的方式,快速的定位到一个“子元素”上。
常用方法:
- public Node selectSingleNode(String xpath路径):只获取一个元素
- public List selectNodes(String xpath路径):获取多个元素(元素的集合)
代码演示
public static void main(String[] args) throws Exception {
//1.创建SAXReader对象
SAXReader reader = new SAXReader();
//2.读取xml,生成dom树
Document dom = reader.read(new FileReader("books.xml"));
//3.dom + XPath
Element root = (Element)dom.selectSingleNode("/books");
System.out.println(root.getName());
System.out.println("----------------------------------------");
List<Element> list = dom.selectNodes("//book/name");
for (Element e : list) {
System.out.println(e.getText());
}
}