目录
2).(#PCDATA):可以包含任何字符数据,但是不能在其中包含任何子元素
3).ANY:元素内容为任意的,主要是使用在元素内容不确定的情况下
5).混合元素 子元素是任意类型 出现任意次数 并且没有出现顺序要求
4).enumerated:(枚举值1|枚举值2|枚举值3...),属性值必须在枚举值中
3).default-value:属性可以不出现,并且当它不出现的时候是有默认值的,而该属性的默认值就是attribute-value
4).#FIXED :属性可以不出现,但是如果出现的话必须是指定的属性值
一 、XML简单的历史介绍
1969年 GML 通用标记语言
用于计算机之间的通信,通信就会传输数据,那么就需要一种数据的规范
1985年 SGML 标准通用标记语言
对GML进行完善
1993年 HTML 超文本的标记语言(HyperText Markup Language)
Client/Server 客户端/服务器
Browser/Server 浏览器/服务器
富客户端/服务器---->小程序,快应用
随着万维网的推广,在SGML的基础上,又出现了HTML语言,用于万维网上的页面展示
1998年 XML 可扩展的标记语言(Extensible Markup Language)
HTML有不少的缺陷,HTML语言的标记不能自定义,HTML语言的标记本身不能用来描述数据,HTML语言的标记没有国际化(不同浏览器显示同一页面的效果可能不一样)
W3C组织在1998年推出了可扩展标记语言XML
XML语言的本身是用来替代HTML语言的,但是俩种语言还有一定差异的,所以中间出现了一种过渡的语言:XHTML
但实际上XML语言已经很难替代HTML语言了,因为HTML语言的使用在整个万维网上使用太广泛了。
二 、XML有什么作用,为什么要学习XML
第一个需求: 数据传输需要一定的格式
1.数据的可读性
2.将来的扩展
3.将来的维护
XML现在已经是业内传输数据的标准,它和语言无关
//XML
//JSON(更多一点)
第二个需求: 配置文件,之前使用的.properties资源文件中描述的信息不丰富
//XML
//Properties
//yml---SpringBoot
第三个需求: 保存数据,充当小型的数据库
保存数据一般是使用数据库保存,或者使用一般的文件保存,这个时候也可以选择XML文件,因为XML可以描述复杂的数据关系。从普通文件中读取数据的速度肯定是比从数据库中读取数据的速度快,只不过这样不是很安全而已
三、语法
1.文档声明
XML文件的后缀为.xml
XML文本要求文件有一个头部声明: 用来告诉解析器一些相关信息
<?xml version="1.0" encoding="UTF-8"?>
表明当前文件是xml文件,XML版本为1.0,文件内容使用的字符编码为UTF-8
注意:要小心在系统中这个xml文件保存时候的编码,是否和文件内容中设置的编码一致
ansi (American National Standards Institute)美国国家标准协会
ansi编码 是这个协会组织制定的一种字符编码
ansi编码在不同国家表示是不用的 中文操作系统中的ansi编码是GB2312
2.元素
2.1
每个XML文档必须有且只有一个根元素。root
根元素是一个完全包括文档中其他所有元素的元素。
根元素的起始标记要放在所有其他元素的起始标记之前。
根元素的结束标记要放在所有其他元素的结束标记之后。
2.2
xml文件中的标记也可以叫标签、元素、节点。
XML元素指XML文件中出现的标签,一个标签分为开始标签和结束标签,一个标签有如下几种书写形式,例如:
包含标签体:<a>www.baidu.com</a>
不含标签体的:<a></a>, 可以简写为:<a/>
一个标签中也可以嵌套若干子标签。但所有标签必须合理的嵌套,绝对不允许交叉嵌套 ,例如:
<a>你好!<b>程序员</a></b>
这样嵌套是可以的
<a>你好!<b>程序员</b></a>
2.3
对于XML标签中出现的所有空格和换行,XML解析程序都会当作标签内容进行处理。例如:下面两段内容的意义是不一样的。
<name>tom</name>
<name>
tom
</name>
由于在XML中,空格和换行都作为原始内容被处理,所以,在编写XML文件时,要特别注意。但是在一些封装好的解析方式中,是可以忽略掉这些空格和换行的.(例如在一些第三方提供的jar包中)
2.4
一个XML元素可以包含字母、数字以及其它一些可见字符,但必须遵守下面的一些规范
区分大小写,例如,<P>和<p>是两个不同的标记。
不能以数字或"_" (下划线)开头。
不能包含空格。
3.属性
<student id="100">
<name>TOM</name>
</student>
属性值用双引号(")或单引号(')分隔
一个元素可以有多个属性,它的基本格式为:
<元素名 属性名="属性值">
特定的属性名称在同一个元素标记中只能出现一次
属性值不能包括<, >, &
4.实体 entity
xml文件中有些特殊的字符是不能直接表示出来的,例如:大于号,小于号,单引号、双引号等等
使用实体的格式: &实体名字;
预定义字符实体,由XML规范预先定义好了
< <
> >
& &
" "
' '
自定义实体 ENTITY entity
格式:
<!DOCTYPE 根元素名称[
<!ENTITY 实体名 实体内容>
]>
eg:
<!DOCTYPE courses[
<!ENTITY company "昆山杰普软件科技有限公司">
]>
其中:company为实体名称
"昆山杰普软件科技有限公司"是实体内容
实体的使用:&company;
4.注释
<!--这是一个注释-->
注释内容中不要出现- -;
不要把注释放在标记中间;
<Name <!--the name--> > TOM </Name>
注释不能嵌套;
可以在除标记以外的任何地方放注释
5.PCDATA,CDATA
PCDATA (Parsed Character Data) 会被xml文档解析器解析的,但是有些特殊字符需要借助实体才可以被解析器解析。XML文件中的正常内容基本都是PCDATA
CDATA (Character Data) 不会被xml文档解析器解析的,按字符串原样输出。有些内容不想让解析,按照内容原样输出就可以了,这种情况可以使用CDATA
格式:<![CDATA[需要原样输出的字符串]]>
<![CDATA[.....]]>
<>
<!>
<![]>
<![CDATA]>
<![CDATA[]]>
<![CDATA[......]]>
XML+XML约束 ~= html
四 、XML约束
DTD的目的:
验证该xml文档是否是有效的xml文档
如果一个良构的xml文档满足了DTD的声明就是一个有效的xml文档。
注意:良构 不一定 有效,但是有效一定良构
DTD对xml文件中元素的约束:
格式:<!ELEMENT 元素名 (内容模式)>
内容模式:
1).EMPTY:元素不能包含子元素和文本(空元素)
例如:
dtd文件:
<!ELEMENT students (stu)>
<!ELEMENT stu EMPTY>
xml文件:
<students>
<!--这个stu元素中的内容必须为空-->
<stu></stu>
</students>
2).(#PCDATA):可以包含任何字符数据,但是不能在其中包含任何子元素
例如:
dtd文件:
<!ELEMENT students (stu)>
<!ELEMENT stu (#PCDATA)>
xml文件:
<students>
<stu>tom</stu>
</students>
3).ANY:元素内容为任意的,主要是使用在元素内容不确定的情况下
例如:
dtd文件:
<!ELEMENT students (stu)>
<!ELEMENT stu ANY>
xml文件:
<students>
<stu>tom</stu>
</students>
或者
<students>
<stu>
<name>tom</name>
</stu>
</students>
4).修饰符:() | + * ? , 默认修饰符
() 来给元素分用组
| 在列出的元素中选择一个
例如:
dtd文件:
<!ELEMENT students (stu|student)>
xml文件:
<students>
<!--这里只能出现stu元素或者student元素-->
<!--俩个元素任选其一,不能同时出现-->
</students>
+ 该元素最少出现一次,可以出现多次 (1或n次)
例如:
dtd文件:
<!ELEMENT students (stu+)>
xml文件:
<students>
<stu></stu>
<stu></stu>
<stu></stu>
</students>
* 该元素允许出现零次到任意多次(0到n次)
例如:
dtd文件:
<!ELEMENT students (stu*)>
xml文件:
<students>
<!--stu出现0次到n次-->
<stu></stu>
<stu></stu>
<stu></stu>
</students>
? 该元素可以出现,但只能出现一次 (0到1次)
例如:
dtd文件:
<!ELEMENT students (stu?)>
xml文件:
<students>
<!--stu出现0次到1次-->
<stu></stu>
</students>
, 对象必须按指定的顺序出现
例如:
dtd文件:
<!ELEMENT students (stu*)>
<!ELEMENT stu (id,name,age)>
xml文件:
<students>
<stu>
<id></id>
<name></name>
<age></age>
</stu>
</students>
默认修饰符 就是什么修饰符都没有加
例如:
dtd文件:
<!ELEMENT students (stu)>
xml文件:
<students>
<!--这里只能出现stu元素1次-->
<!--stu元素不出现也验证不通过-->
<stu></stu>
</students>
5).混合元素 子元素是任意类型 出现任意次数 并且没有出现顺序要求
例如:
dtd文件:
<!ELEMENT students (stu*)>
<!ELEMENT stu (#PCDATA|id|name|age)*>
xml文件:
<students>
<stu></stu>
<stu>
<id></id>
<name></name>
<age></age>
</stu>
<stu>tom</stu>
</students>
注意:
1 根元素students里面可以出现stu子元素0到n次
2 stu元素中可以写文本也可以写id、name、age子元素
3 id、name、age子元素出现的顺序没有要求
4 id、name、age子元素可以都出现也可以都不出现
注意:浏览器是非验证的解析器,不会验证xml的有效性
可以使用Eclipse去验证xml的有效性
DTD对xml文件中属性的约束:
格式:<!ATTLIST 元素名称
属性名称 值类型 属性特点
属性名称 值类型 属性特点
>
属性类型:
1).CDATA:属性值可以是任何字符(包括数字和中文)
例如:
dtd文件:
<!ELEMENT students (stu*)>
<!ELEMENT stu (#PCDATA)>
<!ATTLIST stu
id CDATA #REQUIRED
name CDATA #REQUIRED
>
xml文件:
<students>
<stu id="1" name="tom"></stu>
</students>
2).ID:属性值必须唯一,属性值必须满足xml命名规则
例如:
dtd文件:
<!ELEMENT students (stu*)>
<!ELEMENT stu (#PCDATA)>
<!ATTLIST stu
id ID #REQUIRED
name CDATA #REQUIRED
>
xml文件:
<students>
<stu id="A1" name="tom"></stu>
<stu id="B1" name="tom"></stu>
</students>
注意:
1. id和name属性必须出现
2. id属性的值必须满足xml名字规范,例如不能数字开头
3. id属性的值不能重复
4. 多个属性的出现是没有顺序要求的
3).IDREF/IDREFS
IDREF属性的值指向文档中其它地方声明的ID类型的值。
IDREFS同IDREF,但是可以具有由空格分开的多个引用。
例如:
dtd文件:
<!ELEMENT students (stu*)>
<!ELEMENT stu (#PCDATA)>
<!ATTLIST stu
id ID #REQUIRED
pid IDREFS #IMPLIED
name CDATA #REQUIRED
>
xml文件:
<students>
<stu id="A1" name="tom"></stu>
<stu id="B1" name="tom"></stu>
<stu id="C1" name="tom" pid="A1 B1"></stu>
</students>
注意:
1. id和name属性必须出现
2. pid属性出现可以,不出现也可以
3. id属性的值必须满足xml名字规范,例如不能数字开头
4. id属性的值不能重复
5. pid属性的值必须是引用其他stu元素的id值
6. pid属性的值可以是多个,使用空格隔开
7. 多个属性的出现是没有顺序要求的
4).enumerated:(枚举值1|枚举值2|枚举值3...),属性值必须在枚举值中
例如:
dtd文件:
<!ELEMENT students (stu*)>
<!ELEMENT stu (#PCDATA)>
<!ATTLIST stu
id ID #REQUIRED
name CDATA #REQUIRED
gender (男|女) #REQUIRED
>
xml文件:
<students>
<stu id="A1" name="tom" gender="男"></stu>
<stu id="B1" name="tom" gender="女"></stu>
</students>
注意:
1. id/name/gender属性必须出现
2. id属性的值必须满足xml名字规范,例如不能数字开头
3. id属性的值不能重复
4. gender属性的值必须是男或者女
5. 多个属性的出现是没有顺序要求的
属性特点:
1).#REQUIRED:元素的所有实例都必须有该属性
例如:
dtd文件:
<!ELEMENT students (stu*)>
<!ELEMENT stu (#PCDATA)>
<!ATTLIST stu
name CDATA #REQUIRED
>
xml文件:
<students>
<stu name=""></stu>
<stu name="tom"></stu>
</students>
注意:
1. name属性必须出现
2. name属性的值可以为空也可以不为空
2).#IMPLIED :属性可以不出现
例如:
dtd文件:
<!ELEMENT students (stu*)>
<!ELEMENT stu (#PCDATA)>
<!ATTLIST stu
name CDATA #IMPLIED
>
xml文件:
<students>
<stu name=""></stu>
<stu name="tom"></stu>
<stu></stu>
</students>
注意:
1. name属性可以出现也可以不出现
2. name属性的值可以为空也可以不为空
3).default-value:属性可以不出现,并且当它不出现的时候是有默认值的,而该属性的默认值就是attribute-value
例如:
dtd文件:
<!ELEMENT students (stu*)>
<!ELEMENT stu (#PCDATA)>
<!ATTLIST stu
name CDATA "tom"
>
xml文件:
<students>
<stu name="zhangsan"></stu>
<stu></stu>
</students>
注意:
1. name属性可以出现也可以不出现
2. name属性如果不出现则默认值为tom
4).#FIXED :属性可以不出现,但是如果出现的话必须是指定的属性值
例如:
dtd文件:
<!ELEMENT students (stu*)>
<!ELEMENT stu (#PCDATA)>
<!ATTLIST stu
name CDATA #IMPLIED
school CDATA #FIXED "briup"
>
xml文件:
<students>
<stu school="briup"></stu>
<stu></stu>
</students>
注意:
1. name/school属性可以出现也可以不出现
2. school属性如果出现那么值一定要是briup
DTD文档的一个实例:
dtd文档:
<!ELEMENT students (student+)>
<!ELEMENT student (name,age?,score*)>
<!ATTLIST student id CDATA #REQUIRED>
<!ELEMENT name (#PCDATA)>
<!ATTLIST name firstName CDATA #IMPLIED>
<!ELEMENT age (#PCDATA)>
<!ATTLIST age xuAge CDATA #FIXED "20">
<!ELEMENT score (#PCDATA)>
<!ATTLIST score sel (60|80|100) #REQUIRED>
五、XML的解析
(一)SAX解析
SAX:基于事件处理的机制
sax解析xml文件时,遇到开始标签,结束标签,开始解析文件,文件解析结束,字符内容,空白字符等都会触发各自的方法。
优点:
适合解析大文件,对内存要求不高
轻量级的解析数据方式,效率更高
缺点:
不能随机解析
不能修改XML文件,只能进行查询
(二)DOM解析:
采用dom解析,会将xml文档全部载入到内存当中,然后将xml文档
中的所有内容转换为tree上的节点(对象)。
优点:
可以随机解析
可以修改文件
可以创建xml文件
缺点:
适合解析小文件,对内存要求高
Dom4j是一个简单、灵活的开放源代码的库。Dom4j是由早期开发JDOM的人分离出来而后独立开发的。与JDOM不同的是,dom4j使用接口和抽象基类,虽然Dom4j的API相对要复杂一些,但它提供了比JDOM更好的灵活性。
Dom4j是一个非常优秀的Java XML API,具有性能优异、功能强大和极易使用的特点。现在很多软件采用的Dom4j,例如Hibernate,包括sun公司自己的JAXP也用了Dom4j。
使用Dom4j开发,需下载dom4j相应的jar文件。
DOM4j中,获得Document对象的方式有三种:
开发dom4j要加入新jar包,并且在倒包时要导入dom4j的包
1.读取XML文件,获得document对象
SAXReader reader = new SAXReader();
Document document = reader.read(new File(“src/input.xml"));
2.解析XML形式的文本,得到document对象
String text = "<members></members>";
Document document = DocumentHelper.parseText(text);
3.主动创建document对象.
Document document = DocumentHelper.createDocument();
//创建根节点
Element root = document.addElement("members");
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWriter xw=new XMLWriter(new FileOutputStream(“file”), format);