DOM:文档驱动。DOM在解析文件之前把整个文档装入内存,处理大型文件时其性能很差,是由于DOM的树结构所造成的,此结构占用的内存较多。
SAX:事件驱动型的XML解析方式。顺序读取XML文件,不需要一次全部装载整个文件。当遇到像文件开头,文档结束,或者标签开头与标签结束时,会触发一个事件,用户通过在其回调事件中写入处理代码来处理XML文件,适合对XML的顺序访问,且是只读的
StAX采用流模型中的拉模型分析方式。提供基于指针和基于迭代器两种方式的支持。
优点: 1、接口简单,使用方便。 2、采用流模型分析方式,有较好的性能。
缺点: 1、单向导航,不支持XPath,很难同时访问同一文档的不同部分。
DOM解析:
一、DOM4j中,获得Document对象的方式有三种:
1.读取XML文件,获得document对象
SAXReader reader = new SAXReader();
Document document = reader.read(new File("csdn.xml"));
2.解析XML形式的文本,得到document对象.
String text = "<csdn></csdn>";
Document document = DocumentHelper.parseText(text);
3.主动创建document对象.
Document document = DocumentHelper.createDocument(); //创建根节点
Element root = document.addElement("csdn");
二、节点对象操作的方法:
1.获取文档的根节点.
Element root = document.getRootElement();
2.取得某个节点的子节点.
Element element=node.element(“四大名著");
3.取得节点的文字
String text=node.getText();
4.取得某节点下所有名为“csdn”的子节点,并进行遍历.
List nodes = rootElm.elements("csdn");
for (Iterator it = nodes.iterator(); it.hasNext();) {
Element elm = (Element) it.next();
// do something
}
5.对某节点下的所有子节点进行遍历.
for(Iterator it=root.elementIterator();it.hasNext();){
Element element = (Element) it.next();
// do something
}
6.在某节点下添加子节点
Element elm = newElm.addElement("朝代");
7.设置节点文字. elm.setText("明朝");
8.删除某节点.//childElement是待删除的节点,parentElement是其父节点 parentElement.remove(childElment);
9.添加一个CDATA节点.Element contentElm = infoElm.addElement("content");contentElm.addCDATA(“cdata区域”);
三、将文档写入XML文件
1.文档中全为英文,不设置编码,直接写入的形式.
XMLWriter writer = new XMLWriter(new FileWriter("ot.xml"));
writer.write(document);
writer.close();
2.文档中含有中文,设置编码格式写入的形式.
OutputFormat format = OutputFormat.createPrettyPrint();// 创建文件输出的时候,自动缩进的格式
format.setEncoding("UTF-8");//设置编码
XMLWriter writer = new XMLWriter(newFileWriter("output.xml"),format);
writer.write(document);
writer.close();
四、字符串与XML的转换
1.将字符串转化为XML
String text = "<csdn> <java>Java班</java></csdn>";
Document document = DocumentHelper.parseText(text);
2.将文档或节点的XML转化为字符串.
SAXReader reader = new SAXReader();
Document document = reader.read(new File("csdn.xml"));
Element root=document.getRootElement();
String docXmlText=document.asXML();
String rootXmlText=root.asXML();
Element memberElm=root.element("csdn");
String memberXmlText=memberElm.asXML();
dom4j解析示例:
package dom4j;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.util.Iterator;
import java.util.List;
import org.dom4j.Attribute;
import org.dom4j.Document;
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 Demo01 {
@Test
public void test() throws Exception {
// 创建saxReader对象
SAXReader reader = new SAXReader();
// 通过read方法读取一个文件 转换成Document对象
Document document = reader.read(new File("src/dom4j/sida.xml"));
//获取根节点元素对象
Element node = document.getRootElement();
//遍历所有的元素节点
listNodes(node);
// 获取四大名著元素节点中,子节点名称为红楼梦元素节点。
Element element = node.element("红楼梦");
//获取element的id属性节点对象
Attribute attr = element.attribute("id");
//删除属性
element.remove(attr);
//添加新的属性
element.addAttribute("name", "作者");
// 在红楼梦元素节点中添加朝代元素的节点
Element newElement = element.addElement("朝代");
newElement.setText("清朝");
//获取element中的作者元素节点对象
Element author = element.element("作者");
//删除元素节点
boolean flag = element.remove(author);
//返回true代码删除成功,否则失败
System.out.println(flag);
//添加CDATA区域
element.addCDATA("红楼梦,是一部爱情小说.");
// 写入到一个新的文件中
writer(document);
}
/**
* 把document对象写入新的文件
*
* @param document
* @throws Exception
*/
public void writer(Document document) throws Exception {
// 紧凑的格式
// OutputFormat format = OutputFormat.createCompactFormat();
// 排版缩进的格式
OutputFormat format = OutputFormat.createPrettyPrint();
// 设置编码
format.setEncoding("UTF-8");
// 创建XMLWriter对象,指定了写出文件及编码格式
// XMLWriter writer = new XMLWriter(new FileWriter(new
// File("src//a.xml")),format);
XMLWriter writer = new XMLWriter(new OutputStreamWriter(
new FileOutputStream(new File("src//a.xml")), "UTF-8"), format);
// 写入
writer.write(document);
// 立即写入
writer.flush();
// 关闭操作
writer.close();
}
/**
* 遍历当前节点元素下面的所有(元素的)子节点
*
* @param node
*/
public void listNodes(Element node) {
System.out.println("当前节点的名称::" + node.getName());
// 获取当前节点的所有属性节点
List<Attribute> list = node.attributes();
// 遍历属性节点
for (Attribute attr : list) {
System.out.println(attr.getText() + "-----" + attr.getName()
+ "---" + attr.getValue());
}
if (!(node.getTextTrim().equals(""))) {
System.out.println("文本内容::::" + node.getText());
}
// 当前节点下面子节点迭代器
Iterator<Element> it = node.elementIterator();
// 遍历
while (it.hasNext()) {
// 获取某个子节点对象
Element e = it.next();
// 对子节点进行遍历
listNodes(e);
}
}
/**
* 介绍Element中的element方法和elements方法的使用
*
* @param node
*/
public void elementMethod(Element node) {
// 获取node节点中,子节点的元素名称为西游记的元素节点。
Element e = node.element("西游记");
// 获取西游记元素节点中,子节点为作者的元素节点(可以看到只能获取第一个作者元素节点)
Element author = e.element("作者");
System.out.println(e.getName() + "----" + author.getText());
// 获取西游记这个元素节点 中,所有子节点名称为作者元素的节点 。
List<Element> authors = e.elements("作者");
for (Element aut : authors) {
System.out.println(aut.getText());
}
// 获取西游记这个元素节点 所有元素的子节点。
List<Element> elements = e.elements();
for (Element el : elements) {
System.out.println(el.getText());
}
}
}
SAX解析:
主要是要复写DefaultHandler类,然后在类中调用即可
package saxXml;
import java.io.IOException;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
public class SAXxml {
public static void main(String[] args) throws ParserConfigurationException, SAXException{
//创建解析工厂
SAXParserFactory factory=SAXParserFactory.newInstance();
//得到解析器
SAXParser parse=factory.newSAXParser();
//得到读取器
XMLReader reader= parse.getXMLReader();
//设置内容处理器
BeanListHandler beanListHandler=new BeanListHandler();
reader.setContentHandler(beanListHandler);
//读取文档内容:
try {
reader.parse("src/saxXml/bookXml.xml");
//reader.parse("\\src\\saxXml\\bookXml.xml");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
List<Book> list= beanListHandler.getBooks();
System.out.println("list 数量"+list.size());
//遍历获取取得的内容
for(int i=0;i<list.size();i++){
System.out.println(i);
Book book=list.get(i);
System.out.print("name:"+book.getName());
System.out.print("author"+book.getAuthor());
System.out.print("price"+book.getPrice());
System.out.println();
}
}
}
BeanListHandler类:
package saxXml;
import java.util.ArrayList;
import java.util.List;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
//将XML中的每本书封装到Book中
public class BeanListHandler extends DefaultHandler{
private List books=new ArrayList();
private String currentTag;
private Book book;
public List getBooks(){
return books;
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
System.out.println("字符串"+currentTag+new String(ch,start,length)+";");
if("name".equals(currentTag)){
book.setName(new String(ch,start,length));
book.getName();
// System.out.println("姓名");
// System.out.println("tag:"+book.getName());
}
if("author".equals(currentTag)){
book.setAuthor(new String(ch,start,length));
}
if("price".equals(currentTag)){
book.setPrice(new String(ch,start,length));
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if(qName.equals("book")){
books.add(book);
System.out.println("name:"+book.getName());
book=null;
}
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
//+uri+";"+localName+";" +attributes
currentTag=qName;
System.out.println("startElement:"+qName+";"+currentTag);
if("book".equals(qName)){
book=new Book();
System.out.println("start");
}
}
}
XML文件:
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book>
<name>java</name>
<author>minyi</author>
<price>cpp</price>
</book>
<book>
<name>c++</name>
<author>zhouhui</author>
<price>stl</price>
</book>
</bookstore>
STAX解析:
SAX也是基于事件处理xml文档,但却是用推模式解析,解析器解析完整个xml文档后,才产生解析事件,然后推给程序去处理这些事件。SAX中解析器是工作主体,而事件处理器是由解析器驱动的,如果解析文档过程中产生问题,则剩余的所有文档就无法处理。
StAX使用拉模式,解析器首先将XML文档所有的事件全部取出,然后通过处理程序处理这些事件。StAX中处理器是工作主体,如果解析文档过程中产生问题,只会影响到出问题的部分,其余部分处理不受影响
package staxXml;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Date;
import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartDocument;
import javax.xml.stream.events.XMLEvent;
public class Scheduler {
private static final String TAG_ITEM = "item";
private static final String TAG_TASK = "task";
private static final String TAG_STRATEGY = "strategy";
private static final String STRATEGE_REPEAT = "repeat";
private static final String STRATEGE_DAILY = "daily";
private static final String TAG_REPEATFREQ = "repeatFreq";
private static final String TAG_DAILYRUNTIME = "dailyRuntime";
void readConfig(){
//创建解析工厂
XMLInputFactory inputFactory= XMLInputFactory.newInstance();
inputFactory.setProperty("javax.xml.stream.isCoalescing", true);//避免读取多行数据时出现问题
//简历一个新的eventReader
InputStream in = new FileInputStream(Global.SERVICE_CONFIGURE_FILE);
XMLEventReader eventReader = inputFactory.createXMLEventReader(in);
// One specification
String task = null;
String strategy = null;
Integer freq = null;// by second
// for daily job
Date firstTime = null;
Calendar calendar = Calendar.getInstance();
while(eventReader.hasNext()){
XMLEvent event=(XMLEvent) eventReader.next();
//判断其实开始还是结束标签
if(event.isStartElement()){
StartDocument startElement= (StartDocument) event.asStartElement();
//判断其是哪个标签
if (((EndElement) startElement).getName().getLocalPart().equals(TAG_ITEM)) {
/*
Iterator<Attribute> attributes = startElement.getAttributes();
while (attributes.hasNext()) {
attributes.next();
// skip
}
*/
}
if (event.asStartElement().getName().getLocalPart().equals(TAG_TASK)) {
event = eventReader.nextEvent();
task = event.asCharacters().getData();
continue;
}
if (event.asStartElement().getName().getLocalPart().equals(TAG_STRATEGY)) {
event = eventReader.nextEvent();
strategy = event.asCharacters().getData();
continue;
}
if (event.asStartElement().getName().getLocalPart().equals(TAG_REPEATFREQ)) {
event = eventReader.nextEvent();
freq = Integer.parseInt(event.asCharacters().getData());
continue;
}
if (event.asStartElement().getName().getLocalPart().equals(TAG_DAILYRUNTIME)) {
event = eventReader.nextEvent();
// hour:min:sec
Scanner scanner = new Scanner(event.asCharacters().getData());
scanner.useDelimiter(":");
int hour = scanner.nextInt();
int minute = scanner.nextInt();
int second = scanner.nextInt();
// firstTime (today)
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, second);
firstTime = calendar.getTime();
continue;
}
}
//如果是结束标签
if(event.isEndElement()){
EndElement endElement=event.asEndElement();
if(endElement.getName().getLocalPart().equals(TAG_ITEM)){
Timer timer=new Timer();
if(strategy.equals(STRATEGE_REPEAT)) {
Class<?> clz = Class.forName(Global.TASK_PACKAGE_PREFIX + task);
TimerTask ctr = (TimerTask)clz.newInstance();
timer.schedule(ctr, 0, freq*1000);
} else if(strategy.equals(STRATEGE_DAILY)){
Class<?> clz = Class.forName(Global.TASK_PACKAGE_PREFIX + task);
TimerTask ctr = (TimerTask)clz.newInstance();
timer.schedule(ctr, firstTime, Global.PERIOD_DAY);
} else {
_logger.error("Unexpected configuration option "+ strategy +" in " + Global.SERVICE_CONFIGURE_FILE);
}
}
}
}
}
}
参考文章:
dom4j: http://blog.youkuaiyun.com/redarmy_chen/article/details/12969219
stax: http://blog.youkuaiyun.com/chjttony/article/details/6125123
http://blog.youkuaiyun.com/ro_wsy/article/details/8246882