`
步行者
  • 浏览: 169816 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

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

    博客分类:
  • XML
阅读更多

下面是一个将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": ["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"
}


附件包含上面示例的源文件

  • src.rar (6.8 KB)
  • 下载次数: 771
分享到:
评论
5 楼 isreal 2009-11-01  
我用这一个字符串做测试,报错Missing value at character 419

<?xml version="1.0" encoding="GB2312"?><xml><version>v1.0</version><state>100</state><message>获取期号列表成功</message><list><row opencode="" expect="09128" active="1" addendtime="2009-11-01 19:15:00" buyendtime="2009-11-01 19:15:00" opentime="2009-10-29 19:33:32" allowbuy="1" duizhen="" /></list><curtime>2009-11-01 18:42:44</curtime></xml>

我看了一下,解析字符串把row 属性解析在一起了,请指教。
4 楼 步行者 2009-06-06  
但是用 DOM 解析效率就会低很多
3 楼 303535576 2009-06-06  
<div class="quote_title">步行者 写道</div><div class="quote_div"><p>
</p>
<p style="margin: 0px;">用books.book[0].name表达式来返回一个书名的还是不太好</p>
<p style="margin: 0px;">我们怎么知道books.book[0].name一定是一个元素,我觉得把它</p>
<p style="margin: 0px;">看作一个元素列表更恰当,</p>
<p style="margin: 0px;">即用books.book[0].name[0].text来返回"Thinking in java"</p>
<p style="margin: 0px;">怎么看起来有点像XPath了 呵呵</p>
<p style="margin: 0px;">研究研究</p>

<p> </p>
<p> </p>
<p> </p></div><br/>估计用DOM来解析更方便些
2 楼 步行者 2009-06-05  
<p>
</p>
<p style="margin: 0px;">用books.book[0].name表达式来返回一个书名的还是不太好</p>
<p style="margin: 0px;">我们怎么知道books.book[0].name一定是一个元素,我觉得把它</p>
<p style="margin: 0px;">看作一个元素列表更恰当,</p>
<p style="margin: 0px;">即用books.book[0].name[0].text来返回"Thinking in java"</p>
<p style="margin: 0px;">怎么看起来有点像XPath了 呵呵</p>
<p style="margin: 0px;">研究研究</p>

<p> </p>
<p> </p>
<p> </p>
1 楼 303535576 2009-06-05  
<p><span>用这种方式 生成 的JSON 对象,比如:</span></p>
<p> </p>
<p> </p>
<pre name="code" class="java"><span><span style="color: #0000ff; font-size: small;">var books = {
    "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"
}</span> </span></pre>
 
<p><span>
如果用JS访问感觉还是不太方便,如果要访问“Thinking in java”这个文本,</span></p>
<p><span>需要 用这个表达式 <span style="font-family: Arial; white-space: normal; line-height: 18px;"><span style="color: #0000ff;"><span style="font-size: small;">books</span></span></span><span style="color: #0000ff;"><span style="font-size: small;">.childElements[2].childElements[1].childElements[0] </span></span></span></p>
<p><span>这样看起来不是很直观 ,感觉要是用这个表达式 <span style="color: #0000ff;"><span style="font-size: small;">books</span></span><span><span style="color: #0000ff;"><span style="font-size: small;">.book[0].name就更直观了</span></span></span></span></p>
<p> </p>

相关推荐

    XML通过sax解析JSON格式

    标题中提到的"XML通过SAX解析为JSON格式"是指使用SAX解析器来读取XML文档,并将其转换成等效的JSON对象。SAX解析器以流式方式处理XML,当遇到文档的不同部分(如开始标签、结束标签、文本节点等)时,会触发相应的...

    xml解析和json解析.zip

    它提供了解析JSON字符串为Java对象,以及将Java对象转换为JSON字符串的功能。Fastjson的特性包括高速度、低内存消耗和简单的API。此外,它还支持JSON Schema验证,以及直接映射Java反射机制,使得JSON与Java对象之间...

    Java 解析xml 存入mongodb 返回org.json json包

    总结来说,这个项目涉及了三个主要步骤:使用SAX解析XML文件,将解析得到的数据通过Java驱动存入MongoDB数据库,然后将MongoDB中的数据转换成org.json的JSON格式。这些步骤展示了Java在处理XML、数据库操作以及JSON...

    IOS的进行xml解析和json解析要用的一个很好的类库

    JSON解析在iOS中,Apple提供了内置的NSJSONSerialization类,它是Objective-C标准库的一部分,可以方便地将JSON字符串转换为Foundation对象,反之亦然。然而,在处理复杂或大量数据时,可能需要更高效的解决方案。 ...

    MusicXML 解析与布局

    解析MusicXML文件的过程是将XML文档转化为程序可以理解和操作的数据结构。C++中,这通常通过DOM(Document Object Model)或SAX(Simple API for XML)解析库来实现。DOM解析会一次性加载整个XML文档到内存,适合...

    Android网络之数据解析----SAX方式解析XML数据

    本篇文章将深入探讨如何使用SAX(Simple API for XML)方式解析XML数据,这是Android网络通信中处理XML数据的一种高效方法。 一、XML与JSON数据 XML(eXtensible Markup Language)是一种用于标记数据的语言,它...

    Android XML JSON 解析

    以上就是Android中XML和JSON解析的基本概念和实例。在实际开发中,开发者通常会结合网络请求库(如Volley、OkHttp、Retrofit等)一起使用,从服务器获取XML或JSON数据,然后进行解析和展示。了解和掌握这两种解析...

    http请求网络解析xml以及JSON的demo

    本教程将通过一个名为"HTTP请求网络解析XML以及JSON的demo"的实例,深入讲解如何利用Java实现这两种请求方式,并对返回的数据进行有效的解析。 首先,我们来看HTTP请求。在Java中,有两个主要的HTTP客户端API可供...

    XML解析实例

    总之,XML解析实例为我们提供了实践和理解如何在代码中处理XML数据的机会。无论是选择DOM还是SAX,了解其工作原理和使用方式都是IT从业者必备的技能之一。通过学习和研究这个实例,我们可以加深对XML解析的理解,并...

    PB 解析xml格式串

    2. **XML解析**:XML文档由元素、属性、文本等构成,解析XML时,我们需要读取这些元素并将其转换为内存中的数据结构。Python中可以使用`xml.etree.ElementTree`库进行解析,Java中可使用DOM或SAX解析器。 3. **XML...

    xml解析及使用XStream实现javaBean与xml之间的转换

    在`xmlAnalysis`文件夹中,可能包含了一个简单的Java程序,演示了如何使用DOM、SAX、StAX和XStream解析XML文件,并展示了XStream如何在JavaBean与XML之间进行转换。你可以运行这些代码,观察输出结果,以加深理解。...

    VTD-XML技术解析XML实例

    - **XML转换**:将XML转换为其他格式,如JSON,或者进行XML到XML的映射。 - **XML搜索**:使用VTD-XML可以实现对XML文档的快速搜索和过滤。 VTD-XML的API设计简洁,提供了多种方法来操作XML,例如`AutoPilot`类用于...

    webservice之使用jaxb把xml转换Object或把对象转换成xml文件

    2. 序列化XML:使用`Marshaller`接口将Java对象转换为XML文档。例如: ```java JAXBContext jaxbContext = JAXBContext.newInstance(User.class); Marshaller marshaller = jaxbContext.createMarshaller(); ...

    Java-Java操作XML和JSON教程

    1. **Gson**:Google开发的Gson库能够将Java对象转换成JSON字符串,反之亦然。这使得在Java对象和JSON数据之间进行序列化和反序列化变得非常简单。 2. **Jackson**:Jackson是另一个流行的JSON库,提供了多种API,...

    android异步下载图片实例/解析xml实例

    4. **Java XML API (JAXB)**: 将XML转换为Java对象,反之亦然。适合于对象和XML之间的双向映射,但内存占用较高。 在描述的实例中,可能是通过HTTP请求获取豆瓣电影的XML数据,然后使用上述解析器之一来解析XML,...

    安卓Android源码——比较通用的xml解析方法.rar

    在实际开发中,为了提高效率和便捷性,开发者常选择第三方库,如Gson、Jackson、FastXml(OkHttp的Okio库)等,它们提供了更高级别的API,能快速将XML转换为Java对象。 7. JSON与XML的互转 在某些场景下,可能需要...

    推荐rapidjson-超强JSON文件读取解析库(带打包和解析实例)

    解析后的JSON数据将被转换为DOM(Document Object Model)结构,方便进一步处理。 2. **DOM模型**:RapidJSON的DOM模型包括`Value`类,它表示JSON中的任何值,如对象、数组、字符串、数字等。开发者可以通过DOM模型...

    JSON和XML处理代码

    例如,将一个Java对象转换为JSON字符串: ```java import org.json.JSONObject; public class User { private String name; private int age; // getters and setters public JSONObject toJSON() { return...

    android实例xml解析

    - DOM解析:DOM解析器将整个XML文档加载到内存中,创建一个树形结构,允许开发者通过节点遍历来访问数据。这种方法适合小型XML文件,因为它需要较大的内存空间。 - SAX解析:SAX是一种事件驱动的解析器,它逐行...

    android XML文件解析和序列化 demo

    首先将对象转换为JSON,然后使用像`javax.xml.transform.Transformer`这样的工具将JSON转换为XML。 3. **JAXB (Java Architecture for XML Binding)**: JAXB是Java标准,可以将Java对象转换为XML,反之亦然。不过,...

Global site tag (gtag.js) - Google Analytics