下面是一个将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代码  

<?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