一 XML基本概述
1. XML简单的历史介绍
1969年 GML 通用标记语言
用于计算机之间的通信,通信就会传输数据,那么就需要一种数据的规范
1985年 SGML 标准通用标记语言
对GML进行完善
1993年 HTML 超文本的标记语言(HyperText Markup Language)
随着万维网的推广,在SGML的基础上,又出现了HTML语言,用于万维网上的页面展示
但HTML有不少缺陷:
a.标签不能扩展,不能自定义,只能使用默认的
b.兼容性不好(不同浏览器同一页面效果可能不一样)
c.不能描述数据(主要做页面展示)
例如描述一个学生信息 name:张三 id:12 age:23
<table>表格
<tr>行
<td>张三</td>
<td>12</td>
<td>23</td>
</tr>
</table>
1998年 XML 可扩展的标记语言(Extensible Markup Language)
W3C组织在1998年推出了可扩展标记语言XML(W3C万维网联盟创建于1994年,是Web技术领域最具权威和影响力的国际中立性技术标准机构)。
XML语言的本身是用来替代HTML语言的,但是俩种语言还有一定差异的,所以中间出现了一种过渡的语言:XHTML。但实际上XML语言已经很难替代HTML语言了,因为HTML语言的使用在整个万维网上使用太广泛了。
XML中标签可以自定义,描述性很好,例如:
<student id="001">
<name>lucy</name>
<age>24</age>
</student>
2. XML显著优点
可扩展标记
可描述数据
传输数据案例:
项目小组
组长:张三
组员:。。。
测试:李四
监督人员:。。。
<项目小组 项目名称="Xxx系统">
<组长>张三</组长>
<组员们>
<组员>...</组员>
<组员>...</组员>
<组员>...</组员>
</组员们>
<测试人员们>
<测试人员>...</测试人员>
<测试人员>...</测试人员>
<测试人员>...</测试人员>
</测试人员们>
<监督人员>李四</监督人员>
</项目小组>
3. XML有什么作用,为什么要学习XML
<students>
<student>
<age>15</age>....
</student>
<student>
....
</student>
</students>
(现在用的都不多了,但还有一些地方在用):
第一个用处: 做数据传输,具备一定的格式(相当于是一种介质)
a.数据的可读性
b.将来的扩展
c.将来的维护
XML现在已经是业内传输数据的标准,它和开发语言无关。
第二个用处:配置文件,之前使用的.properties资源文件中描述的信息不丰富,无法描述层次复杂的数据
第三个用处: 保存数据,充当小型的数据库
保存数据一般是使用数据库保存,或者使用一般的文件保存,这个时候也可以选择XML文件,因为XML可以描述复杂的数据关系。从普通文件中读取数据的速度肯定是比从数据库中读取数据的速度快,只不过这样不是很安全而已
二 XML基本语法
1.文档声明
XML文件的后缀为.xml;
XML文本要求文件有一个头部声明(用来告诉解析器一些相关信息);
<?xml version="1.0" encoding="UTF-8"?>
头部声明是给解析器看的,表明当前文件是xml文件,XML版本为1.0,文件内容使用的字符编码为UTF-8。
注意:要小心在系统中这个xml文件保存时候的编码,是否和文件内容中设置的编码一致;
头部声明可以省略,如果不写,会默认加上<?xml version="1.0"?>。
注意:
XML语法很严格,只要有问题,浏览器就无法正常显示;
如果文件的保存格式不对,无法显示;
如果文件格式上有任何问题,也无法显示。
ansi (American National Standards Institute)美国国家标准协会
ansi编码 是这个协会组织指定的一种字符编码
ansi编码在不同国家表示是不用的 中文操作系统中的ansi编码是GB2312 GBK
2.元素
2.1根元素
每个XML文档必须有且只有一个根元素;
根元素是一个完全包括文档中其他所有元素的元素;
根元素的起始标记要放在所有其他元素的起始标记之前;
根元素的结束标记要放在所有其他元素的结束标记之后。
2.2标签
xml文件中的标记也可以叫标签、元素、节点。
XML元素指XML文件中出现的标签,一个标签分为开始标签和结束标签,一个标签有如下几种书写形式;
例如:
包含标签体:<a>www.baidu.com</a>
不含标签体的:<a></a>, 可以简写为:<a/>
一个标签中也可以嵌套若干子标签,但所有标签必须合理的嵌套,
例如:<a>你好!<b>程序员</b></a>;
但绝对不允许交叉嵌套。
例如:<a>你好!<b>程序员</a></b>
2.3 标签内容
对于XML标签中出现的所有空格和换行,XML解析程序都会当作标签内容进行处理。
例如:下面两段内容的意义是不一样的(解析阶段才关心)。
<name>tom</name>
<name>
tom
</name>
由于在XML中,空格和换行都作为原始内容被处理,所以,在编写XML文件时,要特别注意。但是在一些封装好的解析方式中,是可以忽略掉这些空格和换行的。(例如在一些第三方提供的jar包中)
2.4 元素命名规则
一个XML元素可以包含字母、数字以及其它一些可见字符,但必须遵守下面的一些规范:
a. 区分大小写,例如,<P>和<p>是两个不同的标记。
b. 不能以数字开头.
c. 不能包含空格。
注意,XML语法十分严格,以上提到的点,任何一点出问题都不能在浏览器中正常显示。
3.属性
属性出现在 起始标签内部,和标签名用空格隔开。
它的基本格式为:
<元素名 属性名1="属性值" 属性名2="属性值" ...>
注意:
a. 一个元素可以有多个属性;
b. 属性值用双引号(")或单引号(')括起来;
c. 特定的属性名称在同一个元素标记中只能出现一次;
b. 属性值不能包括<, >, &等特殊字符。
例如:
<student id="100">
<name>TOM</name>
</student>
4.实体 ENTITY
xml文件中有些特殊的字符是不能直接表示出来的,例如:大于号,小于号,单引号、双引号等等,为了表示它们,我们可以借助实体完成。
实体可以分为两类:预定义实体、自定义实体。
a.预定义字符实体,由XML规范预先定义好了
< <
> >
& &
" "
' '
注意:使用实体的格式是 &实体名字;
b.自定义实体 ENTITY
定义格式:
<!DOCTYPE 根元素名称[ //其他字符串也可以,并不必须是根元素名称
<!ENTITY 实体名1 "实体内容">
<!ENTITY 实体名2 "实体内容">
...
]>
eg:
<!DOCTYPE courses[
<!ENTITY company "昆山杰普软件科技有限公司">
]>
其中:company为实体名称;
"昆山杰普软件科技有限公司"是实体内容;
实体的使用 &company;
4.注释
<!-- 这是一个注释 -->
注意:
a. 注释内容中不要出现--;
b. 不要把注释放在标记内部;
<Name <!-- the name -->>TOM</Name> 是不合适的
c. 注释不能嵌套;
d. 可以在除标记以外的任何地方放注释;
5.PCDATA,CDATA
在XML文件内部,有两部分数据组成:可以解析的,不能解析的
可以解析的 PCDATA
不需要|不可以解析的 CDATA
PCDATA (Parsed Character Data) 会被xml文档解析器解析的,但是有些特殊字符需要借助实体才可以被解析器解析,XML文件中的正常内容基本都是PCDATA。
CDATA (Character Data) 不会被xml文档解析器解析的,按字符串原样输出。
有些内容,例如< > &不想让解析,按照内容原样输出就可以了,这种情况可以使用CDATA。
格式:
<![CDATA[需要原样输出的字符串]]>
例如: <![CDATA[<<<<]]>
<test><![CDATA[&&&]]></test>
使用这个东西,我们可以保存二进制文件(图片)。
后期myBatic里面用xml存放sql语句,里面包含很多特殊字符,也要用到CDATA。
三 XML的解析
1. SAX解析与DOM解析原理理解
XML解析分为:dom解析和sax解析
dom:(Document Object Model, 即文档对象模型) 是 W3C 组织推荐的处理 XML 的一种方式。
sax: (Simple API for XML) 不是官方标准,但它是 XML 社区事实上的标准(相当于是一个民间标准),几乎所有的 XML 解析器都支持它。
dom和sax都是一种模型/标准/理论,是需要其他人使用具体的代码去实现的。
xml解析器就是用来对dom或者sax解析标准的具体实现。
1.1 SAX解析
SAX:基于事件处理的机制
sax解析xml文件时,遇到根开始标签,根结束标签,开始解析文件,文件解析结束,字符内容,空白字符等都会触发各自的方法。
优点:
适合解析大文件,对内存要求不高
轻量级的解析数据方式,效率更高
缺点:
不能随机解析(只能从头开始解析,一点点往后进行)
不能修改XML文件,只能进行查询
Jaxp中SAX解析步骤
//1.获取解析工厂
SAXParserFactory factroy = SAXParserFactory.newInstance();
//2.使用工厂创建SAX解析器
SAXParser saxParser = factroy.newSAXParser();
//3.开始解析 传入解析文件,重写解析事件
saxParser.parse(file, new DefaultHandler(){
startDocument() ---> 解析器发现了文档的开始标签
endDocument() ---> 解析器发现了文档结束标签
startElement() ---> 解析器发现了一个起始标签
character() ---> 解析器发现了标签里面的文本值
endElement() ---> 解析器发现了一个结束标签
});
注意:SAX只能解析,不能修改!!!
简单语法:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE briup [
<!ENTITY company "昆山杰普软件有限公司">
<!ENTITY address "昆山巴城镇浦东软件园">
]>
<!-- 班级信息 -->
<briup>
<class id="1" group='java'>
<name>jd1911</name>
<size>55</size>
<Room>第一教室</Room>
<teacher>"><'</teacher>
<bookName>xml&oracle&jdbc</bookName>
<study>公司:&company;;位置:&address;</study>
<comtent>
<![CDATA[
select id,last_name from s_emp where id<10;
<?xml version = "1.0" encoding = "utf-8">
]]>
</comtent>
</class>
</briup>
统计xml文件中每个人的金额数:
<?xml version="1.0" encoding="UTF-8"?>
<users>
<user name = "tom">26.5</user>
<user name = "jack">126.5</user>
<user name = "tom">30.4</user>
<user name = "mark">52.1</user>
<user name = "tom">12</user>
<user name = "jack">35</user>
<user name = "tom">95.3</user>
</users>
package com.briup.xml.chap01;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class SaxUser {
public static void main(String[] args) throws Exception {
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
sp.parse("src/com/briup/xml/chap01/user.xml", new DefaultHandler() {
// Set<String> set = new HashSet<String>();
Map<String,Double> map = new HashMap<String,Double>();
// Set<String> keySet = map.keySet();
boolean flag = false;
String name ="";
double count = 0.0;
// boolean flag = false;
// double count = 0;
@Override
public void startDocument() throws SAXException {
}
@Override
public void endDocument() throws SAXException {
System.out.println(map);
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
for(int i =0;i<attributes.getLength();i++) {
//set.add(attributes.getValue(i));
name = attributes.getValue(0);
flag = true;
// System.out.println(set);
}
// for(String name : set) {
// map.put(name, 0.0);
// }
//
//
// for(String name : set) {
// if(qName.equals(name)) {
// flag = true;
// //map.put(name, map.get(name)+count);
//
// }
// }
// if(qName.equals("price")) {
// flag = true;
// }
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
// for(String name : set) {
// if(qName.equals(set)) {
// map.put(name, map.get(name)+count);
//
// }
// }
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
String msg = new String(ch,start,length);
if(flag) {
count = Double.valueOf(msg);
if(map.containsKey(name)) {
map.put(name, map.get(name)+count);
}
else {
map.put(name,count);
}
//System.out.println(count);
flag = false;
}
}
});
}
}