一、SAX解析
1.特点
SAX解析:读一点,取一点,节省内存空间。一旦遇到开始标签触发之后,及时从内存中将开始节点从内存中释放点。
2.三要素
/**
* SAX解析:针对事件编程
* 三要素:
* 1)事件源
* 2)事件监听器
* 遇到文档开始 startDocument(......)
* 遇到开始标签 startElement(......)
* 遇到文本内容 characters(......)
* 遇到结束标签 endElement(......)
* 遇到文档结束 endDocument(......)
* 3)注册事件监听器:基于事件处理程序
* DefaultHandler
* 开发步骤:
* 1)创建SAX解析器对象
* 2)解析当前xml文件
* 3)基于事件处理进行判断(开始标签/结束标签/文本内容)
*/
3.DOM解析和SAX解析的区别
原理:前者,读一点,取一点,节省内存空间。一旦遇到开始标签触发之后,及时从内存中将开始节点从内存中释放点。
后者,一次性加载整个xml文件,如果xml文件结构层次深,可能会导致OOM异常,浪费空间。
使用过程区别:前者,只能去读(需求:使用SAX解析,将xx.xml文件原封不动打印)
后者:不仅能读,还能写,并且能往返读。
编程思想:前者,面向事件编程方式---->Java开发者难理解。
后者,面向对象编程思想,编程方式--->Java开发者好理解。
二、SAX解析的使用
1.使用SAX解析xml文件
xml文件为:
<?xml version="1.0" encoding="utf-8" ?>
<!--使用xml文件来标签联系人,姓名 性别 电话-->
<contact id="001">
<name>张三</name>
<phone>18292886805</phone>
<gender>男</gender>
</contact>
package com.xunpu.sax;
/**
* SAX解析:
* 读一点,取一点。节省空间,一旦遇到开始标签触发之后,及时从内存中将开始节点内存中释放。
*/
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* 编写监听器:自定义类 继续自基类(DefaultHandler)
*/
public class MyDefault1 extends DefaultHandler {
/**
*
* @param uri
* @param localName
* @param qName 开始标签名称<contact id="" name="">
* @param attributes 属性列表
* @throws SAXException
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
System.out.println("MyDefaultHandler1.startDociment:"+qName);
}
/**遇到文本内容
* @param ch
* @param start
* @param length
* @throws SAXException
*/
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
//遇到文本:每次读取到的是当前文本的实际内容
String content=new String(ch,start,length);
System.out.println("文档内容:"+content);
}
/**
* @param uri
* @param localName
* @param qName 结束标签名称
* @throws SAXException
*/
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
System.out.println("MyDefaultHandler1.endElement:"+qName);
}
/**
*
* @throws SAXException
*/
@Override
public void endDocument() throws SAXException {
System.out.println("MyDefault endDocument:森当解析结束了");
}
}
package com.xunpu.sax;
import org.dom4j.Document;
import org.dom4j.io.SAXReader;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.IOException;
public class SAXDemo {
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
//1)创建一个SAX解析器对象 SAXParse--抽象类 使用它的工厂类创建对象。
SAXParser parser=SAXParserFactory.newInstance().newSAXParser();
//2)读取xml文件
//事件源:解析contact.xml
parser.parse(SAXDemo.class.getClassLoader().getResourceAsStream("contact.xml"),
new MyDefault1());
}
}
注意:xml文件首行的拼写一定不能出现错误,否则就会出现"Exception in thread "main" org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 21; 应该有伪属性名。"类错误。
结果:
解析过程:
<contact id="001"> ------>startElement(qname,Attribute) 开始元素的触发事件
<name>张三------->张三:characters(ch,start,length) 文本触发事件
</name></contact>--------->endElement(qname,....) 结束标签触发的事件
2.使用SAX解析将xml文件原封不动输出
步骤:
1)创建解析器
2)读取xml文件
3)定义一个基于事件的处理程序(一个类 extends DefaultHandler)
使用字符串缓冲区对象StringBuffer
定义一个方法-->可以将字符缓冲区的内容-->String类型。
package com.xunpu.sax;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
//基于事件的处理程序
public class MyDefault2 extends DefaultHandler {
private StringBuffer sb=new StringBuffer();
//定义一个成员方法
public String getContent(){
return sb.toString();
}
//遇到开始标签 qName:标签名称
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
sb.append("<"+qName);
//遍历属性列表 getLength():返回属性列表的长度
for(int i=0;i<attributes.getLength();i++){
//获取到每一个属性对象
String attributesName=attributes.getQName(i);
String attrValue=attributes.getValue(i);
//双引号需要转义
sb.append(" "+attributesName+"=\""+attrValue);
}
sb.append(">");
}
//遇到文本内容
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
String content=new String(ch,start,length);
sb.append(content);
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
sb.append("</"+qName+">");
}
}
package com.xunpu.sax;
import org.dom4j.io.SAXReader;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.IOException;
public class SAXDemo2 {
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
SAXParser parser=SAXParserFactory.newInstance().newSAXParser();
MyDefault2 handler2=new MyDefault2();
parser.parse(SAXDemo2.class.getClassLoader().getResourceAsStream("contact.xml"),handler2);
String content=handler2.getContent();
System.out.println(content);
}
}
结果:
三、xml文件的约束(简介)
1.dtd约束
<!--内部方式-->
<!DOCTYPE note[
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
note.xml文件
<!--外部方式 note是根节点 约束为note.dtd文件-->
<!DOCTYPE note SYSTEM "note.dtd">
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
note.dtd文件:
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
外部文件一些约束的声明:
<!--声明属性:
<!ATTLIST 元素名称 属性名称 属性类型 默认值>
CDATA:普通字符串
<!ATTLIST body id CDATA #REQUIRED> :约束body的内容是普通字符串而且必须指定id属性。
<!ATTLIST body id CDATA #FIXED "002"> :约束body的内容是普通字符串而且必须id属性值必须是"002",否则值无效。
-->
2.schema约束
名称空间的定义格式: xmlns:名称空间="别名"(URL)
如:
<bite:书架 xmlns:bite="http://www.bite.cn"
xmlns:xsi="htttp://wwwww.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.bite.cn book.xsd">
在第一行中,bite是名称空间,"http://www.bite.cn"是别名。
schemaLocation中指代的文件是用来约束书架的!!
使用名称空间:1)使用名称空间在xml中定义标签,必须指定别名。如:“http://www.bite.cn”
2)关联当前别名地址:schemaLocation="别名1 地址1 别名2 地址2....."。
定义后的名称空间,指定标签名称格式:名称空间:标签名称(如bite:书架)----->书架标签被book.xsd文件所约束。
xxx.xsd:schema约束文件
w3c组织定义的格式:xs:约束xml文件定义的标签。
Schema约束(类型丰富) 是基于 XML 的 DTD 替代者。