第二章 XML编程
目录
1、XML入门
1.1 XML介绍
Extensible Markup Language,翻译过来为可扩展标记语言。Xml技术是w3c组织发布的,目前推荐遵循的是W3C组织于2000发布的XML1.0规范。在XML语言中,它允许用户自定义标签。一个标签用于描述一段数据;一个标签可分为开始标签和结束标签,在开始标签和结束标签之间,又可以使用其它标签描述其它数据,以此来实现数据关系的描述。
1.2 XML和HTML的区别
HTML语言 | XML语言 | |
---|---|---|
名称 | 超文本标记语言 | 可扩展标记语言 |
标记的范围 | 由w3c组成指定的标签(固定的) | 没有限制的,自定义标签。(符合xml语法) |
语法结构 | 语法结构松散。(大小写不区分) | 相对严谨(大小写区分) |
作用(用途) | 用于网页的结构 | 1、描述带关系的数据(作为软件的配置文件。2、 作为存储数据的容器。(作为小型的数据库) |
1.3 XML的作用
1.3.1 描述带关系的数据(软件的配置文件)
-
一个软件在启动时,它需要启动A、B两个模块,而A、B这两个模块在启动时,又分别需要A1、A2和B1、B2模块的支持,为了准确描述这种关系,此时使用XML文件最为合适不过。
-
web服务器PC: 学生管理系统 -> 添加学生 -> name=jacky age=20 -> 后台接收数据,保存到数据库中。xml文件作为学生管理系统的配置文件。
-
用java代码连接oracle数据库。(使用IP和端口)保存数据条件:IP:211.34.21.54 ;端口:1521
-
数据库服务器PC: oracle 接近3G oracle内存溢出,如果数据库服务器PC奔溃。需要切换数据库服务器,需要改java代码,这样不好!最好把IP和端口写在xml文件中
dbhost.xml
<dbhost>
<ip>211.34.21.56</ip>
<port>1521</port>
</dbhost>
- 三大框架的软件配置文件,就是使用xml文件。
1.3.2 作为数据存储容器
2、XML语法
xml文件后缀名为.xml,使用浏览器去检查xml是否符合语法。因为浏览器内置了xml的解析引擎。
2.1 标签
-
xml的标签是自定义标签,语法: 张三
-
注意:
- 严格区分大小写
- 标签名不能以数字开头。只能以字母或下划线开头,中文。
- 标签名不能包含空格
- 如果没有使用名称空间,标签名不能包含冒号
- 在一个xml文档中,只允许有且仅有一个根标签
2.2 属性
- 属性放在开始标签中。
- 值必须放在双引号或单引号中,不能省略引号,也不能单双混用。
- 在一个标签中,属性可以有多个,但不能出现同名的属性。
2.3 注释
<!-- xml注释 -->
2.4 转义字符
如果希望在xml文件中原样输出xml中的特殊字符,那么就需要对其进行转义。
2.5 CDATA块
CDATA块的作用,如果xml中的一段内容都希望原样输出,可以把这段内容包含在CDATA块中。<![CDATA[ 内容 ]]>
<![CDATA[
<itcast>
<br/>
</itcast>
]]>
2.6 文档声明
- 语法:<?xml version="1.0" encoding="utf-8" standalone="yes" ?> ,version: 表示xml的版本号。encoding: 浏览器打开xml文件时(解码)查询码表;用standalone属性说明文档是否独立。
- xml文档编码问题注意:
- idea工具会自动根据xml文件的文档声明自动设置保存时的编码,所以在idea工具中编写xml文件通常不会有编码问题。
- 但是如果使用记事本工具,那么注意保存xml文件的编码和文件声明的编码保持一致
- 而且这个<?xml 要连在一起写,否则会有报错
2.7 处理指令
- 作用: 主要告诉浏览器如何解析xml文件希望提出出xml文件中对我们有用的内容,把标签忽略掉。 <?xml-stylesheet type="text/css" href="1.css"?> 告诉浏览器该xml文档引用哪个css文档
- 注意:使用了处理指令,xml文档和html文档的作用就类似了,都可以作为网页的结构。但xml的该功能基本已经不再使用了。
3、XML解析
3.1 xml解析入门
- XML解析: xml文件除了给开发者看之外,更多的是使用程序去读取或操作。
3.2 xml解析方式
- DOM解析:基于DOM模型解析xml文件,DOM解析器使用树形模型,把XML文档转化为一个包含其内容的树,并可以对树进行遍历。
- SAX解析:基于SAX的原理解析xml文件,SAX解析器采用了基于事件的模型,解析XML文档的时候可以触发一系列的事件。
3.3 xml解析工具
3.3.1 基于DOM解析
- Dom4j工具。非常流行的xml解析工具。三大框架ssh,读取xml工具的就是dom4j,tomcat7或以上,使用dom4j读取xml文件。
- JAXP工具(sun公司官方)
- JDOM工具:JDOM的目的是成为Java特定文档模型,它简化与XML的交互并且比使用DOM实现更快。
3.3.2 基于SAX解析
- SAX解析工具(sun公司官方api)
4、DOM解析
4.1 DOM解析模型
XML解析引擎加载完毕XML文件时,会啊XML文件的各个部分(标签、属性、文本)等封装成节点对象,然后我们通过节点对象获取或者设置标签、属性、文本、内容,
4.2 DOM4j 解析工具
4.2.1 DOM4J的体系结构
4.2.2 dom4j 目录
目录 | 介绍 |
---|---|
docs | 第三方类库的学习文档(目录下的index.html可以查看文档) |
lib | dom4j需要依赖其他的第三方类库 |
src | dom4j源码目录 |
4.2.3 安装
去官网下载zip包;在项目导入dom4j的jar包。核心包dom4j-1.6.jar包即可;编写测试类。读取xml文件
4.2.5 使用dom4j解析工具读取xml文件
/**
* 使用dom4j解析工具读取xml文件
* @author APPle
*
*/
public class Demo1 {
public static void main(String[] args) {
try {
//1.创建SAXReader(解析器对象)
SAXReader reader = new SAXReader();
//2.调用read方法,读取xml文件
Document doc = reader.read("./src/contact.xml");
System.out.println(doc);
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
4.2.6 遍历标签获取所有标签中的内容
- 第一步,通过创建 SAXReader 对象。来读取 xml 文件,获取 Document 对象
- 第二步,通过 Document 对象。拿到 XML 的根元素对象
- 第三步,通过根元素对象。获取所有的 book 标签对象
- 第四小,遍历每个 book 标签对象。然后获取到 book 标签对象内的每一个元素,再通过 getText() 方法拿到起始标签和结束标签之间的文本内容
/*
* 读取 xml 文件中的内容
*/
@Test
public void readXML() throws DocumentException {
起始标签和结束标签之间的文本内容
// 第一步,通过创建 SAXReader 对象。来读取 xml 文件,获取 Document 对象
SAXReader reader = new SAXReader();
Document document = reader.read("src/books.xml");
// 第二步,通过 Document 对象。拿到 XML 的根元素对象
Element root = document.getRootElement();
// 打印测试
// Element.asXML() 它将当前元素转换成为 String 对象
// System.out.println( root.asXML() );
// 第三步,通过根元素对象。获取所有的 book 标签对象
// Element.elements(标签名)它可以拿到当前元素下的指定的子元素的集合
List<Element> books = root.elements("book");
// 第四小,遍历每个 book 标签对象。然后获取到 book 标签对象内的每一个元素,
for (Element book : books) {
// 测试
// System.out.println(book.asXML());
// 拿到 book 下面的 name 元素对象
Element nameElement = book.element("name");
// 拿到 book 下面的 price 元素对象
Element priceElement = book.element("price");
// 拿到 book 下面的 author 元素对象
Element authorElement = book.element("author");
// 再通过 getText() 方法拿到起始标签和结束标签之间的文本内容
System.out.println("书名" + nameElement.getText() + " , 价格:"
+ priceElement.getText() + ", 作者:" + authorElement.getText());
}
}
4.3 得到xml文档信息
-
SAXReader类: read():读取xml文档
-
节点信息:nodeIterator(): 获取当前标签下的子节点
-
标签信息:getName(): 得到标签名称;element(name); 获取当前标签下的指定名称的第一个子标签;elementIterator(name); 获取当前标签下的指定名称的所有子标签;elements(); 获取当前标签下的所有子标签
-
属性信息:
attributeValue(name): 获取指定属性名的属性值
attribute(name); 获取指定属性名的属性对象
attributes(): 获取所有属性对象。返回List集合
attributeIterator(): 获取所有属性对象。返回Iterator
getName():获取属性名称
getValue(): 获取属性值
- 文本信息:
getText(): 获取标签的文本内容
4.4 如何把xml数据封装成对象
/**
* 在项目需要频繁把xml文档封装成对象
* @author APPle
*
*/
public class Demo4 {
public static void main(String[] args) throws Exception{
List<Contact> list = new ArrayList<Contact>();
//读取xml文档封装到List集合中
//1.读取xml文档
Document doc = new SAXReader().read("./src/contact.xml");
//2.读取所有contact标签
Iterator<Element> it = doc.getRootElement().elementIterator("contact");
while(it.hasNext()){
Element conElem = it.next();
//2.1 创建Contact对象
Contact con = new Contact();
//2.2 把contact标签数据放入Contact对象
//id
con.setId(conElem.attributeValue("id"));
//name
con.setName(conElem.element("name").getText());
con.setGender(conElem.element("gender").getText());
con.setPhone(conElem.element("phone").getText());
con.setQq(conElem.element("qq").getText());
con.setEmail(conElem.element("email").getText());
//2.3 把Contact对象放入List集合
list.add(con);
}
for (Contact contact : list) {
System.out.println(contact);
}
}
}
4.5 修改XML文档信息
XMLWriter类: writer(): 写出一个document对象到xml文件
添加:
DocumentHelper.createDocument(); 添加文档对象
addElement(name) 添加标签对象
addAttribute(name,value) 添加属性对象
修改:
Attribute.setValue(value) 修改属性值
Element.addAttribute("name","value"); 修改属性值,通过添加同名属性
Element.setText(value) 修改文本内容
删除:
Element.getParent().remove(elment) 删除标签
Element.detach() 删除标签
Attribute.getParent().remove(attri) 删除属性
Attribute.detach() 删除属性
5、XPath技术
5.1 Xpath 的作用
XPath主要是用于快速查找到XML文档中的节点的技术。(一般获取节点:Document.getRootElement().element(“contact”).element(“name”))当xml文档的节点层次结构比较深的时候,获取深层次的节点就会比较麻烦了!这时就可以使用xpath技术解决这个问题。
5.3 XPath在dom4j中使用
- 在项目中导入xpath支持jar包。jaxen-1.1-beta-6.jar
- 使用dom4j提供的xpath方法:selectNodes(xpath表达式): 查询符合条件的多个节点对象;selectSingleNode(xpath表达式) 查询符合条件的一个节点对象
5.3 XPath表达式语法
符号 | 解释 | 作用 |
---|---|---|
/ | 绝对路径 | 从根标签开始获取子元素 |
// | 相对路径 | 不分层次结构的所有元素 |
* | 通配符 | 选择所有标签 |
[] | 条件 | 选择带条件的元素。如first()、last() |
@ | 属性 | 选择属性 |
and | 逻辑运算 |
6、SAX解析
6.1 DOM解析和SAX解析比较
DOM解析 | SAX解析 | |
---|---|---|
原理 | 一次性加载xml文档,内存占用比较大 | 加载一点,读取一点,处理一点,释放内存,内存占用较小 |
读取顺序 | DOM可以任意在文档读取,甚至往回读 | SAX解析从上往下依次读取,不能往回读 |
操作 | DOM解析可以增删改查操作 | SAX解析只能读取 |
编程方法 | 基于对象编程模式,根据符合java开发者思维 | 基于事件编程模式,编程相对复杂 |
6.2 SAX解析工具
- oracle-sun官方的API, 在jdk中,属于javase的规范。org.xml.sax.* 。并不需要导入包。
6.3 SAX解析工具的核心API
- SAXParser类: 解析器对象(类似于dom4j SAXReader):parse(File f, DefaultHandler dh): 方法。用于解析xml文件。File: 指定读取的xml文件,DefaultHandler: 事件处理程序的默认基类。
//DefaultHandler类:
startDocument() :// 开始文档时触发的方法
startElement(String uri, String localName, String qName, Attributes attributes) //遇到开始标签触发的方法
characters(char[] ch, int start, int length) //遇到文本内容触发的方法
endElement(String uri, String localName, String qName) //遇到结束标签
endDocument() //结束文档时触发的方法
6.4 SAX解析步骤
6.4.1 SAX解析主程序
/**
* 基于SAX解析读取xml文件
* @author APPle
*
*/
public class Demo1 {
public static void main(String[] args)throws Exception {
//1.创建SAXParser对象
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
//2.调用parse方法,读取和解析xml文件
/**
* 参数一: 指定的文件地址
*/
File file = new File("./src/contact.xml");
/**
* 参数二: 指定DefaultHandler的子类
*/
parser.parse(file, new MyDefaultHandler());
}
}
6.4.2 事件处理程序
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* 事件处理程序
* @author APPle
*/
public class MyDefaultHandler extends DefaultHandler {
/**
* 遇到文档开始
*/
@Override
public void startDocument() throws SAXException {
System.out.println("文档开始读取");
}
/**
* 遇到开始标签
* @param qName: 当前遇到的标签名称
*/
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
System.out.println("MyDefaultHandler.startElement()-->"+qName);
}
/**
* 遇到文本内容(包括空格换行)
* @param ch : 表示整个xml文档所有文本内容
* @param start: 表示当前读到的文本内容的开始位置
* @param length: 表示当前读到的文本内容的长度
*/
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
//得到当前读到的文本内容
String content = new String(ch,start,length);
System.out.println("MyDefaultHandler.characters()-->"+content);
}
/**
* 遇到结束标签
* @param qName: 表示当前读取的结束标签名称
*/
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
System.out.println("MyDefaultHandler.endElement()-->"+qName);
}
/**
* 遇到结束文档时
*/
@Override
public void endDocument() throws SAXException {
System.out.println("文档读取完毕");
}
}
7、XML约束
7.1 引入
XML语法: 由w3c组成规定的编写xml文档的基本规则。(由w3c组成指定)
XML约束: 由开发者指定的约束xml文档的数据内容的规则。(由开发者指定的)
7.2XML约束分类
1、DTD约束:语法结构相对简单。数据类型相对单一。
- 应用场景:三大框架的配置文件。struts 和 hiberate都是使用了dtd约束(.dtd)
2、Schema约束:语法结构相对复杂,数据类型比较丰富。Schema的出现是为了DTD的。
- 应用场景:spring的配置文件使用schema约束(后缀名xsd)
7.3 DTD约束
DTD(Document Type Definition),全称为文档类型定义。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ar1cW8wi-1583581130566)(media/DTD_find.png)]
7.3.1 编程校验XML文档正确性
IE5以上浏览器内置了XML解析工具:Microsort.XMLDOM,开发人员可以编写javascript代码,利用这个解析工具装载xml文件,并对xml文件进行dtd验证。
//创建xml文档解析器对象
var xmldoc = new ActiveXObject("Microsoft.XMLDOM");
//开启xml校验
xmldoc.validateOnParse = "true";
//装载xml文档
xmldoc.load("book.xml");
//获取错误信息
//xmldoc.parseError.reason;
//xmldoc.parseError.line
7.3.2 编写DTD约束的两种方式
DTD约束即可以作为一个单独的文件编写,也可以在XML文件内编写。
1、 内部导入:直接把dtd内容写在xml文件中:
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
7.3.2外部导入
<!DOCTYPE note SYSTEM "note.dtd">
SYSTEM: 导入本地的dtd文件
PUBLIC: 导入网络上dtd文件
7.3.3语法
-
标签约束:语法:<!ELEMENT 元素名称 类别> 或 <!ELEMENT 元素名称 (元素内容)>
-
类别: PCDATA: 表示普通的字符串;ANY: 表示任意内容。可以是普通字符串,也可以是子孙标签;EMPTY: 表示空标签。
-
元素内容:(子元素名称 1,子元素名称 2,…): 表示按顺序依次出现1次子元素。+: 表示1或多次;*: 表示零或多次;?:表示零或1次
-
属性约束:
1、语法: <!ATTLIST 元素名称 属性名称 属性类型 默认值>
2、默认值:
#REQUIRED 属性值是必需的
#IMPLIED 属性不是必需的
#FIXED value 属性值是固定的
3 、属性类型:
CDATA: 表示普通字符串
(en1|en2|..): 表示枚举,只使用其中的某一个值
ID: 表示属性值唯一。注意不能以数字开头
7.4 Schema约束
1、名称空间:
主要用于声明一个xml的标签被哪个schema文件约束。在一个xml文件中,不同的xml标签可以受到不同的schema文件的约束。
2、使用名称空间导入schema文件
<itcast:书架 xmlns:itcast="http://www.itcast.cn"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=“http://www.itcast.cn book.xsd">
3、使用默认名称空间导入schema文件
<书架 xmlns="http://www.it315.org/xmlbook/schema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=“http://www.it315.org/xmlbook/schema book.xsd">
3、使用名称空间导入多个schema文件
<书架 xmlns="http://www.it315.org/xmlbook/schema"
xmlns:demo="http://www.it315.org/demo/schema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.it315.org/xmlbook/schema http://www.it315.org/xmlbook.xsd
http://www.it315.org/demo/schema http://www.it315.org/demo.xsd">