下面是一個將XML轉換為JSON的示例,
通過SAX來解析XML,從而生成相應的JSON字符串
自我感覺還算是一個比較通用的 API ,主要包含3個類
1, ToJsonSAXHandler 類 繼承了 DefaultHandler 類,在解析
XML的過程中負責處理 SAX 事件。代碼如下:
Java代碼
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 是一個異常類(封裝在轉換過程中可能產生的異常),代碼如下:
Java代碼
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字符串的工具類
Java代碼
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字符串):
Java代碼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": ["Thinking in JAVA"],
"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": ["Core JAVA2"],
"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