SAX解析XML

本帖最后由 JenMinZhang 于 2012-11-6 13:47 编辑


       1.  SAX解析XML简单介绍 :SAX是 Simple API for XML(XML 简单应用程序接口),是一个公共的基于事件的XML文档解析标准。它以事件作为解析XML 文件的模式,   将 XML 文件转化成一系列的事件,由不同的事件处理器来决定如何处理。
          SAX是一个解析速度快并且占用内存少的xml解析器,非常适合android等移动设备,SAX解析XML文件采用的是事件驱动,也就是说,它并不需要解析完整个文档,在按内容顺序解析文档的过程中,SAX会判断当前读取到的字符是否合法xml语法中的某部分,如果符合就会触发事件。
                                                                                             解析流程:
    
sax.png 




2.使用SAX解析网络XML:
(1)准备工作:
寻找要解析的XML文件网络路径,可以使用网络路径为:
http://www.w3school.com.cn/example/xmle/plant_catalog.xml  
(2)XML文件对应Model:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import java.io.Serializable;
 
public class Plant implements Serializable {
         /**
          *
          */
         private static final long serialVersionUID = 1L;
         
         private String common= "" ;
         private String botanical= "" ;
         private String  zone= "" ;
         private String price= "" ;
         private String availability= "" ;
         
         public String getCommon() {
                 return common;
         }
         public void setCommon(String common) {
                 this .common = common;
         }
         public String getBotanical() {
                 return botanical;
         }
         public void setBotanical(String botanical) {
                 this .botanical = botanical;
         }
         public String getZone() {
                 return zone;
         }
         public void setZone(String zone) {
                 this .zone = zone;
         }
         public String getPrice() {
                 return price;
         }
         public void setPrice(String price) {
                 this .price = price;
         }
         public String getAvailability() {
                 return availability;
         }
         public void setAvailability(String availability) {
                 this .availability = availability;
         }
 
 
}

(3)助手类代码:
a.引入包 :
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
 
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
 
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

b.助手类代码:
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/**
  * 助手类 传递一个网络XML地址和一个对象实体类实例对象即可解析XML内容
  *
  * @author JenMinZhang
  */
public class SAXParserContentHandler extends DefaultHandler {
         private Object javaBean = null ;
         private String tag; // 标签名称
         List<Object> list = null ;
 
         /**
          * 用 SAX 解析xml文件
          *
          * @param strUrl
          *            网络xml地址
          * @param javaBean
          *            实体类对象
          * @return List 返回实体类的一个list集合
          * @throws Exception
          */
         public List<Object> parseReadXml(String strUrl, Object javaBean)
                         throws Exception {
                 this .javaBean = javaBean;
                 // 要从网络上获取xml,要定义一个URL类对象
                 URL url = new URL(strUrl);
                 // 打开连接,。会返回HttpsURLConnection 对象
                 HttpURLConnection httpsURLConnection = (HttpURLConnection) url
                                 .openConnection();
                 // 现在是使用HTTP协议请求服务器的数据
                 // 所以要设置请求方式
                 httpsURLConnection.setRequestMethod( "GET" );
                 // 设置 超时时间 为5秒
                 httpsURLConnection.setConnectTimeout( 5 * 1000 );
                 // 通过输入流获取网络xml内容
                 // 取得输入流
                 InputStream inputStream = httpsURLConnection.getInputStream();
                 SAXParserFactory parserFactory = SAXParserFactory.newInstance();
                 // 取得SAXParser 实例
                 SAXParser parser = parserFactory.newSAXParser();
                 parser.parse(inputStream, this );
                 return list;
 
         }
 
         @Override
         public void characters( char [] ch, int start, int length)
                         throws SAXException {
                 if ( null != tag && ! "" .equals(tag)) {
                         if (javaBean != null ) {
                                 String data = new String(ch, start, length);
                                 Field[] fields = javaBean.getClass().getDeclaredFields();
                                 for ( int i = 0 ; i < fields.length; i++) {
                                         if (tag.equalsIgnoreCase(fields[i].getName())) {
                                                 setAttribute(javaBean, fields[i].getName(), data,
                                                                 new Class[] { fields[i].getType() });
                                         }
 
                                 }
 
                         }
 
                 }
 
         }
 
         @Override
         public void endDocument() throws SAXException {
         }
 
         @Override
         public void endElement(String uri, String localName, String qName)
                         throws SAXException {
                 if ( null != localName && ! "" .equals(localName)) {
                         String bean = updateSmall(javaBean.getClass().getSimpleName());
                         if (bean.equalsIgnoreCase(localName) && bean != null ) {
                                 list.add(javaBean);
                         }
                 }
                 tag = null ;
         }
 
         @Override
         public void startDocument() throws SAXException {
 
                 // TODO Auto-generated method stub
 
                 list = new ArrayList<Object>();
 
         }
 
         @Override
         public void startElement(String uri, String localName, String qName,
                         Attributes attributes) throws SAXException {
                 tag = qName;
                 // 取得实体类简单名称,把首字母变为小 写
                 String bean = updateSmall(javaBean.getClass().getSimpleName());
                 // 取得实体类的 全限 名称
                 String clazz = javaBean.getClass().getName();
                 if (bean.equalsIgnoreCase(qName)) {
                         try {
                                 javaBean = Class.forName(clazz).newInstance();
                         } catch (Exception e) {
                                 e.printStackTrace();
                         }
                         Field[] fields = javaBean.getClass().getDeclaredFields();
                         for ( int i = 0 ; i < attributes.getLength(); i++) {
                                 for ( int j = 0 ; j < fields.length; j++) {
                                         if (attributes.getQName(i).equalsIgnoreCase(fields[j].getName())) {
                                                 setAttribute(javaBean, attributes.getQName(i),
                                                                 attributes.getValue(i),
                                                                 new Class[] { fields[j].getType() });
                                         }
                                 }
                         }
                 }
         }
 
         /**
          * @param object
          *            类
          * @param setName
          *            方法名
          * @param setValue方法设置
          * @param obj
          *            属性类型
          * @throws Exception
          */
         public void setAttribute(Object object, String setName,
                         String setValue, Class[] obj) {
                 Method method;
                 try {
                         method = object.getClass().getMethod(
                                         "set" + updateStr(setName), obj[ 0 ]);
                         if (obj[ 0 ].equals(Integer. class ) || obj[ 0 ].equals( int . class )) {
                                 method.invoke(object, new Integer(setValue));
                         }
                         if (obj[ 0 ].equals(Float. class ) || obj[ 0 ].equals( float . class )) {
                                 method.invoke(object, new Float(setValue));
                         }
                         if (obj[ 0 ].equals(Short. class ) || obj[ 0 ].equals( short . class )) {
                                 method.invoke(object, new Short(setValue));
                         }
                         if (obj[ 0 ].equals(Byte. class ) || obj[ 0 ].equals( byte . class )) {
                                 method.invoke(object, new Byte(setValue));
                         }
                         if (obj[ 0 ].equals(Double. class ) || obj[ 0 ].equals( double . class )) {
                                 method.invoke(object, new Double(setValue));
                         }
                         if (obj[ 0 ].equals(Date. class )) {
                                 method.invoke(object, new Date( new Long(setValue)));
                         }
                         if (obj[ 0 ].equals(java.util.Date. class )) {
                                 method.invoke(object, new java.util.Date(setValue));
                         }
                         if (obj[ 0 ].equals(Long. class ) || obj[ 0 ].equals( long . class )) {
                                 method.invoke(object, new Long(setValue));
                         }
                         if (obj[ 0 ].equals(Boolean. class )
                                         || obj[ 0 ].equals( boolean . class )) {
                                 method.invoke(object, new Boolean(setValue));
                         }
                         if (obj[ 0 ].equals(String. class )) {
                                 method.invoke(object, setValue);
                         }
                 } catch (Exception e) {
                         e.printStackTrace();
                 }
 
         }
 
         /**
          * 把字符串的首字母改为大写
          *
          * @param str
          * @return String
          */
         public String updateStr(String str) {
                 char c = ( char ) (str.charAt( 0 ) - 32 );
                 String s = str.substring( 1 , str.length());
                 return c + s;
         }
 
         /**
          * 把字符串的首字母改为小写
          *
          * @param str
          * @return String
          */
 
         public String updateSmall(String str) {
                 char c = ( char ) (str.charAt( 0 ) + 32 );
                 String s = str.substring( 1 , str.length());
                 return c + s;
         }
}

(4)权限配置 ,AndroidManifest.xml  配置权限代码:
1
2
<uses-permission android:name= "android.permission.INTERNET" />
<uses-permission android:name= "android.permission.ACCESS_WIFI_STATE" />

(5)解析测试:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@Override
protected void onCreate(Bundle savedInstanceState) {
 
         super .onCreate(savedInstanceState);
 
         setContentView(R.layout.activity_main);
 
         SAXParserContentHandler contentHandler = new SAXParserContentHandler();
 
         List<Object> list;
         Plant plant = new Plant();
         try {
                 SimpleDateFormat formatter = new SimpleDateFormat ( "yyyy-MM-dd HH:mm:ss S " );
                  
                 Date curDate = new Date(System.currentTimeMillis()); //获取当前时间
                  
                 String str = formatter.format(curDate);
                 System.out.println( " 开始时间为 :" +str );
         list = contentHandler.parseReadXml( "http://www.w3school.com.cn/example/xmle/plant_catalog.xml" ,plant);
         System.out.println( list.size()+ "  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA " );
                 for (Object object : list) {
                         Plant pants=(Plant )object;
                          System.out.println( "普通种类:" +pants.getCommon());
                          System.out.println( " 植物名称:" +pants.getBotanical() );
                         System.out.println( "地区:" +pants.getZone() );
                         System.out.println( "可用性:" +pants.getAvailability());
           Log.d( "Pull Helper" , "Pull Helpe:" +pants.getBotanical()+ "可用性:" +pants.getAvailability());
                         }
                 
                 Date curend = new Date(System.currentTimeMillis()); //获取当前时间
                  
                 String strend = formatter.format(curend);
                 System.out.println( " 结束时间为 :" +strend );
         } catch (Exception e) {
                 // System.out.println("   %%%%%%%%%%%%%%&&&&&&&&&&&&&&&&&&&&&&&     "+e.getMessage());
                 e.printStackTrace();
         }
 
}


3.应注意问题:
1)如果要解析网络XML文件,就需要在在AndroidManifest.xml  配置权限,代码为:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
如果不加权限代码会出现:
XML文法正常解析,使用LogCat可以再告警(W)中看到  Permission denied (没有权限;拒绝访问
)异常信息
2)如果XML文件放置在本地服务器(自己的PC机,XMl运行在其他环节中,如 JAVA ,PHP),在访问是需要设置静态IP地址,访问是使用静态IP地址访问:
如: http://192.85.1.235/mms/index.php?controller=default  
如果直接使用  http://localhost/mms/index.php?controller=default   就会报:Connection refused(连接拒绝)
3)如果使用助手类解析XML,在根据XML标签生成对应Model(实体)时,应注意,Model实体名称必须和目标根目录名称忽略大小后保持一致生成实体所定义的属性名称必须和XML目标标签下的属性标签名称保持一致:
<?xml version="1.0" encoding="UTF-8" ?> 
<CATALOG> 
<PLANT> 
<COMMON>Bloodroot</COMMON> 
<BOTANICAL>Sanguinaria canadensis</BOTANICAL>
<ZONE>4</ZONE> 
<LIGHT>Mostly Shady</LIGHT>
<PRICE>$2.44</PRICE> 
<AVAILABILITY>031599</AVAILABILITY> 
</PLANT>
</CATALOG>
       对应Model实体类名称应该为: Plant ,不然的话解析过程中不会报异常,只是解析结果为空,因为解析方法通过传递参数Model对象实例找到对应的Model类名称,并使用它调getClass().getDeclaredFields()获取实体中定义的属性(XML目标标签下的属性标签,如 name  ,price ,description);
      如果实体所定义的属性名称必须和XML目标标签下的属性标签名称保持不一样,就无法把XML标签内容赋值给对应实体的属性,对应实体属性解析结果为null ;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值