java解析XML(sax解析)


XML相关概念:

XML是什么:

  XML:X (extensible: 可扩展的) M (markup 标记/标签) L (language 语言);可扩展的标记语言!


XML的作用:

  1. 存:作为存储文件,例如:单机游戏中的等级,装备等等;因为有时使用数据库太大,而普通文件太慢,所以采用xml文件保存软件中的数据!
  2. 传:代替数据包进行网络上传递数据。
  3. 作为配置文件。

XML的特点:

  1. 平台无关性(windows, linux), 独立的语言
  2. 大多数语言都支持XML
  3. xml具有自我描述性(内容自定义) :
    html文件中,所有元素(标签) 都是官方定义好的,我们直接引用;但在 xml文件中,所有元素都是我们自己定义。

XML的语法规则:

  1. xml 文件必须有根元素
  2. xml元素(标签)有开必有合(结束标签)! .
  3. xml 元素对大小写敏感
  4. xml元素必须正确的嵌套
  5. xml 元素的属性必须加引号(单引双引都可以)

CDATA区

  在CDATA区中书写特殊符号时,忽略其本性,变成普通的字符串。
  如下CDATA中的字符串‘10<5’,为了避免将字符串中的‘<’号当成标签部分,所以将整个字符串放入CDATA区。

<?xml version="1.0" encoding= "UTF-8"?>
<student >
<xx> <![CDATA[ 10<5 ]]> </xx>
</student >

DTD文件

  • DTD 的全称: Document Type Definition文档类型定 义
  • DTD 的目的:帮助你编写合法的代码
  • DTD和XML之间的关系:当XML引入一个DTD文件时,就不可以再自定义标签,因为DTD文件里已经定义好,只需要给标签添加内容即可。有点类似于类和对象的关系。

XSD文件

  • xsd 是xml结构定义(XML Schemas Definition)

  • xsd 是dtd的替代品,比dtd高端;实现和dtd相同的功能。

  • xsd的优点:

    1. xsd 的代码基于xml,没有专门的语法,和xml一样的解析和处理,DTD有自己独立的语法。
    2. xsd支持一系列的数 据类型。

解析XML:

解析xml的四种方式:

  1. DOM解析
  • dom 解析的原理解析xml的时候,把文档中的所有元素按照其出 现的层次关系,在内存中构造出树形结构.
  • dom的优点就是可以遍历和修改节点的内容
  • 缺点是内存压力较大, 解析较慢
  1. SAX 解析

● 是一种xml 解析的替代方法
● 相对比dom 方式,sax 是一种速度更快,更有效的方法 ● 不能修改节点内容

  1. JDOM解析

● 仅适用具体的类,而不用接口,不灵活

  1. DOM4J 解析(最常用)

● JDOM的一种智能的分支,合并了许多超出基本XML文档的功能
● 著名的底层框架hibernate就是用dom4j来解析。


四种方式的分析:

  前两种属于基础方法,是官方提供的与平台无关的解析方式。
  后两种属于扩展方法,他们是在基础的方法之上扩展出来的,只适用于java平台。

  dom4j性能最高,其次是SAX,、dom和jdom表现不好(解析 10兆大小的xml文件,就内存溢出了。)


SAX 解析方法

例一 sax解析的步骤

XML文件内容如下:

<?xml version= "1.0" encoding= "UTF-8"?>
<persons>
	<person>
		<name>至尊宝</name>
		<age> 9000</age>
	</person>
</persons>

java代码如下:

package xml;

import java.io.IOException;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/*
 * SAX解析流程
 */
public class XmlTest01 {
	public static void main(String[] args) throws Exception {
		//SAX解析
		//1、获取解析工厂
		SAXParserFactory factory=SAXParserFactory.newInstance();
		//2、从解析工厂获取解析器
		SAXParser parse =factory.newSAXParser();
		//3、编写处理器
		//4、加载文档Document注册处理器    
		PHandler handler=new PHandler();
		//5.解析
		parse.parse(Thread.currentThread().getContextClassLoader()
		.getResourceAsStream("xml/p.xml")
		,handler );
	}
}

class PHandler extends DefaultHandler{
	@Override
	//解析开始时运行
	public void startDocument() throws SAXException {
		System.out.println("---解析文档开始---");
	}
	
	@Override
	//读取到标签时,获取标签参数运行
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		System.out.println(qName+"-->解析开始");
	}
	
	@Override
	//用于读取内容
	public void characters(char[] ch, int start, int length)throws SAXException {
		String contents = new String(ch, start, length).trim(); //去掉两边的空格
		if(contents.length()>0){
			System.out.println("内容为->"+contents);
		}else{//碰到空格
			System.out.println("内容为->"+"空");
		}
	}
	
	@Override
	//读取到结束标签时,运行
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		System.out.println(qName+"-->解析结束");
	}
	
	@Override
	//文档解析结束时,即读取到根标签的结束符时,运行
	public void endDocument() throws SAXException {
		System.out.println("---解析文档结束---");
	}
}

运行结果:
—解析文档开始—
persons–>解析开始
内容为->空
person–>解析开始
内容为->空
name–>解析开始
内容为->至尊宝
name–>解析结束
内容为->空
age–>解析开始
内容为->9000
age–>解析结束
内容为->空
person–>解析结束
内容为->空
persons–>解析结束
—解析文档结束—


结果解析:
  SAX 解析方法是按照流的方式进行,从上到下依次进行读取。有些内容为空是因为写标签时格式的缩进导致的。


例二 sax解析XML并保存数据

XML文件内容如下:

<?xml version= "1.0" encoding= "UTF-8"?>
<persons>
	<person>
		<name>至尊宝</name>
		<age> 9000</age>
	</person>
	<person>
		<name>白晶晶</name>
		<age> 600</age>
	</person>
</persons>

Person类代码如下:

package xml;

public class Person {
	private String name;
	private int age;
	public Person(){
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}

sax解析代码如下:

package xml;

import java.io.IOException;
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.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/*
 * SAX解析流程
 */
public class XmlTest02 {
	public static void main(String[] args) throws Exception {
		//SAX解析
		//1、获取解析工厂
		SAXParserFactory factory=SAXParserFactory.newInstance();
		//2、从解析工厂获取解析器
		SAXParser parse =factory.newSAXParser();
		//3、编写处理器
		//4、加载文档Document注册处理器    
		PersonHandler handler=new PersonHandler();
		//5.解析
		parse.parse(Thread.currentThread().getContextClassLoader()
		.getResourceAsStream("xml/p.xml")
		,handler );
		
		//读取数据
		List<Person> persons = handler.getPersons();
		for(Person p:persons){
			System.out.println(p.getName()+"-->"+p.getAge());
		}
	}
}

class PersonHandler extends DefaultHandler{
	private List<Person> persons;
	private Person person;
	private String tag; //存储当前操作的标签
	@Override
	//解析开始时运行
	public void startDocument() throws SAXException {
		System.out.println("---解析文档开始---");
		persons = new ArrayList<Person>();
	}
	
	@Override
	//读取到标签时,获取标签参数运行
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		System.out.println(qName+"-->解析开始");
		if(qName!=null){
			tag = qName;  //存储标签名
			if(tag.equals("person")){  //开始读取一个类,即一个<person>标签
				person = new Person();
			}
		}
	}
	
	@Override
	//用于读取内容
	public void characters(char[] ch, int start, int length)throws SAXException {
		String contents = new String(ch, start, length).trim(); //去掉两边的空格
		if(tag!=null){//这个判断是为了避免读取空内容
			if(tag.equals("name")){
				person.setName(contents);
			}else if(tag.equals("age")){
				if(contents.length()>0){
					person.setAge(Integer.valueOf(contents));
				}
			}
		}
	}
	
	@Override
	//读取到结束标签时,运行
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		System.out.println(qName+"-->解析结束");
		if(qName!=null){//这里由于tag有可能已经为空,所以不能再用tag进行判断
			if(qName.equals("person")){
				persons.add(person);   //成功读取完一个类,添加进容器
			}
		}
		tag = null; //将tag丢弃,准备读取下一个类
	}
	
	@Override
	//文档解析结束时,即读取到根标签的结束符时,运行
	public void endDocument() throws SAXException {
		System.out.println("---解析文档结束---");
	}

	public List<Person> getPersons() {
		return persons;
	}

	public void setPersons(List<Person> persons) {
		this.persons = persons;
	}
	
	
}

运行结果如下:
—解析文档开始—
persons–>解析开始
person–>解析开始
name–>解析开始
name–>解析结束
age–>解析开始
age–>解析结束
person–>解析结束
person–>解析开始
name–>解析开始
name–>解析结束
age–>解析开始
age–>解析结束
person–>解析结束
persons–>解析结束
—解析文档结束—
至尊宝–>9000
白晶晶–>600

猜你喜欢

转载自blog.csdn.net/HC199854/article/details/105874455