1.2 XML的作用XML指可扩展标记语言(EXtensible Markup Language)【它是就一堆自定义的标签!】
XML是一种标记语言(标签),很类似 HTML,HTML文件也是XML文档
XML的设计宗旨是传输数据,而非显示数据(HTML:在浏览器中显示数据)
XML标签没有被预定义。您需要自行定义标签。
XML被设计为具有自我描述性(就是易于阅读)。【配置文件】
XML是 W3C 的推荐标准
W3C在1988年2月发布1.0版本,2004年2月又发布1.1版本,单因为1.1版本不能向下兼容1.0版本,所以1.1没有人用。同时,在2004年2月W3C又发布了1.0版本的第三版。我们要学习的还是1.0版本。
- XML可以存储数据 , 作为数据交换的载体(使用XML格式进行数据的传输)。
- XML也可以作为配置文件,例如后面框架阶段我们学习的Spring框架的配置(applicationContext.xml)都是通过XML进行配置的(企业开发中经常使用的)
xml文件可以充当配置文件,properties文件也可以充当配置文件!
properties配置文件:简单(键值对!),无法描述配置的层级关系!而xml文件可以!
XML不是HTML的替代品!XML和HTML为不同的目的而设计。
- XML被设计为传输和存储数据,其焦点是数据的内容(旨在传输信息)。【标签未被预定义】
- HTML被设计用来显示数据,其焦点是数据的外观(旨在显示信息)。【标签都被预定义好了】
展示xml存储数据功能**
需求:编写xml文档,用于描述人员信息,person代表一个人员,id是人员的属性,代表人员编号。人员信息包括name姓名、age年龄、sex性别信息。
第一步:使用IDEA编写一个person.xml文件
第二步:编写person.xml文件内容
刘乃静 22 男 马继昌 25 女
第三步:查看
3、XML语法 3.1 XML组成部分XML文件中常见的组成元素有:文档声明、元素、属性、注释、转义字符、字符区。
3.2 注释XML的注释以 结束
3.3 文档声明
文档声明:
3.4 元素
- 使用IDE创建xml文件时就带有文档声明.
- 文档声明必须为结束
- 文档声明必须从文档的0行0列位置开始
- 文档声明中常见的两个属性:
- version:指定XML文档版本。必须属性,这里一般选择1.0;
- enconding:指定当前文档的编码,可选属性,默认值是utf-8;
* 开始标签、元素体、结束标签组成。 例如:3.5 属性张三 解释: 开始标签:元素体:张三 【开始标签和结束标签中间夹着的内容】 结束标签: 【元素体也可以包含标签 ===>>>】 * 空元素:空元素只有标签,而没有结束标签,但元素必须自己闭合,例如: jack 【还有一个称呼:自闭标签】 * 格式化良好的XML文档,有且仅有一个根元素 * 命名: ①严格区分大小写 ②不建议使用以下标签 * 文本值:2个标签中间夹着的内容(里面没有字标签)! 刘乃静 22男
属性是为了描述当前元素(标签具有什么!)
刘乃静 22 男
上面的代码中,id就是person元素的属性(代表这个人的编号)
* 属性的注意问题:
① 属性是元素的一部分,它必须出现在元素的开始标签中
这是正确的!
这是错误的!
②属性的定义格式:属性名=“属性值”,其中属性值必须使用单引或双引号括起来
这是正确的!
这是正确的!
③一个元素可以有0~N个属性,但一个元素中不能出现同名属性
这是正确的!
这是正确的!
这是正确的!
这是错误的!
④属性名不能使用空格 , 不要使用冒号等特殊字符,且必须以字母开头
3.6 转义字符
有的时候,需要在标签的文本值位置写上很多描述信息,里面包含了一些特殊的字符,xml是不支持(特殊字符会报错)!
一旦我们在xml文件中书写了很多实体字符,那么需要挨个给他使用转义符来转义,这样很麻烦,可以使用CDATA区一次性解决!
4、XML约束 4.1 dtd约束
DTD是文档类型定义(document Type Definition)。DTD 可以定义在 XML 文档中出现的元素、这些元素出现的次序、它们如何相互嵌套以及XML文档结构的其它详细信息。
4.2 schema约束它是xml约束的一种,功能比dtd约束更强大,数据类型约束更完善!schema约束本身也是xml文档,为了与xml文件以示区别,将其扩展名定义为.xsd。
二、XML解析当将数据存储在XML后,我们就希望通过程序获取XML的内容。如果我们使用Java基础所学的IO知识是可以完成的,不过你学要非常繁琐的操作才可以完成,且开发中会遇到不同问题(只读、读写)。人们为不同问题提供不同的解析方式,使用不同的解析器进行解析,方便开发人员操作XML。
2.1 解析方式处理问题的思路!
1. DOM:要求解析器把整个XML文档装载到内存,并解析成一个document对象 a)优点:元素与元素之间保留结构关系,故可以进行增删改查操作。 b)缺点:XML文档过大,可能出现内存溢出 2. SAX:是一种速度更快,更有效的方法。它逐行扫描文档,一边扫描一边解析。并以事件驱动的方式进行具体解析,每执行一行,都触发对应的事件。(了解) a)优点:处理速度快,可以处理大文件 b)缺点:只能读,逐行后将释放资源,解析操作繁琐。 3. PULL:Android内置的XML解析方式,类似SAX。(了解)
基于DOM解析方式的原理图:
2.2 解析器处理问题的工具
解析器,就是根据不同的解析方式提供具体实现。有的解析器操作过于繁琐,为了方便开发人员,有提供易于操作的解析开发包
* 常见的解析开发包有:
JAXP:sun公司提供支持DOM和SAX开发包
Dom4j:比较简单的的解析开发包(常用) 【★★★★★】 解析xml文件!
JDom:与Dom4j类似
Jsoup:功能强大DOM方式的XML解析开发包,尤其对HTML解析更加方便(项目中讲解)
2.3 DOM4j的基本操作
2.3.1 导入dom4j开发的核心包
dom4j 必须使用核心类SaxReader加载xml文档获得document,通过document对象获得文档的根元素,然后就可以操作了。
2.3.2 dom4j核心API* DOM4j通用的api:
// 获得核心解析器对象
new SAXReader() // 构造器
// 使用SaxReader对象来加载xml文件获得document对象
document read(String url) // 加载执行xml文档
// document对象来获得xml文件的根元素
Element getRootElement() // 获得根元素
* Element对象的相关方法:
List elements([String ele] ) // 获得指定名称的所有子元素。可以不指定名称
Element element([String ele]) // 获得指定名称第一个子元素。可以不指定名称
String getName() // 获得当前元素的元素名
String attributevalue(String attrName) // 获得指定属性名的属性值
String elementText(Sting ele) // 获得指定名称子元素的文本值
String getText() // 获得当前元素的文本内容
2.3.3 dom4j解析books.xml文件
books.xml
斗罗大陆 唐家三少 88 斗破苍穹 乱 68
测试类:
public class BookTest {
public static void main(String[] args) throws documentException {
// 获得核心解析器对象
SAXReader saxReader = new SAXReader();
// 使用核心解析器对象读取xml文件得到document对象
document document = saxReader.read("day15_xml/src/books.xml");
//System.out.println(document); // org.dom4j.tree.Defaultdocument@682a0b20 [document: name day15_xml/src/books.xml]
// 使用document对象获得根元素节点
Element root = document.getRootElement();
//System.out.println(root.getName()); // books
// 获得根元素节点的所有子元素节点
List bookEles = root.elements("book");
// 调用方法,获得books.xml文件所有的数据(属性值,文本值)
//getData(bookEles);
// 获得id值为0002的书名!
getBookName(bookEles,"0002");
}
public static void getBookName(List bookEles,String id) {
// 非空判断
if(!bookEles.isEmpty()){
// 遍历
for (Element bookEle : bookEles) {
// 判断
if(bookEle.attributevalue("id").equals(id)){
System.out.println(bookEle.elementText("name"));
}
}
}
}
public static void getData(List bookEles) {
// 遍历
for (Element bookEle : bookEles) {
// 获得元素的名称
//System.out.println(bookEle.getName()); // book book
// 获得指定属性id的值
//System.out.println(bookEle.attributevalue("id")); // 001 002
// 获得指定元素的文本值
//System.out.println(bookEle.elementText("name"));
// 继续遍历获得book元素节点的子元素节点
List eles = bookEle.elements();
for (Element ele : eles) {
// 获得当前元素节点的文本值
System.out.println(ele.getName()+":"+ele.getText());
}
}
}
}
2.4 Dom4j结合Xpath解析xml文件
XPath 使用路径表达式来选取XML 文档中的元素节点或属性节点。节点是通过沿着路径 (path) 来选取的。XPath在解析HTML文档方面提供了一独树一帜的路径思想。
// document对象的核心方法:
List selectNodes("表达式") //获取符合表达式的元素集合
Element selectSingleNode("表达式") // 获取符合表达式的唯一元素
关键点:表达式的路径如何写呢? ===>>>通过查阅API文档学习!
/AAA =====>>> 获得根元素AAA /AAA/CCC =====>>> 获得根元素下面的所有CCC //BBB =====>>> 获得所有的BBB元素 /AAA/BBB[1] =====>>>> 获得根元素下面的第一个BBB元素 //BBB[@id='b1'] =====>>>> 获得有id属性并且值为b1的BBB元素! 【开发常用!】
需求:获得id值为0002的书名!
@Test
public void test() throws documentException {
// 创建SaxReader核心解析器对象
SAXReader saxReader = new SAXReader();
// 通过核心解析器对象加载xml文件获得document对象
document document = saxReader.read("src/books.xml");
// 获得id为0002的书book
Element book = (Element) document.selectSingleNode("//book[@id='0002']");
// 获得指定元素名称的文本值
System.out.println(book.elementText("name"));
}
三、扩展内容
面向接口编程(xml+反射实现解耦问题)
public interface Animal {
void eat();
}
public class Dog implements Animal{
@Override
public void eat() {
System.out.println("狗吃骨头!");
}
}
public class Cat implements Animal {
@Override
public void eat() {
System.out.println("猫吃鱼!");
}
}
public class Test {
public static void main(String[] args) {
// 创建动物类对象
// 更换动物类对象!
// 本身创建动物类对象
Animal animal = (Animal) BeanFactory.getBean("Animal");
animal.eat();
// 此时要更换动物类的对象!不用更改java源代码,只需要修改配置文件!
}
}
beans.xml
public class BeanFactory {
public static void main(String[] args) {
Object obj = getBean("Animal");
//System.out.println(obj); // com.itheima.demo05_interface.Dog@5e265ba4 【子类就是父类!】
Animal animal = (Animal) getBean("Animal");
System.out.println(animal);
}
public static Object getBean(String id){
try {
// 读取配置文件
SAXReader saxReader = new SAXReader();
document document = saxReader.read("day15_xml/src/beans.xml");
// 获得标签:
Element element = (Element) document.selectSingleNode("//bean[@id='"+id+"']");
// 获得Class属性的值
String className = element.attributevalue("class");
// 获得字节码对象
Class> clazz = Class.forName(className);
// 创建实例对象
Object obj = clazz.newInstance();
return obj;
} catch (Exception e) {
return null;
}
}
}



