java编程笔记20 XML开发简介

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 DocumentBuilderFactory()
          用于阻止实例化的受保护构造方法。
构造方法详细信息

用于阻止实例化的受保护构造方法。请使用 newInstance()

static DocumentBuilderFactory newInstance()
          获取 DocumentBuilderFactory 的新实例。
abstract  DocumentBuilder newDocumentBuilder()
          使用当前配置的参数创建一个新的 DocumentBuilder 实例。

DocumentBuilder:

 Document parse(File f)
          将给定文件的内容解析为一个 XML 文档,并且返回一个新的 DOM Document 对象。
 Document parse(String uri)
          将给定 URI 的内容解析为一个 XML 文档,并且返回一个新的 DOM Document 对象。
Document parse(InputStream is)
          将给定 InputStream 的内容解析为一个 XML 文档,并且返回一个新的 DOM Document 对象。
abstract  Document newDocument()
          获取 DOM Document 对象的一个新实例来生成一个 DOM 树。
abstract  DOMImplementation getDOMImplementation()
          获取 DOMImplementation 对象的一个实例。
 Schema getSchema()
          获取由 XML 处理器使用的 Schema 的引用。

Document:

 DocumentType getDoctype()
          与此文档相关的文档类型声明(参见 DocumentType)。
 Element getDocumentElement()
          这是一种便捷属性,该属性允许直接访问文档的文档元素的子节点。
Element getElementById(String elementId)
          返回具有带给定值的 ID 属性的 Element
 NodeList getElementsByTagName(String tagname)
          按文档顺序返回包含在文档中且具有给定标记名称的所有 ElementNodeList
 Attr createAttributeNS(String namespaceURI, String qualifiedName)
          创建给定的限定名称和名称空间 URI 的属性。
 CDATASection createCDATASection(String data)
          创建其值为指定字符串的 CDATASection 节点。
 Element createElement(String tagName)
          创建指定类型的元素。
 Text createTextNode(String data)
          创建给定指定字符串的 Text 节点。

下面我们来看一个示例程序:先初始化一个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("<!DOCTYPE notes>").append("\r\n");
		buffer.append("<notes>").append("\r\n");
		buffer.append("	<note hasRead=\"true\" ID=\"1\">").append("\r\n");
		buffer.append("		<from>Ordm</from>").append("\r\n");
		buffer.append("		<to>Lin</to>").append("\r\n");
		buffer.append("		<head>Reminder</head>").append("\r\n");
		buffer.append("		<body>Don't forget me this weekend!</body>").append("\r\n");
		buffer.append("		<date>2007-4-1 12:00:00</date>").append("\r\n");
		buffer.append("	</note>").append("\r\n");
		buffer.append("\r\n");
		buffer.append("	<note hasRead=\"false\" ID=\"2\">").append("\r\n");
		buffer.append("		<from>Lin</from>").append("\r\n");
		buffer.append("		<to>Ordm</to>").append("\r\n");
		buffer.append("		<head>Re: Reminder</head>").append("\r\n");
		buffer.append("		<body>Ok. I will call you then. </body>").append("\r\n");
		buffer.append("		<date>2007-4-1 12:31:25</date>").append("\r\n");
		buffer.append("	</note>").append("\r\n");
		buffer.append("</notes>").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<childNodes.getLength(); 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<nodeDetail.getLength(); 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文件:

  <?xml version="1.0" encoding="UTF-8" ?>
  <!DOCTYPE notes (View Source for full doctype...)>
- <notes>
- <note hasRead="true" ID="1">
  <from>Ordm</from>
  <to>Lin</to>
  <head>Reminder</head>
  <body>Don't forget me this weekend!</body>
  <date>2007-4-1 12:00:00</date>
  </note>
- <note hasRead="false" ID="2">
  <from>Lin</from>
  <to>Ordm</to>
  <head>Re: Reminder</head>
  <body>Ok. I will call you then.</body>
  <date>2007-4-1 12:31:25</date>
  </note>
  </notes>
结果:
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 characters(char[] ch, int start, int length)
          接收元素中字符数据的通知。
 void endDocument()
          接收文档结束的通知。
 void endElement(String uri, String localName, String qName)
          接收元素结束的通知。
 void startDocument()
          接收文档开始的通知。
 void startElement(String uri, String localName, String qName, Attributes attributes)
          接收元素开始的通知。
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());
				}
			}
			
		}
		
	}
	
}

posted @ 2011-03-20 20:49  jinmengzhe  阅读(657)  评论(0编辑  收藏  举报