版权声明:

欢迎转载,但请保留文章原始出处

作者:GavinCT

出处:http://www.cnblogs.com/ct2011/p/4002738.html

什么时候可以把解析值赋给对象

一般从网上看到的sax解析,都是在Handler中的characters方法进行对象数据的赋值。

示例代码如下:

private TransportFile parseXML(String xml) {
SAXParserFactory saxfac = SAXParserFactory.newInstance();
try {
SAXParser saxparser = saxfac.newSAXParser();
InputStream is = new ByteArrayInputStream(xml.getBytes());
MySAXHandler handler = new MySAXHandler();
saxparser.parse(is, handler);
return handler.getData();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private class MySAXHandler extends DefaultHandler{
String currentTagName = "";
TransportFile mData = null ;
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
currentTagName = qName ;
if("file".equals(qName)){
mData = new TransportFile();
}
} @Override
public void characters(char[] ch, int start, int length)
throws SAXException {
String str = new String(ch,start,length);
if("guid".equals(currentTagName)){
mData.guid = str;
}else if("name".equals(currentTagName)){
mData.name = str;
}else if("type".equals(currentTagName)){
mData.type = str;
}else if("length".equals(currentTagName)){
mData.length = Long.parseLong(str);
}else if("index".equals(currentTagName)){
mData.index = Integer.parseInt(str);
}else if("count".equals(currentTagName)){
mData.count = Integer.parseInt(str);
}else if("data".equals(currentTagName)){
mData.data = Base64.decode(str);
}
} @Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
currentTagName = "";
} public TransportFile getData(){
return mData ;
}
}

普通的使用场景中上述代码没有问题,但是当xml中某一标签的内容很长时,就会引发上述代码的bug。

实践发现sax解析每次也就解析1k左右的数据,超出部分其实是要分段多次解析的。

所以问题来了,如果在characters方法中解析,那么其他几段的数据仍然会不断覆盖最终返回对象中的数据,导致数据丢失。

因此,对于赋值给最终传回对象的数据,在characters阶段只能不断拼接,解析必须在endElement时才可以完成。否则当数据内容比较大的时候,网上代码中的bug就会凸显出来。

顺便贴上我的代码:

    private class MySAXHandler extends DefaultHandler{
String currentTagName = "";
TransportFile mData = null ;
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
currentTagName = qName ;
mStringBuilder = new StringBuilder();
if("file".equals(qName)){
mData = new TransportFile();
}
}
private StringBuilder mStringBuilder;
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
mStringBuilder.append(ch, start, length);
} @Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
String str = mStringBuilder.toString();
if("guid".equals(currentTagName)){
mData.guid = str;
}else if("name".equals(currentTagName)){
mData.name = str;
}else if("type".equals(currentTagName)){
mData.type = str;
}else if("length".equals(currentTagName)){
mData.length = Long.parseLong(str);
}else if("index".equals(currentTagName)){
mData.index = Integer.parseInt(str);
}else if("count".equals(currentTagName)){
mData.count = Integer.parseInt(str);
}else if("data".equals(currentTagName)){
mData.data = Base64.decode(str);
}
currentTagName = "";
} public TransportFile getData(){
return mData ;
}
}

characters方法参数注意

ch是当前解析到的字符数组,并不是精确的标签内的内容。

下面是解析第一个标签时characters中 ch 、 start、length输出:

===========characters ch: <?xml version='1.0' encoding='utf-8' standalone='yes' ?><file><guid>678c6f92-d617-40af-bb87-a80c3b2be91f</guid><name>0CAQLTZGO.jpg</name><type>image</type><length>71374</length><index>0</index><count>1</count><data>/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoK.....
===========characters start:31
===========characters length:36

真正当前需要的数据是ch数组从start开始的length个字符。

Java XML SAX 解析注意的更多相关文章

  1. Java用SAX解析XML

    要解析的XML文件:myClass.xml <?xml version="1.0" encoding="utf-8"?> <class> ...

  2. Java XML Dom解析工具

    Java XML Dom解析工具 缩进等 transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); ...

  3. JAVA使用SAX解析XML文件

    在我的另一篇文章(http://www.cnblogs.com/anivia/p/5849712.html)中,通过一个例子介绍了使用DOM来解析XML文件,那么本篇文章通过相同的XML文件介绍如何使 ...

  4. java使用sax解析xml

    目的:解析xml文件,并存入mysql,并且要解析的字段能一一对应.这里解析的是微博的文件,想要利用里面的article和person_id字段. 思路: 为了能得到person_id和article ...

  5. Java中Sax解析XML

    SAX基于事件的解析,解析器在一次读取XML文件中根据读取的数据产生相应的事件,由应用程序实现相应的事件处理逻辑,即它是一种“推”的解析方式:这种解析方法速度快.占用内存少,但是它需要应用程序自己处理 ...

  6. 简单的java使用SAX解析xml

    1.新建一个SAXTest类,继承import org.xml.sax.helpers.DefaultHandler类 package com.qiao.SrpingSource; import or ...

  7. XML SAX解析

    SAX是一种占用内存少且解析速度快的解析器,它采用的是事件驱动,它不需要解析完整个文档,而是按照内容顺序,看文档某个部分是否符合xml语法,如果符合就触发相应的事件.所谓的事件就是些回调方法( cal ...

  8. JavaEE XML SAX解析

    SAX解析XML @author ixenos SAX解析工具 SAX解析工具-  Sun公司提供的.内置在jdk中.org.xml.sax.* 核心的API: SAXParser类: 用于读取和解析 ...

  9. 浅谈 Java Xml 底层解析方式

    XML 使用DTD(document type definition)文档类型来标记数据和定义数据,格式统一且跨平台和语言,已成为业界公认的标准. 目前 XML 描述数据龙头老大的地位渐渐受到 Jso ...

随机推荐

  1. POJ 2291

    #include<iostream> #include<stdio.h> using namespace std; int compare(void const *,void ...

  2. 大数据技术之_19_Spark学习_04_Spark Streaming 应用解析小结

    ========== Spark Streaming 是什么 ==========1.SPark Streaming 是 Spark 中一个组件,基于 Spark Core 进行构建,用于对流式进行处 ...

  3. Anaconda 入门详解

    Anaconda Anaconda简介 Anaconda是一个免费开源的Python和R语言的发行版本,用于计算科学(数据科学.机器学习.大数据处理和预测分析),Anaconda致力于简化包管理和部署 ...

  4. Hadoop2.0.0+CDH4.5.0集群配置

    Hadoop 2.0.0-cdh4.5.0安装:http://blog.csdn.net/u010967382/article/details/18402217 CDH版本下载:http://arch ...

  5. EF 数据库连接约定(Connection String Conventions in Code First)

    一个典型的EF应用大多数情况下是一个DbContext的派生类(derived class)来控制,通常可以使用该派生类调用DbContext的构造函数,来控制以下的东西: (1).上下文如何连接到数 ...

  6. Spring Security构建Rest服务-1100-单机Session管理

    Session失效时间: springboot配置session失效时间,只需要在application.properties里配置 #session超时时间,低于60秒按60秒server.sess ...

  7. Android 开发工具类 29_sendPOSTRequest

    sendPOSTRequest 业务类 package com.wangjialin.internet.userInformation.service; import java.io.OutputSt ...

  8. lintcode-->哈希函数

    在数据结构中,哈希函数是用来将一个字符串(或任何其他类型)转化为小于哈希表大小且大于等于零的整数.一个好的哈希函数可以尽可能少地产生冲突.一种广泛使用的哈希函数算法是使用数值33,假设任何字符串都是基 ...

  9. [学习笔记] Miller-Rabin质数测试 & Pollard-Rho质因数分解

    目录 Miller-Rabin质数测试 & Pollard-Rho质因数分解 Miller-Rabin质数测试 一些依赖的定理 实现以及正确率 Pollard-Rho质因数分解 生日悖论与生日 ...

  10. Linux下编译ffmpeg并用GDB调试

    1.在Ubuntu界面上调处命令行界面,最方便的方式是使用快捷键Ctrl+Alt+T. 2.安装SDL SDL是一个开源的多媒体开发库,可以设置图像和视频的绘制等操作.如果不安装SDL,FFMPEG将 ...