SAX是解析XML文档是一种“基于事件的模型”。基于SAX的解析器在处理文档时,会生成名为“事件”的通知信息。软件程序可“侦听”这些事件,以便从文档获取数据。处理大型XML文档时,SAX的解析器通常比基于DOM的解析器更有效,尤其重要的是,基于SAX的解析器不会将整个XML文档载入内存。SAX只解析一次,是顺序解析的。所以SAX速度更快,而且更省内存。

     将xml文件转成json格式的,建立二个类,Xml2JsonHandler 用来解析xml文件,SaxJSON用来存放json同时运行。

     首先,说明一下SAX工作流程:

      第一步建立sax解析工厂:SAXParserFactory spf = SAXParserFactory.newInstance();

     第二步建立sax解析对象:SAXParser parser = spf.newSAXParser();

     第三部指定解析xml文件,解析:parser.parse(new File("D://1.xml"), new XmlToJson());

     当读到第一个xml的“<”符号就会调用public void startDocument() 函数,而且只调用一次,当读到节点时则调用public void startElement(String url, String localName, String qName, Attributes attributes ) 函数,其中localName,qName时节点名称,attributes 时节点属性名称和节点属性的值。attributes.getQName(i)获得节点属性名称 ,attributes.getValue(i)获得节点属性的值。public void characters(char[] ch, int offset, int length)去读节点值,注意是所有的节点。当读到结束节点时调用public void endElement(String url, String localName, String qName),文档解析结束调用public void endDocument()。

    类Xml2JsonHandler:

package com.xml.sax;
import java.util.HashMap;
import java.util.Map;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class Xml2JsonHandler extends DefaultHandler{

 private SaxJSON saxJson; //存放json的类
 private String currentKey = ""; //当前xml的节点路线  如读到<book><y></y></book> <y> 为book.y
 //解析完一个文档用来清空
 public void clear(){
  this.saxJson = null;
  this.currentKey = "";
  this.saxJson = new SaxJSON();
 }
 
 public Xml2JsonHandler(){
  this.saxJson = new SaxJSON();
 }
 
 public Map getResult(){
  return this.saxJson.getResult();
 }
 //解析文档开始
 public void startDocument() {
  this.saxJson.startDoc();
 }
 //当遇到开始节点时调用
 public void startElement(String url, String localName, String qName,
   Attributes attributes ) throws SAXException {
  if (currentKey != null && !currentKey.equals("")) {
   currentKey = currentKey + ".";
  }
  currentKey = currentKey + qName; //记录当前节点路径
  for (int i = 0; i < attributes.getLength(); i++) {
   if (attributes.getQName(i).equals("scheme")) { // 获取节点属性名称,
    Map map = new HashMap();
    map.put("@scheme", attributes.getValue(i)); //将节点属性名称前加@
    this.saxJson.startEl(currentKey, map); // 调用saxJson的开始建json
   }
  }
 }
 
 public void characters(char[] ch, int offset, int length) {
//  this.saxJson.characters("");
  String value = new String(ch, offset, length); // 获取节点数据
  value = value.replace("\n", "");  //为了去掉空格,制表符,换行等。
  value = value.replace("\t", "");
  value = value.replace(" ", "");
  Map map = new HashMap();
  map.put("#text", value);
  if (length != 1 && !value.equals("")) {
   this.saxJson.characters(currentKey, map); //调用saxJson的存放数据
  }
 }

 public void endElement(String url, String localName, String qName) {
  if (currentKey.lastIndexOf(".") != -1) {
   currentKey = currentKey.substring(0, currentKey.lastIndexOf(qName)-1); // 去掉当前结束节点名称
  }
  this.saxJson.endEl();
 }

 // 文档结束时调用
 public void endDocument() {
  this.saxJson.endDoc();
  Map map = this.saxJson.getResult();
  System.out.println("----result----"+map);
  this.clear();
 }
}
类SaxJSON:

package com.xml.sax;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class SaxJSON {

 private Map map; // 存放整个xml的json
 // map中存放的当前json的父节点json 如 {"a":{"b":{"#text":"c"}} 当"c"sonMap为{"b":{}}
 private Map sonMap;
 private String str; //@全路径名

 public SaxJSON() {

 }

 public void startDoc() {
  this.map = new HashMap();
  this.sonMap = new HashMap();
  this.str = "";
 }

 public void endDoc() {

 }

 public void startEl(String currentKey, Map value) {
  String[] arr = currentKey.split("\\."); // 用来处理节点属性的
  this.setMap(arr, value);
  str = currentKey;
 }

 public void endEl() {

 }

 public void characters(String currentKey, Map value) { // 处理节点的值
  String[] arr = currentKey.split("\\.");
  this.setMap(arr, value);
  str = "";
 }

 public Map getResult() {
  return map;
 }

 /**
  *
  * @param arr
  *            arr 是一个深度的值 所有key的集合, sonMap 记录上次存放map
  * @param value
  */
 private void setMap(String[] arr, Object value) {
  if (str != null && !str.equals("")) { // 判断有没有节点属性
   String[] s = str.split("\\.");
   Map m = map;
   for (int i = 0; i < s.length; i++) {  // 获取当前路径下的子map
    m = (Map) m.get(s[i]);
   }
   List list = new ArrayList();  // 将节点属性 和当前的值放在一个数组存放
   list.add(value);
   list.add(m);
   value = list;
   for (int i = s.length - 1; i >=0 ; i--) {
    value = maps(s[i],value); //从底层向外出建map
   }
   map.putAll((Map)value); //将当前map放入大map中
   return;
  }
  for (int i = 0; i < arr.length; i++) { // 没有节点属性名称
   
   if (map.get(arr[i]) == null) {
    for (int j = arr.length - 1; j > i; j--) {
     value = maps(arr[j], value); //从底层向外出建map
    }
    if (i == 0) { // 当前map 在大map中没有重复key值
     map.put(arr[i], value); //直接放入
    } else {
     Map sonMap = (Map) map.get(arr[i - 1]); // 用,获取最底层sonmap;
     sonMap.putAll((Map) value); //将其放入
     for (int j = i - 1; j >= 0; j--) {
      sonMap = maps(arr[j], sonMap);
      if (j == 0) {
       map.putAll(sonMap); 
      }
     }
    }
    return;
   }
  }

 }

 private Map maps(Object key, Object ma) {
  Map m = new HashMap();
  m.put(key, ma);
  return m;
 }
}
测试类:

package com.xml.sax;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;

public class TestMain {

 public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
  SAXParserFactory spf = SAXParserFactory.newInstance();
  SAXParser parser = spf.newSAXParser();
  parser.parse(new File("D://2.xml"),new Xml2JsonHandler());

 }
}
xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<people>
  <person>
    <name scheme="213213">zhangsan</name>
    <tel>5128</tel>
    <email>txq512@sina.com</email>
  </person>    
</people>
结果为:

----result----{people={person={name=[{#text=zhangsan}, {@scheme=213213}]}, email={#text=txq512@sina.com}, tel={#text=5128}}}