XML文档最基本的解析方式有两种,文档对象模型(DOM)和XML解析的简单API(SAX)
1,DOM解析
核心:
DOM解析是一种基于对象的API,它把XML的内容加载到内存中,生成一个与XML文档内容相对应的对象模型,这样根据树的结构,以结点形式来对文档进行操作。
过程:
使用DOM解析首先要一个DocumentBuilder对象,它可以通过pare(File  file)来解析一个XML文件,并返回该XML文件对应的Document对象。DocumentBuilder是一个抽象类,因而不能直接实例化,可以使用DocumentBuilderFactory构建一个DocumentBuilder对象。去的Document对象之后,就可以使用Document的各种方法来遍历整个XML内容了。
即:先用DocumentBuilderFactory构建一个DocumentBuilder对象,然后由DocumentBuilder通过parse得到一个Document对象,这样就可以使用了!!!
DocumentBuilderFactory:
构造方法摘要
protected
构造方法详细信息
用于阻止实例化的受保护构造方法。请使用 newInstance()。
DocumentBuilderFactory 的新实例。
DocumentBuilder:
Document 对象。
Document 对象。
InputStream 的内容解析为一个 XML 文档,并且返回一个新的 DOM Document 对象。
abstract  Document
Document
对象的一个新实例来生成一个 DOM 树。
Document:
DocumentType)。
Element。
Element 的
NodeList。
下面我们来看一个示例程序:先初始化一个XML文件,然后使用DOM对象来解析这个XML文件,初始化XML文件之后会把这个文件路径打印出来,可以找到这个文件,看一下XML文件的结果,然后从运行结果看DOM解析的结果。
package com.book.ch15.xml;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/*涉及到的类:DocumentBuilderFactory,DocumentBuilder,Document,
* Element,NodeList,Node,都是在xml解析中常用到的类*/
public class DOMTest {
//初始化一个XML文件
public static void initFile(File xmlFile) throws IOException {
StringBuffer buffer = new StringBuffer();
buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>").append("\r\n");
buffer.append("").append("\r\n");
buffer.append("").append("\r\n");
buffer.append("").append("\r\n");
buffer.append("Ordm").append("\r\n");
buffer.append("Lin").append("\r\n");
buffer.append("
Reminder").append("\r\n"); 
 
buffer.append("
Don't forget me this weekend!").append("\r\n"); 
 
buffer.append("2007-4-1 12:00:00").append("\r\n");
buffer.append("").append("\r\n");
buffer.append("\r\n");
buffer.append("").append("\r\n");
buffer.append("Lin").append("\r\n");
buffer.append("Ordm").append("\r\n");
buffer.append("
Re: Reminder").append("\r\n"); 
 
buffer.append("
Ok. I will call you then. ").append("\r\n"); 
 
buffer.append("2007-4-1 12:31:25").append("\r\n");
buffer.append("").append("\r\n");
buffer.append("").append("\r\n");
FileOutputStream ous = null;
try{
ous = new FileOutputStream(xmlFile);
ous.write(buffer.toString().getBytes("UTF-8"));
ous.flush();
}catch(IOException e){
e.printStackTrace();
}finally{
if(ous != null){
ous.close();
}
}
}
//main方法,解析上述文件
public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException{
File file = new File("dom_test.xml");
initFile(file);//生成要解析的初始化xml文件
System.out.println("File: " + file.getAbsolutePath());
// 声明一个 DocumentBuilder. 抽象类,不能直接构建,可以通过 DocumentFactory 来构建。
DocumentBuilder builder = null;
// 声明一个 DocumentBuilderFactory. 这是一个单态模式
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
// 取得默认的 DocumentBuilder.
builder = builderFactory.newDocumentBuilder();
Document document = builder.parse(file);//注意一个Document的生成过程
Element root = document.getDocumentElement();//Element类!!!
System.out.println("根元素:" + root.getNodeName());
NodeList childNodes = root.getChildNodes();//第一层root的子节点,NodeList类!!!
for(int i=0; i
Node node = childNodes.item(i);//Node类!!!
if("note".equals(node.getNodeName())){
System.out.print("\r\n找到一条 Note 记录. ID: " + node.getAttributes().getNamedItem("ID").getNodeValue() + ". ");
if("true".equalsIgnoreCase(node.getAttributes().getNamedItem("hasRead").getNodeValue())){
System.out.println("\t已读");
}
else{
System.out.println("\t新邮件");
}
NodeList nodeDetail = node.getChildNodes();//继续遍历子节点
for(int j=0; j
Node detail = nodeDetail.item(j);
if("from".equals(detail.getNodeName())){
System.out.println("发信人: " + detail.getTextContent());
}
else if("to".equals(detail.getNodeName())){
System.out.println("收信人: " + detail.getTextContent());
}
else if("head".equals(detail.getNodeName())){
System.out.println("主题: " + detail.getTextContent());
}
else if("body".equals(detail.getNodeName())){
System.out.println("内容: " + detail.getTextContent());
}
else if("date".equals(detail.getNodeName())){
System.out.println("日期: " + detail.getTextContent());
}
}
}
}
}
}
初始化的xml文件:
version="1.0" encoding="UTF-8"?>
View Source for full doctype...)>
- 
- 
Ordm
Lin
2007-4-1 12:00:00
- 
Lin
Ordm
2007-4-1 12:31:25
结果:
File: E:\eclipse\workspace\JAVAbase\dom_test.xml
根元素:notes
找到一条 Note 记录. ID: 1.     已读
发信人: Ordm
收信人: Lin
主题: Reminder
内容: Don't forget me this weekend!
日期: 2007-4-1 12:00:00
找到一条 Note 记录. ID: 2.     新邮件
发信人: Lin
收信人: Ordm
主题: Re: Reminder
内容: Ok. I will call you then.
日期: 2007-4-1 12:31:25
2,SAX解析
SAX与DOM是两种功能差不多但是底层实现不太一样的解析方式。DOM在解析的时候会把整个xml文件全部映射为Document里的树状结构,换而言之,xml的每个元素,属性,文本,注释都在Document里有所体现,对于小的XML文件来说,这样处理还是比较方便的。但是遇到比较大的文件的时候,DOM的缺点就看出来了,它占用的内存比较大。而且查找速度也比较慢。
SAX就是针对这种情况出现的解决方案,SAX解析器对XML文档进行解析时,会从xml文档的开始位置进行解析,同时根据已经定义好的事件处理器,来决定当前解析的部分(元素,属性,或是元素内容)是否有必要记录并存储。
SAX解析使用SAXPaser,这也是一个抽象类,不能实例化,可以通过SAXParserFactory来构建一个实例,然后调用SAXParser的parse(File  f,DefaultHander  dh)来解析xml文档,第一个参数是要解析的xml文件,第二个参数是决定要处理什么样的元素和属性。该函数不返回Document对象,所有的处理过程都是在第二个参数里完成的。
DefaultHander 是一个默认的Hander,包含几个解析xml时触发的方法,不过默认是什么都不做,它需要继承然后覆盖它的方法,添加所需要的操作代码。
DefaultHander常用方法:
主要是要理解上面四种方法的含义和执行方式:
startDocument() 在文档开始处采取的操作
endDocument()在文档结束处采取的操作
startElement()在每个元素的开始处采取的操作
endElement()在每个元素结束处采取的操作
void
接收元素中字符数据的通知。
void
void
void
void
package com.book.ch15.xml;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
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;
public class SAXTest {
public static void initFile(File xmlFile) throws IOException{
DOMTest.initFile(xmlFile);//调用上一个程序的方法初始化要解析的xml文件
}
public static void main(String[] args) throws IOException, ParserConfigurationException, SAXException{
File file = new File("sax_test.xml");
initFile(file);
System.out.println("File: " + file.getAbsolutePath());
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();//注意一个parser的得到过程
parser.parse(file, new MyHandler());//所有解析的工作都放在DefaultHandler的子类MyHandler中了
}
}
class MyHandler extends DefaultHandler {
static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private String content;
public static void log(Object obj){
//System.out.println(dateFormat.format(new java.util.Date()) + " [" + MyHandler.class.getName() + "] " + obj);
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
content = new String(ch, start, length);
if(content.length() > 0){
//log("content: " + content);
}
}
@Override
public void endDocument() throws SAXException {
log("endDocument(); ");
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
//log("endElement(\"" + uri +"\", \"" + localName + "\", \"" + qName + "\"); \r\n");
if("from".equals(qName)){
System.out.println("发信人: " + content);
}
else if("to".equals(qName)){
System.out.println("收信人: " + content);
}
else if("head".equals(qName)){
System.out.println("标题: " + content);
}
else if("body".equals(qName)){
System.out.println("内容: " + content);
}
else if("date".equals(qName)){
System.out.println("日期: " + content);
}
}
@Override
public void startDocument() throws SAXException {
//log("startDocument(); ");
}
//@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
//log("startElement(\"" + uri + "\", \"" + localName + "\", \"" + qName + "\", " + attributes + "); ");
if("note".equals(qName)){
System.out.println("\r\n找到一条 note 记录:, ID: " + attributes.getValue("ID") + ". \t" +
("true".equals(attributes.getValue("hasRead")) ? "已读" : "新邮件" ));
}
}
}
结果:
File: E:\eclipse\workspace\JAVAbase\sax_test.xml
找到一条 note 记录:, ID: 1.     已读
发信人: Ordm
收信人: Lin
标题: Reminder
内容: Don't forget me this weekend!
日期: 2007-4-1 12:00:00
找到一条 note 记录:, ID: 2.     新邮件
发信人: Lin
收信人: Ordm
标题: Re: Reminder
内容: Ok. I will call you then.
日期: 2007-4-1 12:31:25
3,使用JDOM简化xml解析
JDOM的xml解析主要使用SAXBuilder,SAXBuilder类的parse(File  file)可以解析一个xml文件并返回一个JDOM的Document对象,这有点像前面的DOM解析,JDOM也有DOMBuilder类,不过这个DOMBuilder不解析xml文档,只负责把org.w3c.dom.Document和org.w3c.dom.Element对象转org.jdom.Document和org.jdom.Element。
JDom解析一个xml文档比较简单,只需要Document document = new SAXBuilder(“jdom.xml”);这句话就把xml文档封装成了Document对象,剩下的就只需要通过Document来取得自己需要的元素或者属性了。
package com.book.ch15.xml;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
public class JDOMTest {
//初始化一个xml,构建xml文件的形式是以document对象的形式,跟前面字符串缓存的形式大不一样
public static void initXML(File xmlFile) throws IOException {
Document document = new Document();
Element rootElement = new Element("notes");
{
Element note = new Element("note");
note.setAttribute("hasRead", "true");
note.setAttribute("ID", "1");
note.addContent(new Element("from").setText("Ordm"));
note.addContent(new Element("to").setText("Lin"));
note.addContent(new Element("head").setText("Reminder"));
note.addContent(new Element("body").setText("Don't forget me this weekend"));
note.addContent(new Element("date").setText("2007-4-1 12:00:00"));
rootElement.addContent(note);
}
{
Element note = new Element("note");
note.setAttribute("hasRead", "false");
note.setAttribute("ID", "2");
note.addContent(new Element("from").setText("Lin"));
note.addContent(new Element("to").setText("Ordm"));
note.addContent(new Element("head").setText("Re: Reminder"));
note.addContent(new Element("body").setText("Ok. I will call you then. "));
note.addContent(new Element("date").setText("2007-4-1 12:31:25"));
rootElement.addContent(note);
}
document.setRootElement(rootElement);
XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
outputter.output(document, new FileOutputStream(xmlFile));//将这个document对象输出为xml文件
}
public static void main(String[] args) throws JDOMException, IOException{
File file = new File("jdom_test.xml");
initXML(file);
System.out.println(file.getAbsolutePath());
//构建一个JDom的Document对象
SAXBuilder builder = new SAXBuilder();
Document document = builder.build(file);
Element rootElement = document.getRootElement();
List notes = rootElement.getChildren("note");//notes类型
for(Iterator it=notes.iterator(); it.hasNext(); ){
Element note = (Element)it.next();
System.out.println("\r\n找到一个 note 消息, ID: " + note.getAttributeValue("ID") + ". \t" +
("true".equals(note.getAttributeValue("hasRead")) ? "已读" : "新消息"));
List details = note.getChildren();
for(Iterator iterator=details.iterator(); iterator.hasNext(); ){
Element detail = (Element)iterator.next();
if("from".equals(detail.getName())){
System.out.println("发信人: " + detail.getTextTrim());
}
else if("to".equals(detail.getName())){
System.out.println("收信人: " + detail.getTextTrim());
}
else if("head".equals(detail.getName())){
System.out.println("标题: " + detail.getTextTrim());
}
else if("body".equals(detail.getName())){
System.out.println("内容: " + detail.getTextTrim());
}
else if("date".equals(detail.getName())){
System.out.println("日期: " + detail.getTextTrim());
}
}
}
}
}