这里讲解xml的两种解析方式:dom解析和sax解析。
1.简要说明
(1)将整个XML使用类似树的结构保存在内存中,再对其进行操作。
(2)是 W3C 组织推荐的处理 XML 的一种方式。
(3)需要等到XML完全加载进内存才可以进行操作。
(4)缺点:解析过程比较慢,需要将整个文档都解析完成后才能进行操作,耗费内存,当解析超大的XML时慎用。
(5)优点:可以方便的对xml进行增删该查操作;只需解析一次拿到dom对象后可以重复使用对象减少解析次数。
sax解析
(1)逐行扫描XML文档,当遇到标签时触发解析处理器,采用事件处理的方式解析xml。
(2)(Simple API for XML) 不是官方标准,但它是 XML 社区事实上的标准,几乎所有的 XML 解析器都支持它。
(3)在读取文档的同时即可对xml进行处理,不必等到文档加载结束,相对快捷
(4)优点:不需要加载进内存,因此不存在占用内存的问题,可以解析超大XML
(5)缺点:只能用来读取XML中数据,无法进行增删改
基于这两种解析思想市面上就有了很多的解析api:
(1)sun jaxp 既有dom方式也有sax方式,并且这套解析api已经加入到j2se的规范中,意味这不需要导入任何第三方开发包就可以直接使用这种解析方式.但是这种解析方式效率低下,没什么人用.
(2)dom4j 可以使用dom方式高效的解析xml.
(3)pull Android开发里面会用的。
注:(1)使用dom4j开发包:(文件名:dom4j-1.6.1.jar)
(2)导入开发包,通常只需要导入核心包(dom4j-1.6.1.jar)就可以了,如果在使用的过程中提示少什么包到lib目录下在导入缺少的包即可。
(3)导入过程:
①在java工程中新建”lib“文件夹;
②copy包到此文件夹中;
③右键此包,选择"Build Path"→”Add to path“即可。
2.java代码示例
public class SaxDemo1 {
public static void main(String[] args) throws Exception {
// 1.获取解析器工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
// 2.通过工厂获取sax解析器
SAXParser parser = factory.newSAXParser();
// 3.获取读取器
XMLReader reader = parser.getXMLReader();
// 4.注册事件处理器 设置读取器的事件处理器
reader.setContentHandler(new MyContentHandler2());
// 5.解析xml
reader.parse("book.xml");
}
}
// 适配器模式
//DefaultHandler是一个类,他默认实现了ContentHandler接口,
//并提供了其中所有方法的空实现,我们可以自己写一个类继承这个类,复写其中我们需要使用到的方法。就不必实现所有的方法了,好用!!!
class MyContentHandler2 extends DefaultHandler {
private String eleName = null;
private int count = 0;
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
this.eleName = qName;
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if ("书名".equals(eleName)&& (++count==2)) { //打印第二本书名
System.out.println(new String(ch, start, length));
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
this.eleName= null;
}
}
class MyContentHandler implements ContentHandler {
//我们需要实现ContentHandler所有方法
@Override
public void startDocument() throws SAXException {
System.out.println("文档解析开始了.........");
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes atts) throws SAXException {
System.out.println("发现了开始标签:" + qName);
}
@Override
public void characters(char[] ch, int start, int length) //char[] ch指的是整个文档,不是当前这个字符数组。
throws SAXException {
System.out.println(new String(ch, start, length));
}
@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("文档解析结束了.........");
}
@Override
public void endPrefixMapping(String prefix) throws SAXException {
}
@Override
public void ignorableWhitespace(char[] ch, int start, int length)
throws SAXException {
}
@Override
public void processingInstruction(String target, String data)
throws SAXException {
}
@Override
public void setDocumentLocator(Locator locator) {
}
@Override
public void skippedEntity(String name) throws SAXException {
}
@Override
public void startPrefixMapping(String prefix, String uri)
throws SAXException {
}
}
dom解析(使用了dom4j)
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.List;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.junit.Test;
public class Dom4jDemo2 {
//改
@Test
public void update() throws Exception{
SAXReader reader = new SAXReader();
Document dom = reader.read("book.xml");
Element root = dom.getRootElement();
root.element("书").element("特价").setText("24.99");
XMLWriter writer = new XMLWriter(new FileOutputStream("book.xml"), OutputFormat.createPrettyPrint());
writer.write(dom);
writer.close();
}
//增加
@Test
public void add() throws Exception {
//1.获取dom4j解析器
SAXReader reader = new SAXReader();
//2.获取document对象dom
Document dom = reader.read("book.xml");
//3.获取根节点对象
Element root = dom.getRootElement();
//4.凭空创建节点<特价>,并设置标签体内容
Element newPrice = DocumentHelper.createElement("特价");
newPrice.setText("25.00");
root.element("书").add(newPrice);
//将内存中的dom树写到xml文件中。从而使其数据更新。
/*①第一种方法
FileWriter fw = new FileWriter("book.xml");
dom.write(fw);
fw.flush();
fw.close();*/
//②第二种方法
XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("book.xml"), OutputFormat.createPrettyPrint());
xmlWriter.write(dom);
xmlWriter.close();
}
//查询第二本书的名字
@Test
public void find() throws Exception {
SAXReader reader = new SAXReader();
Document dom = reader.read("book.xml");
Element root = dom.getRootElement();
List<Element> list = root.elements();
Element book2Ele = list.get(1);
System.out.println(book2Ele.element("书名").getText());
}
//删除
@Test
public void delete() throws Exception{
SAXReader reader = new SAXReader();
Document dom = reader.read("book.xml");
Element root = dom.getRootElement();
Element newPrice = root.element("书").element("特价");
newPrice.getParent().remove(newPrice);
XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("book.xml"), OutputFormat.createPrettyPrint());
xmlWriter.write(dom);
xmlWriter.close();
}
//对属性的操作
@Test
public void attributeTest() throws Exception{
SAXReader reader = new SAXReader();
Document dom = reader.read("book.xml");
Element root = dom.getRootElement();
//****************增加属性********************************************
/*
List<Element> bookName = root.elements("书");
//给第二本书增加属性
bookName.get(1).addAttribute("出版社", "北京大学出版社");
//给第二本书的“书名”增加属性
bookName.get(1).element("书名").addAttribute("语言", "中文");
*/
//*******************************************************************
//****************查询属性********************************************
/*
List<Element> bookName = root.elements("书");
//查询第二本书出版社属性
String publisherText = bookName.get(1).attribute("出版社").getText();
System.out.println(publisherText);
*/
//*******************************************************************
//****************更新属性********************************************
/*
List<Element> bookName = root.elements("书");
//修改第二本书出版社属性
bookName.get(1).attribute("出版社").setText("人民教育出版社");
*/
//*******************************************************************
//****************删除属性********************************************
List<Element> bookName = root.elements("书");
//删除第二本书出版社属性
Attribute publisher = bookName.get(1).attribute("出版社");
publisher.getParent().remove(publisher);
//*******************************************************************
XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("book.xml"), OutputFormat.createPrettyPrint());
xmlWriter.write(dom);
xmlWriter.close();
}
}