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
 1
import java.io.File;
 2
 3
import javax.xml.parsers.SAXParser;
 4
import javax.xml.parsers.SAXParserFactory;
 5
 6
import org.xml.sax.Attributes;
 7
import org.xml.sax.SAXException;
 8
import org.xml.sax.helpers.DefaultHandler;
 9
10
public 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
 1
import org.xml.sax.Attributes;
 2
import org.xml.sax.ContentHandler;
 3
import org.xml.sax.Locator;
 4
import org.xml.sax.SAXException;
 5
 6
public 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 
 1
public 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 
 1
import java.io.FileInputStream;
 2
 3
import org.xml.sax.InputSource;
 4
import org.xml.sax.XMLReader;
 5
import org.xml.sax.helpers.XMLReaderFactory;
 6
 7
public 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
 1
import org.w3c.dom.Document;
 2
import org.w3c.dom.NamedNodeMap;
 3
import org.w3c.dom.Node;
 4
 5
import com.sun.org.apache.xerces.internal.parsers.DOMParser;
 6
 7
public 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 
 1
import java.io.FileNotFoundException;
 2
import java.io.FileOutputStream;
 3
import java.io.IOException;
 4
 5
import javax.xml.parsers.DocumentBuilder;
 6
import javax.xml.parsers.DocumentBuilderFactory;
 7
import javax.xml.parsers.ParserConfigurationException;
 8
 9
import org.w3c.dom.Document;
10
import org.w3c.dom.Element;
11
12
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;
13
14
public 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 
 1
import java.io.File;
 2
 3
import org.jdom.Document;
 4
import org.jdom.Element;
 5
import org.jdom.input.SAXBuilder;
 6
import org.jdom.output.Format;
 7
import org.jdom.output.XMLOutputter;
 8
 9
public 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 
 1
import java.io.IOException;
 2
 3
import org.jdom.Document;
 4
import org.jdom.Element;
 5
import org.jdom.output.XMLOutputter;
 6
 7
public 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 
 1
import java.io.IOException;
 2
 3
import org.dom4j.Document;
 4
import org.dom4j.DocumentHelper;
 5
import org.dom4j.Element;
 6
import org.dom4j.io.OutputFormat;
 7
import org.dom4j.io.XMLWriter;
 8
 9
public 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