1 XPath技术
1.1 作用
作用:快速地查询到xml文件中节点。
当xml文件中的标签层次结构很深,那么如何来快速地定位到所需的标签呢?这就用到了xpath技术!!
1.2 体验xpath技术
1)导入jaxen-1.1-beta-6.jar dom4j的xpath插件包
2)在dom4j中使用xpath
List<Node> list =selectNodes("xpath表达式") 查询多个节点
Node node = selectSingleNode("xpath表达式") 查询一个节点
1.3xpath表达式(重点)
/ 绝对路径 斜杠在最前面,代表xml文件的根。斜杠在中间,表示子元素。
// 相对路径 选择后代元素(不分层次结构)
* 通配 选择所有元素
[] 条件 选择什么条件下的元素。例如 /AAA/BBB[1] 选择第一个BBB子元素
@ 属性 选取属性
= 内容 (值)
and 逻辑与
text() 选取文本内容
2 SAX解析
2.1 引入
xml解析方法:
dom解析:原理为xml解析引擎一次性把整个xml文件加载进内存,在内存创建一颗document树。
问题:大文件的话,使用dom解析效率比较低,甚至会导致内存溢出。
编程方式:面向对象编程方式
sax解析:原理为加载一点,读取一点,处理一点。优势:占用的内存比较小。
编程方式:基于事件编程方式。
2.2 SAX解析工具
sun公司官方的sax解析工具。 在jdk中包含sax解析工具的api。org.xml.sax.*;
2.3 SAX解析的开发步骤
package gz.itcast.b_sax;
import java.io.File;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
/**
* sax解析入门
* @author 王磊
*
*/
public class Demo1 {
public static void main(String[] args) throws Exception, SAXException {
//1)创建SAXParser解析对象
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
//2)解析xml文件
/**
* 参数一: 需要解析的xml文件
* 参数二: 指定的DefaultHandler
*/
/**
* 事件编程模式三要求:
* 事件源:xml文件
* 事件:解析到开始标签(包含属性),解析到结束标签,解析文本内容
* 监听器:DefaultHandler
*/
//3)类似于注册监听器
parser.parse(new File("./src/contact.xml"), new MyDefaultHandler1());
}
}
package gz.itcast.b_sax;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* sax解析事件处理程序(类似于事件的监听器)
* @author 王磊
*
*/
public class MyDefaultHandler1 extends DefaultHandler{
/**
* 遇到xml文档的开始位置触发此方法
*/
@Override
public void startDocument() throws SAXException {
System.out.println("MyDefaultHandler1.startDocument()");
}
/**
* 遇到每个开始标签触发次方法
* @param qName: 表示当前读到的开始标签名称
* @param attributes : 属性列表
*/
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
System.out.println("MyDefaultHandler1.startElement()->"+qName);
}
/**
* 遇到每个结束标签时触发此方法
* @param qName: 当前读到的结束标签名称
*/
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
System.out.println("MyDefaultHandler1.endElement()->"+qName);
}
/**
* 遇到文本内容触发此方法
* 如何获取当前读到的内容?
* char[]: 表示到目前为止读到的文本内容
* start: 表示当前内容的起始位置
* length: 表示当前内容的长度
*/
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
/**
* char[]内容: 张三 男 1341111122222
*/
//获取当前读到的内容
String content = new String(ch,start,length);
System.out.println("MyDefaultHandler1.characters()->"+content);
}
/**
* 遇到xml文档 的结尾
*/
@Override
public void endDocument() throws SAXException {
System.out.println("MyDefaultHandler1.endDocument()");
}
}
2.4 SAX案例
package gz.itcast.b_sax;
import java.io.File;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
/**
* 使用sax解析方式读取contact.xml文件内容,原封不动打印文件信息
* @author 王磊
*
*/
public class Demo2 {
public static void main(String[] args) throws Exception, SAXException {
//1)创建SAXParser对象
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
//创建事件处理程序
MyDefaultHandler2 handler2 = new MyDefaultHandler2();
//2)读取xml文件
parser.parse(new File("./src/contact.xml"), handler2);
System.out.println(handler2.getContent());
}
}
package gz.itcast.b_sax;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* sax事件处理程序
* @author APPle
*
*/
public class MyDefaultHandler2 extends DefaultHandler{
//存储contact.xml文件信息
//当contact.xml读取完毕之后,这个变量就有了所有xml文件信息
private StringBuffer sb = new StringBuffer();
public String getContent(){
return sb.toString();
}
//开始标签
/**
* qName:开始标签的名称
* attributes: 属性列表
*/
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
sb.append("<"+qName);
//属性列表
if(attributes!=null){
//遍历属性
for(int i=0;i<attributes.getLength();i++){
String name = attributes.getQName(i);//属性名称
String value = attributes.getValue(i);//属性值
sb.append(" "+name+"=\""+value+"\"");
}
}
sb.append(">");
}
//文本内容
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
//当前文本内容
String content = new String(ch,start,length);
sb.append(content);
}
//结束标签
//qName: 结束标签名称
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
sb.append("</"+qName+">");
}
}
=============== DOM解析 vs SAX解析=====================
| DOM解析 | SAX解析 |
原理 | 一次性加载进内存,构造document树,内存占用比较大 | 加载一点,读取一点,内存占用相对小 |
读取顺序 | 可以读取XML文件任意位置信息,甚至往回读 | 只能是从上往下依次读取,不能往回读 |
操作方式 | 可以进行查询,也可以进行修改 | 只能查询 |
编码方式 | 面向对象编程方式,更加适合java开发者 | 基于事件编程方式,相对java开发难理解 |
3 XML约束
3.1 什么是约束?
xml语法: w3c组织对xml文件的编程规则规范。(w3c组织制定的)
xml约束:由开发者指定的对xml文件内容规范。(开发者根据业务指定的)
3.2 约束分类
DTD约束:相对简单的,数据类型简单的
场景:hibernate struts2
Schema约束:相对复杂,功能很强大,数据类型非常丰富。schema的出现时为了替代DTD的。
3.3 DTD约束
1)dtd的使用方法
内部的dtd
外部的dtd
2)语法
约束标签
<!ELEMENT元素名称 类别> 或<!ELEMENT 元素名称 (元素内容)>
类别:
EMPTY:空标签
PCDATA:普通字符串(不能包含子标签)
ANY:任意内容(可以包含子标签)
顺序问题:
(子元素名称 1,子元素名称 2,.....):一定要依次出现1,2,...
数量问题:
子元素: 有且仅有1个
+: 1个或多个
*: 0个或多个
?: 0个或1个
约束属性
<!ATTLIST 元素名称属性名称 属性类型 默认值>
默认值
#REQUIRED:必须
#IMPLIED:不是必须的
#FIXED value : 固定的
属性类型:控制属性值
CDATA:普通字符串
(en1|en2...): 枚举中的一个值
ID:唯一的值
3.4schema约束
重点:名称空间
总结:
1)xml语法:
标签、属性、文档声明、处理指令
2)xml解析(运用)
Dom解析:原理???(面向对象)
2.1 dom解析的工具:dom4j工具
2.2 对xml文件增删改查(方法)
2.3 xpath技术:快速查询xml文件的节点(标签,属性,文本)
SAX解析:原理???(基于事件的)
2.1 DefaultHandler类
startElement():开始标签
characters():文本内容
endElement():结束标签
3)xml约束(看懂)
dtd约束:简单
schema约束:看得懂名称空间,如何找到scheme约束文件?
语法查询w3c文档