概述
配置文件是用来保存程序在运行时需要的一些参数
常见的配置文件:txt、properties、xml
三种配置文件的优缺点:
txt:
优点:没有优点
缺点:不利于阅读
properties:
优点:键值对形式易于阅读、解析简单
缺点:无法配置一组一组的数据(例如有多个用户时,一个键就会对应多个值)
XML:
优点:易于阅读、可以配置成组出现的数据
缺点:解析比较复杂
配置文件的选择:数据量较少,一个键只对应一个值,使用properties;数据量较多,使用xml
XML的全称为EXtensible Markup Language,是一种可扩展的标记语言
标记语言:通过标签来描述数据的一门语言(标签有时我们也将其称之为元素)
可扩展:标签的名字是可以自己定义的
XML作用:
① 用于进行存储数据和传输数据
② 作为软件的配置文件
语法规则:
① XML文件的后缀名为:xml
② 文档声明必须是第一行
<?xml version="1.0" encoding="UTF-8" ?>
version:XML默认的版本号码、该属性是必须存在的
encoding:本XML文件的编码
标签(元素)规则:
① 标签由一对尖括号和合法标识符组成:<name></name>
,必须存在一个根标签,有且只能有一个
② 标签必须成对出现,有开始,有结束:<name></name>
③ 特殊的标签可以不成对,但是必须有结束标记,如:<br/>
④ 标签中可以定义属性,属性和标签名空格隔开,属性值必须用引号引起来<student id = "1"></student>
⑤ 标签需要正确的嵌套
其他组成:
① XML文件中可以定义注释信息:<!-- 注释内容 -->
② XML文件中可以存在以下特殊字符:
<
:< 小于
>
:> 大于
&
: & 和号
'
:’ 单引号
"
:" 引号
③ XML文件中可以存在CDATA区:<![CDATA[...内容...]]>
,CDATA区里的内容会被当做普通的文本来进行解析
示例:
<?xml version="1.0" encoding="UTF-8" ?>
<students>
<student id="1">
<name><![CDATA[ <<<>>>> ]]></name>
</student>
</students>
文档约束
问题:由于XML文件可以自定义标签,导致XML文件可以随意定义,程序在解析的时候可能出现问题
文档约束:是用来限定xml文件中的标签以及属性应该怎么写。以此强调约束程序员必须按照文档约束的规定来编写xml文件
文档约束的分类:
① DTD
② schema
这两个文档约束了解就行,因为这个文档一般是软件或者别人已经写好的,我们只需要会按照对应的要求写XML文件就行
1.DTD
DTD的使用:
需求:利用DTD文档约束,约束一个XML文件的编写
分析:
① 编写DTD约束文档,后缀必须是**.dtd**
<!ELEMENT 书架 (书+)>
<!ELEMENT 书 (书名,作者,售价)>
<!ELEMENT 书名 (#PCDATA)>
<!ELEMENT 作者 (#PCDATA)>
<!ELEMENT 售价 (#PCDATA)>
第一行表示根标签(书+表示根标签下的字标签为“书”,且有一个或多个这样的字标签);第二行定义了书这个标签的内容,即有三个子标签(书名、作者、售价);最后三行定义了剩下的三个子标签,表明这三个标签下没有子标签了,但是里面内容是PCDATA(文本数据)
② 在需要编写的XML文件中导入该DTD约束文档
③ 按照约束的规定编写XML文件的内容
DTD引入的三种方式:
① 引入本地dtd(掌握):<!DOCTYPE 根元素名称 SYSTEM 'DTD文件的路径'>
② 在xml文件内部引入(了解):<!DOCTYPE 根元素名称[dtd文件内容]>
③ 引入网络dtd(了解):<!DOCTYPE 根元素的名称 PUBLIC "DTD文件名称" "DTD文档的URL">
示例:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE 书架 SYSTEM 'book.dtd'>
<书架>
<书>
<书名>Java从入门到起飞</书名>
<作者>高斯林</作者>
<售价>300.78</售价>
</书>
<书>
<书名>别吃别吃</书名>
<作者>thehsy</作者>
<售价>2000</售价>
</书>
</书架>
DTD的作用:可以约束XML文件的编写
DTD的问题:不能约束具体的数据类型
2.schema
schema可以约束具体的数据类型,约束能力上更强大
schema本身也是一个xml文件,本身也受到其他约束文件的要求,所以编写的更加严谨
schema的使用:
需求:利用schema文档约束,约束一个XML文件的编写
分析:
① 编写schema约束文档,后缀必须是**.xsd**
② 在需要编写的XML文件中导入该schema约束文档
③ 按照约束内容编写XML文件的标签
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.itcast.cn/"
elementFormDefault="qualified">
<xs:element name="书架">
<xs:complexType>
<xs:sequence maxOccurs="unbounded">
<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>
第二行表示当前schema文件被谁约束;第三行表示如果别人想要让这个schema文件去约束xml,那么这个xml文件必须要使用到这个地址,这个地址可以理解是一个名字
element表示一个标签,而最外面的element就是根标签;complexType表示当前的标签是一个复杂的标签,即含有其他标签;sequence表示该标签里的内容是有顺序的,必须按照这个顺序来编写;maxOccurs表示最大出现次数,而unbounded表示无上限
最简单的引用方式:直接使用刚才的地址
<?xml version="1.0" encoding="UTF-8" ?>
<书架 xmlns="http://www.itcast.cn/">
<书>
<书名>别吃别吃</书名>
<作者>theshy</作者>
<售价>2800</售价>
</书>
</书架>
解析
XML解析就是使用程序读取XML中的数据
两种解析方式:
① SAX解析
② DOM解析
SAX和DOM的优缺点:
① SAX:不会把整体的xml文件都加载到内存,而是从上往下逐行进行扫描(目前不常用)
缺点:只能读取,不能添加,不能删除
优点:因为它是逐行扫描不需要把整体的xml文件都加载到内存,所以它可以解析比较大的xml文件
② DOM:会把整体的xml文件都加载到内存
会把这个整体在内存中形成一个树形结构,我们可以通过这个树形结构去解析xml文件
优点:可以读取,可以添加,可以删除,可以做任何事情
缺点:需要xml文件全部加载到内存,所以不能解析非常大的xml文件(但是目前的内存都很大,所以不需要考虑这个问题)
Dom常见的解析工具:
名称 | 说明 |
---|---|
JAXP | SUN公司提供的一套XML的解析的API |
JDOM | JDOM是一个开源项目,它基于树形结构,利用纯JAVA的技术对XML文档实现解析、生成、序列化以及多种操作 |
Dom4j | 是JDOM的升级品,用来读写XML文件。具有性能优异、功能强大和极其易使用的特点,它的性能超过sun公司官方的dom技术,同时它也是一个开放源代码的软件,Hibernate也用它来读写配置文件 |
jsoup | 功能强大DOM方式的XML解析开发包,尤其对HTML解析更加方便 |
DOM解析文档对象模型:
<?xml version="1.0" encoding="UTF-8" ?>
<students>
<!--第一个学生信息-->
<student id="1">
<name>张三</name>
<age>23</age>
</student>
<!--第二个学生信息-->
<student id="2">
<name>李四</name>
<age>24</age>
</student>
</students>
Document对象:整个xml文档
Element对象:标签
Attribute对象:属性
Text对象:文本内容
其中Element、Attribute和Text的共同父类是Node对象
案例:使用Dom4j解析出XML文件
需求:使用Dom4j把一个XML文件的数据进行解析
分析:
① 下载Dom4j框架,官网下载
② 在项目中创建一个文件夹:lib
③ 将对应jar包复制到lib文件夹
④ 将这一jar包添加为库
④ 在类中导包使用
得到Document对象:
SAXReader类:
构造器 / 方法 | 说明 |
---|---|
public SAXReader() | 创建Dom4j的解析器对象 |
Document read(File file) | 加载XML文件成为Document对象 |
Document类:
方法名 | 说明 |
---|---|
Element getRootElement() | 获取根元素对象 |
Dom4j解析XML的元素、属性、文本:
方法名 | 说明 |
---|---|
List<Element> elements() | 得到当前元素下所有子元素 |
List<Element> elements(String name) | 得到当前元素下指定名字的子元素返回集合 |
Element element(String name) | 得到当前元素下指定名字的子元素,如果有很多名字相同的返回第一个 |
String getName() | 得到元素名字 |
String attributeValue(String name) | 通过属性名直接得到属性值 |
String elementText(子元素名) | 得到指定名称的子元素的文本 |
String getText() | 得到文本 |
案例代码:
public static void main(String[] args) throws InterruptedException, DocumentException {
//1.创建解析器对象
SAXReader saxReader = new SAXReader();
//2.利用解析器去读取xml文件,并返回文档对象
File file = new File("src\\p2\\a.xml");
Document document = saxReader.read(file);
//3.自己解析的时候,一定要一层一层地解析
Element rootElement = document.getRootElement();
//4.获取根标签的子标签
List<Element> elements = rootElement.elements();
for (Element element : elements) {
//5.继续获取里面的内容
//属性id
Attribute id = element.attribute("id");
String idValue = id.getText();
//标签name
Element name = element.element("name");
String nameValue = name.getText();
//标签age
Element age = element.element("age");
String ageValue = age.getText();
System.out.println(idValue + ", " + nameValue + ", " + ageValue);
}
}
检索
XPath在解析XML文档方面提供了独树一帜的路径思想,更加优雅、高效
XPath使用路径表达式来定位XML文档中的元素节点或属性节点
示例:
① / 元素 / 子元素 / 孙元素
② // 子元素 // 孙元素
案例:使用Xpath检索出XML文件
需求:使用Dom4j把一个XML文件的数据进行解析
分析:
① 导入jar包(dom4j和jaxen),Xpath技术依赖Dom4j技术
② 通过dom4j的SAXReader获取Document对象
③ 利用XPath提供的API,结合XPath的语法完成选取XML文档元素节点进行解析操作
④ Document中与XPath相关的API如下:
方法名 | 说明 |
---|---|
Node selectSingleNode("表达式") | 获取符合表达式的唯一元素 |
List<Node> selectNodes("表达式") | 获取符合表达式的元素集合 |
注意:对于selectSingleNode这个方法来说,如果目标对象有多个,则选取第一个
Xpath的四大检索方案:
① 绝对路径
② 相对路径
③ 全文检索
④ 属性查找
1.绝对路径
采用绝对路径获取从根节点开始逐层的查找 /contactList/contact/name 节点列表并打印信息
方法名 | 说明 |
---|---|
/ 根元素 / 子元素 / 孙元素 | 从根元素开始,一级一级向下查找,不能跨级 |
示例:
public static void main(String[] args) throws InterruptedException, DocumentException {
//1.创建解析器对象
SAXReader saxReader = new SAXReader();
//2.利用解析器去读取本地的xml文件,并返回文档对象
Document document = saxReader.read(new File("src\\p2\\a.xml"));
//然后就可以利用xpath方式来进行快速检索
List<Node> list = document.selectNodes("/students/student/name");
for (Node node : list) {
System.out.println(node.getText());
}
Node node = document.selectSingleNode("/students/student/name");
System.out.println(node.getText());
}
2.相对路径
先得到根结点contactList,再采用相对路径获取下一级contact节点的name子节点并打印信息
方法名 | 说明 |
---|---|
./ 子元素 / 孙元素 | 从当前元素开始,一级一级向下查找,不能跨级 |
示例:
public static void main(String[] args) throws InterruptedException, DocumentException {
//1.创建解析器对象
SAXReader saxReader = new SAXReader();
//2.利用解析器去读取本地的xml文件,并返回文档对象
Document document = saxReader.read(new File("src\\p2\\a.xml"));
//然后就可以利用xpath方式来进行快速检索
Element rootElement = document.getRootElement();
//相对于自己去往下查找
Element element = (Element) rootElement.selectSingleNode("./student/age");
System.out.println(element.getName());
System.out.println(element.getText());
}
3.全文检索
直接全文搜索所有的name元素并打印
方法名 | 说明 |
---|---|
// contact | 找contact元素,无论元素在哪里 |
// contact / name | 找contact,无论在哪一级,但name一定是contact的子节点 |
// contact // name | contact无论在哪一级,name只要是contact的子孙元素都可以找到 |
public static void main(String[] args) throws InterruptedException, DocumentException {
//1.创建解析器对象
SAXReader saxReader = new SAXReader();
//2.利用解析器去读取本地的xml文件,并返回文档对象
Document document = saxReader.read(new File("src\\p2\\a.xml"));
//全文检索
List<Node> list1 = document.selectNodes("//name");
for (Node node : list1) {
System.out.println(node.getText());
}
List<Node> list2 = document.selectNodes("//student/name");
for (Node node : list2) {
System.out.println(node.getText());
}
List<Node> list3 = document.selectNodes("//student//name");
for (Node node : list3) {
System.out.println(node.getText());
}
}
4.属性查找
在全文中搜索属性,或者带属性的元素
方法名 | 说明 |
---|---|
//@属性名 | 查找属性对象,无论是哪个元素,只要有这个属性即可 |
//元素[@属性名] | 查找元素对象,全文搜索指定元素名和属性名 |
//元素[@属性名=‘值’] | 查找元素对象,全文搜索指定元素名和属性名,并且属性值相等 |
public static void main(String[] args) throws InterruptedException, DocumentException {
//1.创建解析器对象
SAXReader saxReader = new SAXReader();
//2.利用解析器去读取本地的xml文件,并返回文档对象
Document document = saxReader.read(new File("src\\p2\\a.xml"));
//查找属性和带属性查找
//查属性
List<Node> list1 = document.selectNodes("//@id");
for (Node node : list1) {
System.out.println(node.getText());
}
//查的是带有指定属性的标签
List<Node> list2 = document.selectNodes("//student[@id]");
for (Node node : list2) {
System.out.println(node.getName());
}
//查的是带有指定属性值的标签
List<Node> list3 = document.selectNodes("//student[@id='1']");
for (Node node : list3) {
System.out.println(node.getName());
}
}