xml的四种解析方法及源代码(SAX、DOM、JDOM、DOM4J)
第一种:SAX解析
SAX处理机制:SAX是一种基于事件驱动的API。利用SAX解析XML文档,牵涉到两个部分:解析器和事件处理器。解析器负责读取XML文档,并向事件处理器发生事件,如元素开始和元素结束事件;而事件处理器则负责对事件做出响应,对传递的XML数据进行处理。
测试用的xml文件db.xml
1<?xml version="1.0" encoding="UTF-8"?>
2<!--<!DOCTYPE dbconfig SYSTEM "db.dtd">-->
3<dbconfig>
4 <db type="oracle">
5 <driver>oracle.jdbc.driver.OracleDriver</driver>
6 <url>jdbc:oracle:thin:@localhost:1521:oracle</url>
7 <user>scott</user>
8 <password>tiger</password>
9 </db>
10</dbconfig>
DTD文件db.dtd
1<!ELEMENT dbconfig (db+)>
2<!ELEMENT db (driver,url,user,password)>
3<!ELEMENT driver (#PCDATA)>
4<!ELEMENT url (#PCDATA)>
5<!ELEMENT user (#PCDATA)>
6<!ELEMENT password (#PCDATA)>
7<!ATTLIST db type CDATA #REQUIRED>
SAX解析实例一
org.xml.sax.DefalutHandler类: 可以扩展该类,给出自己的解析实现
SAXPrinter.java
1import java.io.File;
2
3import javax.xml.parsers.SAXParser;
4import javax.xml.parsers.SAXParserFactory;
5
6import org.xml.sax.Attributes;
7import org.xml.sax.SAXException;
8import org.xml.sax.helpers.DefaultHandler;
9
10public class SAXPrinter extends DefaultHandler
11{
12
13 /** *//**
14 * 文档开始事件
15 */
16 public void startDocument() throws SAXException
17 {
18 System.out.println("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
19 }
20
21 /** *//**
22 * 接收处理指令事件
23 */
24 public void processingInstruction(String target, String data) throws SAXException
25 {
26 System.out.println("<?"+target+" "+data+"?>");
27 }
28
29 /** *//**
30 * 元素开始事件
31 * 参数说明:
32 * uri - 名称空间 URI,如果元素没有任何名称空间 URI,或者没有正在执行名称空间处理,则为空字符串。
33 * localName - 本地名称(不带前缀),如果没有正在执行名称空间处理,则为空字符串。
34 * qName - 限定的名称(带有前缀),如果限定的名称不可用,则为空字符串。
35 * attributes - 附加到元素的属性。如果没有属性,则它将是空的 Attributes 对象。
36 */
37 public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException
38 {
39 System.out.print("<"+qName);//输出元素名称
40 int len=attrs.getLength();//元素属性列表长度
41
42 //利用循环输出属性列表
43 for(int i=0;i<len;i++)
44 {
45 System.out.print(" ");
46 System.out.print(attrs.getQName(i));
47 System.out.print("=\"");
48 System.out.print(attrs.getValue(i));
49 System.out.print("\"");
50 }
51 System.out.print(">");
52 }
53
54 /** *//**
55 * 元素中字符数据事件:接收元素中字符数据
56 * 注意:1.应用程序不要试图读取ch数组指定范围外的数据,(即start至length之外)
57 * 2.有些解析器将使用ignorableWhitespace()方法来报告元素内容中的空白,而不是characters()方法,如:进行有效性验证的解析器
58 */
59 public void characters(char[] ch, int start, int length) throws SAXException
60 {
61 System.out.print(new String(ch,start,length));
62 }
63
64 /** *//**
65 * 结束元素事件
66 */
67 public void endElement(String uri, String localName, String qName) throws SAXException
68 {
69 System.out.print("</"+qName+">");
70 }
71
72 public static void main(String[] args)
73 {
74 SAXParserFactory spf=SAXParserFactory.newInstance();
75
76 try
77 {
78 SAXParser sp=spf.newSAXParser();
79 sp.parse(new File("db.xml"),new SAXPrinter());
80 }
81 catch (Exception e)
82 {
83 e.printStackTrace();
84 }
85 }
86}
SAX解析实例二
org.xml.sax.ContentHandler接口: 通过实现该接口给出自己的解析实现。
org.xml.sax.ErrorHandler接口:如果SAX应用程序需要实现定制的错误处理,那么它必须实现这个接口,并调用XMLReader对象的setErrorHandler()方法向解析器注册异常处理实例,这样,解析器将通过这个接口报告所有的错误和警告。
ContentHandlerImpl.java
1import org.xml.sax.Attributes;
2import org.xml.sax.ContentHandler;
3import org.xml.sax.Locator;
4import org.xml.sax.SAXException;
5
6public class ContentHandlerImpl implements ContentHandler
7{
8 /** *//**
9 * 文档开始事件
10 */
11 public void startDocument() throws SAXException
12 {
13 System.out.println("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
14 }
15
16 /** *//**
17 * 接收处理指令事件
18 */
19 public void processingInstruction(String target, String data) throws SAXException
20 {
21 System.out.println("<?"+target+" "+data+"?>");
22 }
23
24 /** *//**
25 * 元素开始事件
26 * 参数说明:
27 * uri - 名称空间 URI,如果元素没有任何名称空间 URI,或者没有正在执行名称空间处理,则为空字符串。
28 * localName - 本地名称(不带前缀),如果没有正在执行名称空间处理,则为空字符串。
29 * qName - 限定的名称(带有前缀),如果限定的名称不可用,则为空字符串。
30 * attributes - 附加到元素的属性。如果没有属性,则它将是空的 Attributes 对象。
31 */
32 public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException
33 {
34 System.out.print("<"+qName);//输出元素名称
35 int len=attrs.getLength();//元素属性列表长度
36
37 //利用循环输出属性列表
38 for(int i=0;i<len;i++)
39 {
40 System.out.print(" ");
41 System.out.print(attrs.getQName(i));
42 System.out.print("=\"");
43 System.out.print(attrs.getValue(i));
44 System.out.print("\"");
45 }
46 System.out.print(">");
47 }
48
49 /** *//**
50 * 元素中字符数据事件:接收元素中字符数据
51 * 注意:1.应用程序不要试图读取ch数组指定范围外的数据,(即start至length之外)
52 * 2.有些解析器将使用ignorableWhitespace()方法来报告元素内容中的空白,而不是characters()方法,如:进行有效性验证的解析器
53 */
54 public void characters(char[] ch, int start, int length) throws SAXException
55 {
56 System.out.print(new String(ch,start,length));
57 }
58
59 /** *//**
60 * 结束元素事件
61 */
62 public void endElement(String uri, String localName, String qName) throws SAXException
63 {
64 System.out.print("</"+qName+">");
65 }
66
67 public void endDocument() throws SAXException
68 {
69
70 }
71
72 public void endPrefixMapping(String prefix) throws SAXException
73 {
74
75 }
76
77 public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException
78 {
79
80 }
81
82 public void setDocumentLocator(Locator locator)
83 {
84
85 }
86
87 public void skippedEntity(String name) throws SAXException
88 {
89
90 }
91
92 public void startPrefixMapping(String prefix, String uri) throws SAXException
93 {
94
95 }
96
97}
ErrorHandlerImpl.java
1public class ErrorHandlerImpl implements ErrorHandler
2{
3
4 public void warning(SAXParseException e) throws SAXException
5 {
6 System.out.println("[Warning ]"+getLocationString(e)+":"+e.getMessage());
7 }
8
9 public void error(SAXParseException e) throws SAXException
10 {
11 System.out.println("[Error ]"+getLocationString(e)+":"+e.getMessage());
12 }
13
14 public void fatalError(SAXParseException e) throws SAXException
15 {
16 System.out.println("[Fatal Error ]"+getLocationString(e)+":"+e.getMessage());
17 }
18
19 private String getLocationString(SAXParseException e)
20 {
21 StringBuffer sb=new StringBuffer();
22 String publicId=e.getPublicId();
23 if(publicId!=null)
24 {
25 sb.append(publicId);
26 sb.append(" ");
27 }
28
29 String systemId=e.getSystemId();
30 if(systemId!=null)
31 {
32 sb.append(systemId);
33 sb.append(" ");
34 }
35
36 sb.append(e.getLineNumber());
37 sb.append(":");
38 sb.append(e.getColumnNumber());
39 return sb.toString();
40 }
41}
SaxParserTest.java
1import java.io.FileInputStream;
2
3import org.xml.sax.InputSource;
4import org.xml.sax.XMLReader;
5import org.xml.sax.helpers.XMLReaderFactory;
6
7public class SaxParserTest
8{
9 public static void main(String[] args)
10 {
11 try
12 {
13 XMLReader xmlReader=XMLReaderFactory.createXMLReader();
14 //关闭或打开验证
15 xmlReader.setFeature("http://xml.org/sax/features/validation",true);
16 //注册事件处理器
17 xmlReader.setContentHandler(new ContentHandlerImpl());
18 //注册异常处理器
19 xmlReader.setErrorHandler(new ErrorHandlerImpl());
20
21 xmlReader.parse(new InputSource(new FileInputStream("saxdb.xml")));
22 } catch (Exception e)
23 {
24 System.out.println(e.getMessage());
25 }
26 }
27}
第二种:DOM解析
DOM中的核心概念就是节点。DOM在分析XML文档时,将将组成XML文档的各个部分(元素、属性、文本、注释、处理指令等)映射为一个对象(节点)。在内存中,这些节点形成一课文档树。整棵树是一个节点,树中的每一个节点也是一棵树(子树),可以说,DOM就是对这棵树的一个对象描述,我们通过访问树中的节点来存取XML文档的内容。
PS:属性节点是附属于元素的,不能被看做是元素的子节点,更不能作为一个单独的节点DOMPrinter.java
1import org.w3c.dom.Document;
2import org.w3c.dom.NamedNodeMap;
3import org.w3c.dom.Node;
4
5import com.sun.org.apache.xerces.internal.parsers.DOMParser;
6
7public class DOMPrinter
8{
9 public static void main(String[] args)
10 {
11 try
12 {
13 /** *//** 获取Document对象 */
14 DOMParser parser = new DOMParser();
15 parser.parse("db.xml");
16 Document document = parser.getDocument();
17 printNode(document);
18 } catch (Exception e)
19 {
20 e.printStackTrace();
21 }
22 }
23
24 public static void printNode(Node node)
25 {
26 short nodeType=node.getNodeType();
27 switch(nodeType)
28 {
29 case Node.PROCESSING_INSTRUCTION_NODE://预处理指令类型
30 printNodeInfo(node);
31 break;
32 case Node.ELEMENT_NODE://元素节点类型
33 printNodeInfo(node);
34 printAttribute(node);
35 break;
36 case Node.TEXT_NODE://文本节点类型
37 printNodeInfo(node);
38 break;
39 default:
40 break;
41 }
42
43 Node child=node.getFirstChild();
44 while(child!=null)
45 {
46 printNode(child);
47 child=child.getNextSibling();
48 }
49 }
50
51 /** *//**
52 * 根据节点类型打印节点
53 * @param node
54 */
55 public static void printNodeInfo(Node node)
56 {
57 if (node.getNodeType() == Node.ELEMENT_NODE)
58 {
59 System.out.println("NodeName: " + node.getNodeName());
60 }
61 else if (node.getNodeType() == Node.TEXT_NODE)
62 {
63 String value = node.getNodeValue().trim();
64 if (!value.equals(""))
65 System.out.println("NodeValue: " + value);
66 else
67 System.out.println();
68 }else
69 {
70 System.out.println(node.getNodeName()+" : "+node.getNodeValue());
71 }
72 }
73
74 /** *//**
75 * 打印节点属性
76 * @param aNode 节点
77 */
78 public static void printAttribute(Node aNode)
79 {
80 NamedNodeMap attrs = aNode.getAttributes();
81 if(attrs!=null)
82 {
83 for (int i = 0; i < attrs.getLength(); i++)
84 {
85 Node attNode = attrs.item(i);
86 System.out.println("Attribute: " + attNode.getNodeName() + "=\"" + attNode.getNodeValue()+"\"");
87 }
88 }
89 }
DOM生成XML文档:DOMCreateExample.java
1import java.io.FileNotFoundException;
2import java.io.FileOutputStream;
3import java.io.IOException;
4
5import javax.xml.parsers.DocumentBuilder;
6import javax.xml.parsers.DocumentBuilderFactory;
7import javax.xml.parsers.ParserConfigurationException;
8
9import org.w3c.dom.Document;
10import org.w3c.dom.Element;
11
12import com.sun.org.apache.xml.internal.serialize.XMLSerializer;
13
14public class DOMCreateExample
15{
16 public static void main(String[] args) throws ParserConfigurationException
17 {
18 //DOMImplementation domImp = DOMImplementationImpl.getDOMImplementation();
19 DocumentBuilderFactory builderFact = DocumentBuilderFactory.newInstance();
20 DocumentBuilder builder = builderFact.newDocumentBuilder();
21
22 Document doc = builder.newDocument();
23 //Document doc = domImp.createDocument(null, null, null);
24
25 Element root = doc.createElement("games");
26 Element child1 = doc.createElement("game");
27 child1.appendChild(doc.createTextNode("Final Fantasy VII"));
28 child1.setAttribute("genre", "rpg");
29 root.appendChild(child1);
30 doc.appendChild(root);
31
32 XMLSerializer serial;
33 try
34 {
35 serial = new XMLSerializer(new FileOutputStream("domcreate.xml"), null);
36 serial.serialize(doc);
37 } catch (FileNotFoundException e1)
38 {
39 e1.printStackTrace();
40 } catch (IOException e)
41 {
42 e.printStackTrace();
43 }
44 }
45}
第三种JDOM解析
JDOM利用了java语言的优秀特性,极大地简化了对XML文档的处理,相比DOM简单易用。JDOM也使用对象树来表示XML文档,JDOM使用SAXj解析器来分析XML文档,构建JDOM树。然而JOMD本身并没有提供解析器,它使用其他开发商提供的标准SAX解析器,JDOM默认通过JAXP来选择解析器,可以通过手动知道解析器的类名来设置。
首先要在工程中添加jdom的jar包,这里使用jdom1.0.jar。(见附件)
JDOMConvert.java
1import java.io.File;
2
3import org.jdom.Document;
4import org.jdom.Element;
5import org.jdom.input.SAXBuilder;
6import org.jdom.output.Format;
7import org.jdom.output.XMLOutputter;
8
9public class JDOMConvert
10{
11 public static void main(String[] args)
12 {
13 SAXBuilder saxBuilder=new SAXBuilder();
14 try
15 {
16 Document doc=saxBuilder.build(new File("domdb.xml"));
17
18 //首先创建好节点
19 Element eltDb=new Element("db");
20 Element eltDriver=new Element("driver");
21 Element eltUrl=new Element("url");
22 Element eltUser=new Element("user");
23 Element eltPassword=new Element("password");
24
25 //设置节点的值
26 eltDriver.setText("com.mysql.jdbc.Driver");
27 eltUrl.setText("jdbc:mysql://localhost/mySql");
28 eltUser.setText("root");
29 eltPassword.setText("xlc");
30
31 //添加到根节点
32 eltDb.addContent(eltDriver);
33 eltDb.addContent(eltUrl);
34 eltDb.addContent(eltUser);
35 eltDb.addContent(eltPassword);
36 //根节点设置属性
37 eltDb.setAttribute("type","mysql");
38
39 Element root=doc.getRootElement();
40 //root.removeChild("db");//删除节点
41 root.addContent(eltDb);//增加节点
42
43 //修改db节点中内容
44 root.getChild("db").getChild("user").setText("system");
45 root.getChild("db").getChild("password").setText("manager");
46
47 XMLOutputter xmlOut=new XMLOutputter();
48
49 //设置XML格式
50 Format fmt=Format.getPrettyFormat();
51 fmt.setIndent(" ");
52 fmt.setEncoding("utf-8");
53
54 xmlOut.setFormat(fmt);
55 xmlOut.output(doc,System.out);
56 }
57 catch (Exception e)
58 {
59 e.printStackTrace();
60 }
61 }
62}
JDOM生成XML文档:JDOMCreate.java
1import java.io.IOException;
2
3import org.jdom.Document;
4import org.jdom.Element;
5import org.jdom.output.XMLOutputter;
6
7public class JDOMCreate
8{
9 public static void main(String[] args)
10 {
11 Document doc = new Document(new Element("games"));
12 Element newGame = new Element("game").setText("Final Fantasy VI");
13 doc.getRootElement().addContent(newGame);
14 newGame.setAttribute("genre", "rpg");
15 XMLOutputter domstream = new XMLOutputter();
16 try
17 {
18 domstream.output(doc, System.out);
19 } catch (IOException e)
20 {
21 e.printStackTrace();
22 }
23 }
24}
第四种:DOM4J解析
dom4j与JDOM一样,也是一种用于解析XML文档的开放源代码的XML框架,dom4j也应用于java平台,dom4j API使用了java集合框架并完全支持DOM、SAX和JAXP。与JDOM不同的是,dom4j使用接口和抽象类,虽然dom4j的API相对复杂些,但它提供了比JDOM更好的灵活性。dom4j也使用SAX解析器来分析XML文档,创建dom4j树。此外dom4j也可以接收DOM格式的内容,并提供了从dom4j树到SAX事件流或W3C DOM树的输出机制。与JDOM不同,dom4j自带了一个SAX解析器Aelfred2,如果没有显示的设置SAX解析器,也没有通过系统属性org.xml.sax.driver设置解析器,dom3j将会使用JAXP来加载JAXP配置的解析器,如果创建解析器失败,那么最后才使用dom4j自带的Aelfred2解析器。
同样,首先要在工程中添加dom4j的jar包,这里使用dom4j-1.6.1.jar。(见附件)
Dom4j生成XML文档db.xml:Dom4jCreate.java
1import java.io.IOException;
2
3import org.dom4j.Document;
4import org.dom4j.DocumentHelper;
5import org.dom4j.Element;
6import org.dom4j.io.OutputFormat;
7import org.dom4j.io.XMLWriter;
8
9public class Dom4jCreate
10{
11
12 public static void main(String[] args)
13 {
14 Document doc = DocumentHelper.createDocument();
15
16 doc.addProcessingInstruction("xml-stylesheet", "type='text/xsl' href='db.xsl'");
17 doc.addDocType("dbconfig", null,"db.dtd");
18
19 //Element root=DocumentHelper.createElement("dbconfig");
20 // doc.setRootElement(root);
21 Element root = doc.addElement("dbconfig");
22
23 Element eltDb= root.addElement("db");
24 Element eltDriver = eltDb.addElement("driver");
25 Element eltUrl = eltDb.addElement("url");
26 Element eltUser = eltDb.addElement("user");
27 Element eltPassword = eltDb.addElement("password");
28
29 eltDriver.setText("com.mysql.jdbc.Driver");
30 eltUrl.setText("jdbc:mysql://localhost/mySql");
31 eltUser.setText("root");
32 eltPassword.setText("xlc");
33 eltDb.addAttribute("type","mysql");
34
35 try
36 {
37 //设置输出格式
38 OutputFormat outFmt = new OutputFormat(" ", true);
39 outFmt.setEncoding("UTF-8");
40
41 /**//*PrintWriter pw = new PrintWriter(System.out);
42 doc.write(pw);
43 pw.flush();
44 pw.close();*/
45
46 XMLWriter xmlWriter = new XMLWriter(System.out, outFmt);
47 // XMLWriter xmlWriter=new XMLWriter(new FileWriter("db.xml"),outFmt);
48 xmlWriter.write(doc);
49 xmlWriter.flush();
50 xmlWriter.close();
51 } catch (IOException e)
52 {
53 e.printStackTrace();
54 }
55 }
56}
Dom4j修改XML文档db.xml:Dom4jModify.java
Dom4jModify.java
import java.io.File;
import java.io.FileWriter;
import java.util.Iterator;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
public class Dom4jModify
{
public Document modifyDocument(File inputXml)
{
try
{
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(inputXml);
document.addDocType("dbconfig",null,"db.dtd");
List list = document.content();
// Iterator iter = document.nodeIterator();
Iterator iter = list.iterator();
Element element = (Element) iter.next();
element.element("db").attribute("type").setValue("mysql");
element.element("db").element("url").setText("jdbc:mysql://localhost/mySql");
element.element("db").element("driver").setText("com.mysql.jdbc.Driver");
element.element("db").element("user").setText("root");
element.element("db").element("password").setText("xlc");
// 设置输出格式
OutputFormat outFmt = new OutputFormat(" ", true);
outFmt.setEncoding("UTF-8");
XMLWriter xmlWriter=new XMLWriter(new FileWriter("domdb-modified.xml"),outFmt);
xmlWriter.write(document);
xmlWriter.flush();
xmlWriter.close();
return document;
}
catch (Exception e)
{
System.out.println(e.getMessage());
return null;
}
}
public static void main(String[] args) throws Exception
{
Dom4jModify dom4jParser = new Dom4jModify();
Document document = dom4jParser.modifyDocument(new File("domdb.xml"));
OutputFormat outFmt = new OutputFormat(" ", true);
outFmt.setEncoding("UTF-8");
XMLWriter xmlWriter = new XMLWriter(System.out,outFmt);
xmlWriter.write(document);
xmlWriter.flush();
xmlWriter.close();
}
}
相关资料链接
J2EE复习(一)HTML
J2EE复习(二)XML(上)
J2EE复习(二)XML(下)--XML解析
J2EE复习(三)JavaScript