【转】将XML转换为JSON (SAX解析实例)

下面是一个将XML转换为JSON的示例,

通过SAX来解析XML,从而生成相应的JSON字符串

自我感觉还算是一个比较通用的API,主要包含3个类

1,ToJsonSAXHandler类继承了DefaultHandler类,在解析

XML的过程中负责处理SAX事件。代码如下:

package org.yjf.xmlToJson;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class ToJsonSAXHandler extends DefaultHandler {
	
	//jsonStringBuilder 保存解析XML时生成的json字符串
	private StringBuilder jsonStringBuilder ;
	
	/*
	 *  isProcessing 表示 是否正在解析一个XML
	 *  	startDocument 事件发生时设置 isProcessing = true
	 *  	startDocument 事件发生时设置 isProcessing = false
	 */
	private boolean isProcessing;
	
	/*
	 *  justProcessStartElement 表示 是否刚刚处理完一个 startElement事件
	 *  引入这个标记的作用是为了判断什么时候输出逗号 
	 */
	private boolean justProcessStartElement;
	
	public ToJsonSAXHandler(){
		jsonStringBuilder = new StringBuilder();
	}
	
	@Override
	public void startDocument() throws SAXException {
		/*
		 * 开始解析XML文档时 设定一些解析状态
		 *     设置isProcessing为true,表示XML正在被解析
		 *     设置justProcessStartElement为true,表示刚刚没有处理过 startElement事件
		 */
		isProcessing = true;
		justProcessStartElement = true;
		//清空 jsonStringBuilder 中的字符
		this.jsonStringBuilder.delete(0, this.jsonStringBuilder.length());
	}
	
	@Override
	public void endDocument() throws SAXException {
		isProcessing = false;
	}
	
	@Override
	public void startElement(String uri, String localName, String qName, 
			Attributes attrs) throws SAXException {	
		/*
		 * 是否刚刚处理完一个startElement事件
		 *     如果是 则表示这个元素是父元素的第一个元素 。
		 *     如果不是 则表示刚刚处理完一个endElement事件,即这个元素不是父元素的第一个元素
		 */
		if(!justProcessStartElement){
			jsonStringBuilder.append(',');
			justProcessStartElement = true;
		}
		jsonStringBuilder.append("{");
		jsonStringBuilder.append("localName:").append('\"').append(localName).append('\"').append(',');
		jsonStringBuilder.append("uri:").append('\"').append(uri).append('\"').append(',');
		jsonStringBuilder.append("qName:").append('\"').append(qName).append('\"').append(',');
		//将解析出来的元素属性添加到JSON字符串中
		jsonStringBuilder.append("attrs:{");
		if(attrs.getLength() > 0){
			jsonStringBuilder.append(attrs.getLocalName(0)).append(":")
				.append(attrs.getValue(0));
			for(int i = 1 ; i < attrs.getLength() ; i++){
				jsonStringBuilder.append(',').append(attrs.getLocalName(i)).append(":")
					.append(attrs.getValue(i));
			}	
		}
		jsonStringBuilder.append("},");
		//将解析出来的元素的子元素列表添加到JSON字符串中
		jsonStringBuilder.append("childElements:[").append('\n');
	}
	
	@Override
	public void endElement(String uri,String localName,String qName)
			throws SAXException {
		justProcessStartElement = false;
		jsonStringBuilder.append("]}").append('\n');
	}

	@Override
	public void characters(char[] ch, int begin, int length) 
			throws SAXException {
		/*
		 * 是否刚刚处理完一个startElement事件
		 *     如果是 则表示这个元素是父元素的第一个元素 。
		 *     如果不是 则表示刚刚处理完一个endElement事件,即这个元素不是父元素的第一个元素
		 */
		if(!justProcessStartElement){
			jsonStringBuilder.append(',');
		}else
			justProcessStartElement = false;
		
		jsonStringBuilder.append('\"');
		for(int i = begin ; i < begin+length ; i++){
			switch(ch[i]){
				case '\'':jsonStringBuilder.append("\\'");break;
				case '\"':jsonStringBuilder.append("\\\"");break;
				case '\n':jsonStringBuilder.append("\\n");break;
				case '\t':jsonStringBuilder.append("\\t");break;
				case '\r':jsonStringBuilder.append("\\r");break;
				default:  jsonStringBuilder.append(ch[i]);break;
			}
		}
		jsonStringBuilder.append('\"').append('\n');
	}
	
	public String getJsonString() throws XMLToJSONException{
		if(this.isProcessing)
			throw new XMLToJSONException("getJsonString before resolution is finished");
		else
			return jsonStringBuilder.toString();
	}
}

2,XMLToJSONException是一个异常类(封装在转换过程中可能产生的异常),代码如下:

package org.yjf.xmlToJson;

public class XMLToJSONException extends Exception {

	private static final long serialVersionUID = 1L;
	
	public XMLToJSONException(){}
	public XMLToJSONException(String message){
		super(message);
	}

}

3,XMLToJSON类是一个将XML转换为JSON字符串的工具类

package org.yjf.xmlToJson;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.StringReader;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;

public class XMLToJSON {
	
	public static String convert(String xmlStr) throws SAXException,
			IOException, XMLToJSONException {
		return convert(new InputSource(new StringReader(xmlStr)));
	}

	public static String convert(File file) throws SAXException,
			IOException, XMLToJSONException {
		return convert(new InputSource(new FileInputStream(file)));
	}

	public static String convert(InputSource inputSource) throws SAXException,
			IOException, XMLToJSONException {
		ToJsonSAXHandler handler = new ToJsonSAXHandler();
		//创建一个 SAX 解析器 ,并设置这个解析器的内容事件处理器 和 错误事件处理器 为 handler
		XMLReader reader = XMLReaderFactory.createXMLReader();
		reader.setContentHandler(handler);
		reader.setErrorHandler(handler);
		//用 SAX 解析器解析XML输入源
		reader.parse(inputSource);
		//返回 ToJsonSAXHandler 中保存的 json字符串
		return handler.getJsonString();
	}

}

测试类Test如下(因为生成的JSON不包含缩进,所以看起来可能不太直观,所以我用了JSONObject类来打印带有缩进的JSON字符串,同时也验证了转换出来的JSON字符串是一个有效的JSON字符串):

package test;

import java.io.File;
import java.io.IOException;

import org.json.JSONException;
import org.json.JSONObject;
import org.xml.sax.SAXException;
import org.yjf.xmlToJson.XMLToJSON;
import org.yjf.xmlToJson.XMLToJSONException;

public class Test_1 {

	public static void main(String[] args) throws JSONException, 
			SAXException, IOException, XMLToJSONException{
		String jsonStr = XMLToJSON.convert(new File("books.xml"));
		/*
		 * JSONObject 是一个JSON对象的java实现
		 * 可以通过用一个有效的JSON字符串来构造JSON对象
		 * 下面的两行代码通过转换而来的JSON字符串构造了一个JSON对象,
		 * 并且打印出了这个JSON对象的带有缩进的字符串表示
		 */
		JSONObject jsonObj = new JSONObject(jsonStr);
		System.out.println(jsonObj.toString(2));
	}

}

books.xml的内容如下:

<?xml version="1.0" encoding="utf-8"?>
<books  count="2" xmlns="http://test.org/books">
	<book id="1" page="1000">
		<name>Thinking in JAVA</name>
	</book>
	<book id="2" page="800">
		<name>Core JAVA2</name>
	</book>
</books>

运行Test类输出的JSON字符串如下:

{

"attrs":{"count":2},

"childElements":[

"\n\t",

{

"attrs":{

"id":1,

"page":1000

},

"childElements":[

"\n\t\t",

{

"attrs":{},

"childElements":["ThinkinginJAVA"],

"localName":"name",

"qName":"name",

"uri":"http://test.org/books"

},

"\n\t"

],

"localName":"book",

"qName":"book",

"uri":"http://test.org/books"

},

"\n\t",

{

"attrs":{

"id":2,

"page":800

},

"childElements":[

"\n\t\t",

{

"attrs":{},

"childElements":["CoreJAVA2"],

"localName":"name",

"qName":"name",

"uri":"http://test.org/books"

},

"\n\t"

],

"localName":"book",

"qName":"book",

"uri":"http://test.org/books"

},

"\n"

],

"localName":"books",

"qName":"books",

"uri":"http://test.org/books"

}

本博客转自http://www.iteye.com/topic/402083

原版主望谅解,新人不知道怎么做

相关推荐