1,XML
==简单介绍XML:==
- 为了灵活实现不同路径,执行不同的资源,我们需要使用XML进行配置。
- 为了限制XML的内容,我们需要使用XML约束(DTD或schema)。
- 为了获取XML的内容,我们进行dom4j进行解析。
- xml也可以传输数据,但现在主要是做配置文件,传输数据使用json。
1.1 XML概述
XML是可扩展标记语言(EXtensible Markup Language)的缩写,它是一种数据表示格式,可以描述非常复杂的数据结构,常用于传输和存储数据。xml在语法上与html比较相似,但html的标签都是固定的,xml中的标签是可以由用户自定义的。
特定
- 纯文本,默认使用UTF-8编码
- 可嵌套
- 如果把XML内容存为文件,那么它就是一个XML文件
使用场景
- XML内容经常被当成消息进行网络传输
- 作为配置文件用于存储系统的信息
1.2 XML的创建、语法规则
就是创建一个XML类型的文件(File),要求文件的后缀必须使用xml。
语法规则
- XML文件的后缀名为:xml
- 文档声明必须是第一行
<?xml version="1.0" encoding="UTF-8" standalone="yes/no"?>
文档的声明必须以<?xml开始,以?>结束,必须从文档的0行0列开始,
version是xml的版本,
encoding是xml的编码格式(可选的,默认就是UTF-8),
standalone,表示这个xml文档是否依赖其他文件。
XML的标签规则
- 标签由一对尖括号和合法标识符组成: ,必须存在一个根标签,有且只能有一个。
- 标签必须成对出现,有开始,有结束:
- 特殊的标签可以不成对,但是必须有结束标记,如:<br/>
- 标签中可以定义属性,属性和标签名空格隔开,属性值必须用引号引起来
- 标签需要正确的嵌套,标签之间不能交叉
注释
<!- 注释内容 -->
特殊字符
< < 小于
> > 大于
& & 和号
' ' 单引号
" " 引号
如果想直接写特殊字符,不想转义,需要先写一个字符数据区<![CDATA[ 内容 ]]>
在字符数据区里面的特殊符号不在有任何含义,可以直接使用。
1.3 XML文档约束
由于XML文件可以自定义标签,导致XML文件可以随意定义,程序在解析的时候可能出现问题。于是出现了文档约束。
==文档约束:是用来限定xml文件中的标签以及属性应该怎么写。以此强制约束程序员必须按照文档约束的规定来编写xml文件。==
文档约束的分类
- DTD
- schema
DTD约束
DTD(Document Type Definition)文档类型定义,用来约束xml
文档。规定xml
文档中元素的名称,子元素的名称及顺序,元素的属性等等。
文档声明
内部DTD,在
xml
文档内部嵌入DTD,只对当前xml
有效。<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <!DOCTYPE web-app[ <!-- ......具体语法 --> ]> <web-app> </web-app>
外部DTD(本地DTD),DTD在本地文件系统,内部自己项目使用。
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE web-app SYSTEM "web-app_...."> <!-- SYSTEM "DTD约束文件所在路径"--> <web-app> </web-app>
外部DTD(网络)
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE web-app PUBLIC "dtd的名称" "dtd文件的路径"> <web-app> </web-app>
我们选择使用外部DTD。创建外部DTD的步骤如下:
- 创建一个以.dtd为文件后缀名的文件。
看xml中有多少元素,有多少元素就 写几个
<!ELEMENT>
- 判断元素是简单元素还是复杂元素。
- 简单元素:没有子元素的元素。<!ELEMENT 元素名称 (#PCDATA)>
复杂元素:拥有子元素的元素。<!ELEMENT 元素名称 (子元素)>
<!ELEMENT students (student+)> <!ELEMENT student (name,age,sex)> <!ELEMENT name (#PCDATA)> <!ELEMENT age (#PCDATA)> <!ELEMENT sex (#PCDATA)>
关于使用dtd定义元素
复杂元素
表示子元素可以出现的次数:
- +:表示只能出现一次或者多次
- ?:表示零次或者一次
- *:表示出现任意次
- 子元素列表以逗号隔开,表示出现的顺序
子元素用|隔开,表示只能出现一个
<!ELEMENT person (name+,age?,sex*)> <!ELEMENT person (name,age,sex)> <!ELEMENT sex (man|woman)>
简单元素
<!ELEMENT name (#PCDATA)> <!--//(#PCDATA)表示name是字符串类型--> <!ELEMENT age EMPTY> <!--//EMPTY表示age约束为空,不能有值--> <!ELEMENT sex ANY> <!--//ANY表示任意,可有值,可无值-->
关于使用dtd定义属性
属性类型
- CDATA:字符串类型
- (XX|XX|XX):枚举类型,只能在一定的范围内出现值,而且值只能出现一次
- ID:只能以字母或下划线开头
约束类型
REQUIRED:属性必须存在
IMPLIED:属性可有可无
FIXED:表示一个固定值
FIXED "人类"-----此属性必须为人类
- "男" --------------此属性不写默认为男
<!ATTLIST 元素名称 属性名称 属性类型 约束条件 属性名称 属性类型 约束条件 属性名称 属性类型 约束条件 > <!ATTLIST student name CDATA #REQUIRED age ID #IMPLIED sex (男|女) "男" galaxy CDATA #FIXED "地球" > <person> <student name="张三" age="ten" galaxy="地球"></student> <!-- name: 字符串类型 是必须出现的 age: ID类型 age属性可有可无 sex: 枚举类型 默认值是男 galaxy: 字符串类型 固定值就是"地球" --> </person>
关于使用dtd定义实体
- 语法:<!ENTITY 实体名称 "实体内容">
- 应用方法:&实体名称;
- 类似取别名
<!ENTITY text "hello world"> <person> <student>&text;</student> </person> 运行效果就是 <person> <student>hello world</student> </person>
schema约束
schema约束介绍:用于定义和描述xml文档结构与内容的模式语言,其出现是为了克服DTD的局限性
Schema与DTD相比:
- schema符合xml语法结构, dtd语法:<!ELEMENT 元素名称 约束条件>
- schema对名称空间支持得非常好,一个xml可以有多个schema,多个schema使用名称空间区分(类似于Java中的包名)
- schema比DTD支持更多的数据类型、并支持用户自定义新的数据类型
- schema定义约束的能力非常强大,可以对xml实例文档作出细致的语义限制
- schema不能像DTD一样定义实体,比DTD更复杂,但schema现在已是w3c组织的标准,它正逐步取代DTD
步骤
- 创建一个schema文件,文件的后缀名是.xsd,必须有一个根节点,根节点是
xsd文件的头部书写
-
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/1" elementFormDefault="qualified"> </schema>
xml被约束文件的引入
-
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.example.org/1" xsi:schemaLocation="http://www.example.org/1 person.xsd" id="123"> </person>
标签
- schema 三个属性 xmlns、targetNamespace、elementFormDefault
- 表示根标签,有几个根标签,就有几个
- 看下层如果还有子元素,就写,:表示是一个复杂类型
在下一层先写出子元素的性质
子元素
maxOccurs="unbounded"
:表示该元素可以出现多次maxOccurs
:表示该元素可以出现几次
-
<?xml version="1.0" encoding="UTF-8"?>
<!-- xmlns="http://www.w3.org/2001/XMLSchema"这个就表示这个文件是一个约束文档,与被约束文档加以区分 -->
<!-- targetNamespace="url路径"表示可以通过targetNamespace中的url路径(路径可以随便写)引入这个schema文件 -->
<!-- elementFormDefault="qualified":表示质量良好的 -->
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/1"
elementFormDefault="qualified">
<!-- 1、看被约束文件有几个元素,有几个元素写几个element -->
<!-- 2、区分是简单元素还是复杂元素 -->
<!-- person是一个复杂元素 -->
<element name="person">
<!-- <complexType>:表示一个复杂类型 -->
<complexType>
<!-- sequence:表示有序的 -->
<sequence>
<!-- 这里面放子元素
maxOccurs="unbounded":表示该元素可以出现多次, maxOccurs:表示该元素可以出现几次 -->
<element name="name" type="string" maxOccurs="unbounded"></element>
<element name="age" type="int"></element>
</sequence>
<!--all:表示里面定义的元素只能出现一次 -->
<!-- <all>
<element name="name" type="string"></element>
<element name="age" type="int"></element>
</all> -->
<!-- choice:元素只能出现其中一个 -->
<!-- <choice>
<element name="name" type="string"></element>
<element name="age" type="int"></element>
</choice> -->
<!-- 约束属性:name:属性的名称 type:属性的数据类性 use="required":表示必须出现 -->
<attribute name="id" type="string" use="required"></attribute>
</complexType>
</element>
</schema>
xml文件的引入
<?xml version="1.0" encoding="UTF-8"?>
<!-- 引入约束person.xsd文件 -->
<!-- xmlns="http://www.w3.org/2001/XMLSchema-instance":表示这是一个被约束的文件 -->
<!-- xmlns="http://www.example.org/1":表示引入targetNamespace中的url路径的方式,引入约束文件 -->
<!-- 由于表示被约束文件与约束文件的xmlns会发生冲突,所以要给表示被约束文件的xmlns去一个别名xmlns:xsi -->
<!-- xsi:schemaLocation="{namespace} {location}":{namespace}是targetNamespace中的url路径,{location}是约束文件的路径和名称 -->
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.example.org/1"
xsi:schemaLocation="http://www.example.org/1 person.xsd" id="123">
<name>zhangsan</name>
<age>18</age>
</person>
2,XML解析技术
关于xml的解析
==xml的解析方法:dom和sax==
dom解析分析:跟据xml的层次结构,在内存中分配一个树形结构,把xml中的标签、属性和文本都封装成对象。
- 优点:对于增删改操作很方便。
- 缺点:如果xml文件过大,会造成文件的溢出。
sax解析分析:采用事件驱动,边读边解析,从上到下,一行一行的解析,解析到某个对象,把对象名称返回。
- 优点:不会造成内存溢出,实现查询
- 缺点:不能实现增删改操作
Dom4j解析xml文件
dom4j介绍:
- dom4j是一个组织,针对于xml文档解析,提供dom4j解析器
- dom4j并不是JavaSE的一部分,所以使用它需要倒入对应的jar包
导包
- 下载dom4j框架,官网下载。
- 在项目中创建一个文件夹:lib
- 将dom4j-2.1.1.jar文件复制到 lib 文件夹
- 在jar文件上点右键,选择 Add as Library -> 点击OK
- 在类中导包使用
得到Document文档对象和根元素对象
创建一个Dom4j的解析器对象,代表整个dom4j的框架
- SEXReader reader = new SEXReader();
把XML文件加载到内存中成为一个Document文档对象
- Document document = reader.read(url);
获取根元素对象
- Element root = document.getRootElement();
元素的方法
返回值 | 方法名 | 说明 |
---|---|---|
List | elements() | 得到当前元素下所有子元素 |
List | elements(String name) | 得到当前元素下指定名字的子元素返回集合 |
Element | element(String name) | 得到当前元素下指定名字的子元素,如果有很多名字相同的返回第一个 |
String | getName() | 得到元素名字 |
String | attributeValue(String name) | 通过属性名直接得到属性值 |
String | elementText(子元素名) | 得到指定名称的子元素的文本 |
String | elementTextTrim(子元素名) | 得到指定名称的子元素的文本(去前后空格) |
String | getText() | 得到文本 |
String | getTextTrim() | 得到文本(去前后空格) |
3,XML检索技术:Xpath
XPath在解析XML文档方面提供了一独树一帜的路径思想,更加优雅,高效
XPath使用路径表达式来定位XML文档中的元素节点或属性节点。
使用Xpath检索出XML文件
- 导入jar包(dom4j和jaxen-1.1.2.jar),Xpath技术依赖Dom4j技术
- 通过dom4j的SAXReader获取Document对象
- 利用XPath提供的API,结合XPath的语法完成选取XML文档元素节点进行解析操作。
Document中与Xpath相关的API如下:
- Node selectSingleNode("表达式") 获取符合表达式的唯一元素
- List selectNodes("表达式") 获取符合表达式的元素集合
Xpath的检索方式
绝对路径
- /根元素/子元素/孙元素
- 从根元素开始,一级一级向下查找,不能跨级
- /AAA/DDD/BBB:表示一层一层的,AAA下面DDD下面的BBB
相对路径
- ./子元素/孙元素
- . /属于是根元素,可以直接冲根元素向下进行查找
全文检索
- /* 表示所有元素
- //contact 找contact元素,无论元素在哪里
- //contact/name 找contact,无论在哪一级,但name一定是contact的子节点
- //contact//name contact无论在哪一种,name只要是contact的子孙元素都可以找到
属性查找
- //@属性名 查找属性对象,无论是哪个元素,只要有这个属性即可。
- //元素[@属性名] 查找元素对象,全文搜索指定元素名和属性名。
- //元素//[@属性名=‘值’] 查找元素对象,全文搜索指定元素名和属性名,并且属性值相等。
- BBB[1]:表示第一个BBB元素 、 BBB[last()]:表示最后一个元素
XML实例
<?xml version="1.0" encoding="UTF-8"?>
<person>
<student id="hhh">
<name>张三</name>
<age>300</age>
</student>
<student>
<name>李四</name>
<age>20</age>
</student>
</person>
java代码
import java.io.Reader;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
public class Dom4j_xpath {
public static void main(String[] args) {
//getNames();
getName();
}
/**
* 获得所有的目标标签
*/
private static void getNames() {
try {
//创建SAX解析器
SAXReader reader = new SAXReader();
//得到document
Document document = reader.read("src/XPATH/Person.xml");
//得到所有的name元素
List<Node> list = document.selectNodes("//name");
//遍历 增强for循环
for (Node name : list) {
//得到name的值
String s = name.getText();
System.out.println(s);
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
private static void getName() {
try{
//创建SAX解析器
SAXReader reader = new SAXReader();
//得到document
Document document = reader.read("src/XPATH/Person.xml");
//得到目标元素
Node name = document.selectSingleNode("//student[@id='hhh']/name");
//得到目标元素中的值
String s = name.getText();
System.out.println(s);
}catch(Exception e){
e.printStackTrace();
}
}
}