java 解析XML文件(DOM & SAX)(一)
2015-12-10 16:47
615 查看
XML :可扩展标记语言,XML是一个以文本来描述数据的文档。
XML 用途:
1:充当显示数据。2:XML描述数据并在联系服务器系统的其余部分之间传递。
XML 是信息封装,和消息传递技术。
解析XML文件
1:DOM解析:
解析原理: 在处理DOM解析的时候,需要读入整个XML文档,然后在内存中创建DOM树,生成DOM树的每个NODE对象,当文档相对较小的时候,不会出现问题,当文档一旦较大,处理DOM就会相当费时,特别是其对内存的需求,也将成倍增加,以至于在某些应用中使用DOM是不划算的。
实例如下:
Person.xml 文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<codinkge>
<Person personid="1">
<name> 杨跟超</name>
<age>18</age>
<sex> 男 </sex>
<tel>11129290900</tel>
</Person>
<Person personid="2">
<name> 王建</name>
<age>18</age>
<sex> 男 </sex>
<tel>11129290900</tel>
</Person>
</codinkge>
创建一个Person类,属性包含xml文件中的各个属性 此处省略(生成Seter ,Geter 方法 构造方法,toString方法等)
主程序如下:
public class DOMforXML {
public static void main(String[] args) {
List <Person> p=parseDomXML();
for (Person person :p){
System.out.println(person);
}
}
private static List <Person> parseDomXML() {
List <Person> list = new ArrayList<Person>();
Person p = null;
// 创建一个文档解析工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 创建文档解析器
DocumentBuilder builder;
try {
builder = factory.newDocumentBuilder();
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/xiyou/Person.xml");
Document doc =builder.parse(is); // 将XML文件的输入流放入解析器中解析
// 从解析器中获取数据 (根据标签获得消息)
NodeList personlist= doc.getElementsByTagName("Person"); // 获取两个Person节点
for (int j = 0 ;j <personlist.getLength();j++){
Node presonNode = personlist.item(j);
p= new Person();
String id = presonNode.getAttributes().getNamedItem("personid").getNodeValue(); // 获取ID
p.setPersonid(id);
NodeList childs = presonNode.getChildNodes();// 获取根结点person下的所有子节点
for (int k = 0 ; k <childs.getLength() ;k++){
Node childNode =childs.item(k);
String name = childNode.getNodeName();
if ("name".equals(name)){
/*<name> 杨跟超</name> 杨跟超 相当于<name>标签的第一个节点
*/
p.setName(childNode.getFirstChild().getNodeValue());
}else if ("age".equals(name)){
p.setAge(Integer.parseInt(childNode.getFirstChild().getNodeValue()));
}else if ("sex".equals(name)){
p.setSex(childNode.getFirstChild().getNodeValue());
}else if ("tel".equals(name)){
p.setTel(Long.parseLong(childNode.getFirstChild().getNodeValue()));
}
}
list.add(p);
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
}
DOM解析的优缺点:
优点:1:由于整棵树在内存中,因此对xml文档随机访问 2:对XML文档进行修改
缺点 2: 整个文档必须一次解析完,2:由于真个文档都需要载入内存,对于大文档成本较高。
SAX 解析XML
由于DOM在解析XML的时候将整个XML文档读入内存,因此存在缺陷。SAX不同于DOM的文档驱动,它是事件驱动,也就是说它并不需要读入整个文档,而读入文档的过程就是SAX解析的过程,事件驱动是指一种基于回调机制的程序运行方法,在XMLReader接受XML文档的过程中就进行解析,就是读入的文档的过程就是解析的过程。适用于较大的只读文档。
在Sax的解析过程中,读取到文档开头、结尾,元素的开头和结尾都会触发一些回调方法,你可以在这些回调方法中进行相应事件处理
这四个方法是:startDocument() 、 endDocument()、 startElement()、 endElement
此外,光读取到节点处是不够的,还需要characters()方法来仔细处理元素内包含的内容
将这些回调方法集合起来,便形成了一个类,这个类也就是我们需要的触发器
一般从Main方法中读取文档,却在触发器中处理文档,这就是所谓的事件驱动解析方法
如上图在触发器中首先开始读取文档,然后逐个解析元素,每个元素中的内容会返回到characters ()方法,接着结束元素读取,所有元素读取完后,结束文档解析,
实例如下: 创建触发器类:
创建触发器类首先要继承DefaultHandler并重写响应的方法
public class PersonHandler extends DefaultHandler{
private List <Person > person;
private Person p ;
private String tag;//标记标签的名称
public List<Person> getPerson() {
return person;
}
@Override
// 开始文档解析
public void startDocument() throws SAXException {
super.startDocument();
person = new ArrayList<Person>();
System.out.println("开始解析文档。。。。。。");
}
@Override
// 开始解析标签, 形如<name> <sex>的标签为开始标签
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
if ("Person".equals(qName)){
p = new Person ();
p.setPersonid(attributes.getValue("personid"));
}
tag = qName;
}
@Override
//处理文本内容包括空格
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
if (tag!=null){
if ("name".equals(tag)){
p.setName(new String (ch, start , length));
}else if ("age".equals(tag)){
p.setAge(Integer.parseInt(new String (ch, start, length)));
}else if ("sex".equals(tag)){
p.setSex(new String (ch, start, length));
}else if ("tel".equals(tag)){
p.setTel(Long.parseLong(new String (ch , start,length)));
}
}
}
@Override
// 结束标签解析
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
if ("Person".equals(qName)){
person.add(p);// 将Person对象添加到列表中
}
tag = null;
}
@Override
// 结束文档解析
public void endDocument() throws SAXException {
super.endDocument();
System.out.println("文档解析完毕!!!!!");
}
}
Xml文档 (与上DOM解析同一个XML文档)
创建一个Person类,属性包含xml文件中的各个属性 此处省略(生成Seter ,Geter 方法 构造方法,toString方法等)
解析如下:
package com.xiyou;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
public class SAXUSE {
public static void main(String[] args) {
List <Person> list = parseSAXxml ();
for (Person person : list){
System.out.println(person);
}
}
private static List <Person> parseSAXxml() {
List <Person> list = null;
// 创建解析器工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
// 生成一个sax解析器
SAXParser parser = factory.newSAXParser();
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/xiyou/Person.xml");
PersonHandler dh = new PersonHandler();
try {
parser.parse(is, dh);//解析
list=dh.getPerson();
} catch (IOException e) {
e.printStackTrace();
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
return list;
}
}
XML 用途:
1:充当显示数据。2:XML描述数据并在联系服务器系统的其余部分之间传递。
XML 是信息封装,和消息传递技术。
解析XML文件
1:DOM解析:
解析原理: 在处理DOM解析的时候,需要读入整个XML文档,然后在内存中创建DOM树,生成DOM树的每个NODE对象,当文档相对较小的时候,不会出现问题,当文档一旦较大,处理DOM就会相当费时,特别是其对内存的需求,也将成倍增加,以至于在某些应用中使用DOM是不划算的。
实例如下:
Person.xml 文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<codinkge>
<Person personid="1">
<name> 杨跟超</name>
<age>18</age>
<sex> 男 </sex>
<tel>11129290900</tel>
</Person>
<Person personid="2">
<name> 王建</name>
<age>18</age>
<sex> 男 </sex>
<tel>11129290900</tel>
</Person>
</codinkge>
创建一个Person类,属性包含xml文件中的各个属性 此处省略(生成Seter ,Geter 方法 构造方法,toString方法等)
主程序如下:
public class DOMforXML {
public static void main(String[] args) {
List <Person> p=parseDomXML();
for (Person person :p){
System.out.println(person);
}
}
private static List <Person> parseDomXML() {
List <Person> list = new ArrayList<Person>();
Person p = null;
// 创建一个文档解析工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 创建文档解析器
DocumentBuilder builder;
try {
builder = factory.newDocumentBuilder();
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/xiyou/Person.xml");
Document doc =builder.parse(is); // 将XML文件的输入流放入解析器中解析
// 从解析器中获取数据 (根据标签获得消息)
NodeList personlist= doc.getElementsByTagName("Person"); // 获取两个Person节点
for (int j = 0 ;j <personlist.getLength();j++){
Node presonNode = personlist.item(j);
p= new Person();
String id = presonNode.getAttributes().getNamedItem("personid").getNodeValue(); // 获取ID
p.setPersonid(id);
NodeList childs = presonNode.getChildNodes();// 获取根结点person下的所有子节点
for (int k = 0 ; k <childs.getLength() ;k++){
Node childNode =childs.item(k);
String name = childNode.getNodeName();
if ("name".equals(name)){
/*<name> 杨跟超</name> 杨跟超 相当于<name>标签的第一个节点
*/
p.setName(childNode.getFirstChild().getNodeValue());
}else if ("age".equals(name)){
p.setAge(Integer.parseInt(childNode.getFirstChild().getNodeValue()));
}else if ("sex".equals(name)){
p.setSex(childNode.getFirstChild().getNodeValue());
}else if ("tel".equals(name)){
p.setTel(Long.parseLong(childNode.getFirstChild().getNodeValue()));
}
}
list.add(p);
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
}
DOM解析的优缺点:
优点:1:由于整棵树在内存中,因此对xml文档随机访问 2:对XML文档进行修改
缺点 2: 整个文档必须一次解析完,2:由于真个文档都需要载入内存,对于大文档成本较高。
SAX 解析XML
由于DOM在解析XML的时候将整个XML文档读入内存,因此存在缺陷。SAX不同于DOM的文档驱动,它是事件驱动,也就是说它并不需要读入整个文档,而读入文档的过程就是SAX解析的过程,事件驱动是指一种基于回调机制的程序运行方法,在XMLReader接受XML文档的过程中就进行解析,就是读入的文档的过程就是解析的过程。适用于较大的只读文档。
在Sax的解析过程中,读取到文档开头、结尾,元素的开头和结尾都会触发一些回调方法,你可以在这些回调方法中进行相应事件处理
这四个方法是:startDocument() 、 endDocument()、 startElement()、 endElement
此外,光读取到节点处是不够的,还需要characters()方法来仔细处理元素内包含的内容
将这些回调方法集合起来,便形成了一个类,这个类也就是我们需要的触发器
一般从Main方法中读取文档,却在触发器中处理文档,这就是所谓的事件驱动解析方法
如上图在触发器中首先开始读取文档,然后逐个解析元素,每个元素中的内容会返回到characters ()方法,接着结束元素读取,所有元素读取完后,结束文档解析,
实例如下: 创建触发器类:
创建触发器类首先要继承DefaultHandler并重写响应的方法
public class PersonHandler extends DefaultHandler{
private List <Person > person;
private Person p ;
private String tag;//标记标签的名称
public List<Person> getPerson() {
return person;
}
@Override
// 开始文档解析
public void startDocument() throws SAXException {
super.startDocument();
person = new ArrayList<Person>();
System.out.println("开始解析文档。。。。。。");
}
@Override
// 开始解析标签, 形如<name> <sex>的标签为开始标签
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
if ("Person".equals(qName)){
p = new Person ();
p.setPersonid(attributes.getValue("personid"));
}
tag = qName;
}
@Override
//处理文本内容包括空格
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
if (tag!=null){
if ("name".equals(tag)){
p.setName(new String (ch, start , length));
}else if ("age".equals(tag)){
p.setAge(Integer.parseInt(new String (ch, start, length)));
}else if ("sex".equals(tag)){
p.setSex(new String (ch, start, length));
}else if ("tel".equals(tag)){
p.setTel(Long.parseLong(new String (ch , start,length)));
}
}
}
@Override
// 结束标签解析
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
if ("Person".equals(qName)){
person.add(p);// 将Person对象添加到列表中
}
tag = null;
}
@Override
// 结束文档解析
public void endDocument() throws SAXException {
super.endDocument();
System.out.println("文档解析完毕!!!!!");
}
}
Xml文档 (与上DOM解析同一个XML文档)
创建一个Person类,属性包含xml文件中的各个属性 此处省略(生成Seter ,Geter 方法 构造方法,toString方法等)
解析如下:
package com.xiyou;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
public class SAXUSE {
public static void main(String[] args) {
List <Person> list = parseSAXxml ();
for (Person person : list){
System.out.println(person);
}
}
private static List <Person> parseSAXxml() {
List <Person> list = null;
// 创建解析器工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
// 生成一个sax解析器
SAXParser parser = factory.newSAXParser();
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/xiyou/Person.xml");
PersonHandler dh = new PersonHandler();
try {
parser.parse(is, dh);//解析
list=dh.getPerson();
} catch (IOException e) {
e.printStackTrace();
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
return list;
}
}
相关文章推荐
- Java Stream(流)、file(文件)和IO
- 老李案例分享:定位JAVA内存溢出 2
- 老李案例分享:定位JAVA内存溢出 1
- java中多种排序算法总结
- Mockito:一个强大的用于 Java 开发的模拟测试框架
- java的concurrent用法详解
- JAVA设计模式索引-- JournalDev
- java八大基本数据类型
- springmvc+ajaxfileupload异步上传
- 企业级微信公众号开发框架(spring+hibernate+springmvc)-01
- Java排序之排序大综合
- Java学习----数组
- Java IO流详解
- 启动工程时总会报一些奇葩的问题,Failed to read candidate component class,Caused by: java.lang.IncompatibleClassChang
- MyEclipse 优化
- spring+atomikos+JTA完整例子
- Spring详解
- Spring没有对ORM模块提供自己的实现,只对JDBC和其他ORM框架进行了封装。
- 另类的package-info.java文件探讨
- Spring注解@Component、@Repository、@Service、@Controller区别