解析XML数据

写在前面:

测试的时候我申请了一个查询快递的接口,其返回的xml数据示例如下:

<root>
	<resultcode>200</resultcode>
	<reason>查询成功!</reason>
	<result>
		<company>顺丰</company>
		<com>sf</com>
		<no>575677355677</no>
                <status>0</status>
		<list>
			<item>
				<datetime>2013-06-25 10:44:05</datetime>
				<remark>已收件</remark>
				<zone>台州市</zone>
			</item>
			<item>
				<datetime>2013-06-25 11:05:21</datetime>
				<remark>快件在 台州 ,准备送往下一站 台州集散中心</remark>
				<zone>台州市</zone>
			</item>
			......
		</list>
	</result>
</root>

一、Pull解析方式

1.获取XmlPull解析工厂的实例,并通过它获取一个解析器

XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser = factory.newPullParser();

2.给解析器设置需要解析的数据

xmlPullParser.setInput(new StringReader(xmlData));

setInput()方法接收的是一个Reader对象,Demo中的网络请求采用的是上一篇文章通过http协议实现的,返回数据为String类型,这里通过StringReader将其封装一下即可。

3.开始逐个标签进行解析

int eventType = xmlPullParser.getEventType();
String dateTime = "";
String remark = "";
//开始解析数据
while(eventType!=XmlPullParser.END_DOCUMENT){
    String nodeName = xmlPullParser.getName();
    //Log.d(TAG, "parseNodeName:"+nodeName);
    switch (eventType){
        //开始解析某个节点
        case XmlPullParser.START_TAG:
            if("datetime".equals(nodeName)){
                dateTime = xmlPullParser.nextText();
            } else if("remark".equals(nodeName)){
                remark = xmlPullParser.nextText();
            }
            break;
        //完成解析某个节点
        case XmlPullParser.END_TAG:
            if("item".equals(nodeName)){
                stringBuilder.append("时间:"+dateTime+"\r\n"+"内容:"+remark+"\r\n");
            }
            break;
        default:
            break;
    }
    eventType = xmlPullParser.next();
}

其中,getEventType()方法可以得到当前的解析事件,然后在while循环中不断的进行逐个标签的解析。如果当前的解析事件不等于XmlPullParser.END_DOCUMENT,说明解析工作还没有完成,调用next()方法来获取下一个解析事件。在while循环中,我们通过getName()方法得到当前标签的名字,如果发现标签名是我们想要数据的标签名,就调用nextText()方法来获取标签体的内容。

二、SAX解析方式

1.新建一个类去继承DefaultHandler然后重写其中的5个方法

public class ContentHandler extends DefaultHandler {
    @Override
    public void startDocument() throws SAXException {
        super.startDocument();
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        super.startElement(uri, localName, qName, attributes);
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        super.characters(ch, start, length);
    }

    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        super.endElement(uri, localName, qName);
    }
}

2.根据需要读取的数据添加成员变量(其中contentResult用于存储读取结果)

private String nodeName;
private StringBuilder dateTime,remark,contentResult;

3.开始XML解析时初始化成员变量

//在开始XML解析的时候调用
@Override
public void startDocument() throws SAXException {
    dateTime = new StringBuilder();
    remark = new StringBuilder();
    contentResult = new StringBuilder();
}

4.解析标签时记录标签名

//在开始解析某个标签时调用
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
    nodeName = localName;
}

5.解析标签体时,根据标签名筛选出我们需要的数据并存入成员变量

//在解析标签体内容时调用
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
    if("datetime".equals(nodeName)){
        dateTime.append(ch, start, length);
    } else if("remark".equals(nodeName)){
        remark.append(ch, start, length);
    }
}

PS:在获取标签体中的内容时,characters()方法可能会被调用多次,一些换行符也被当作内容解析出来,需要针对该情况在代码中做好控制。

6.在解析完某个标签时,存储读取结果并清空临时数据

//在完成解析某个标签时调用
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
    if("item".equals(localName)){
        contentResult.append("时间:"+dateTime.toString().trim()+"\r\n"+"内容:"+remark.toString().trim()+"\r\n");
        //清空dateTime和remark避免影响下一条数据的读取
        dateTime.setLength(0);
        remark.setLength(0);
    }
}

完成ContentHandler的编写工作之后,就可以正式开始SAX解析了。

7.获取SAX解析工厂的实例,并通过它获取一个解析器

SAXParserFactory factory = SAXParserFactory.newInstance();
XMLReader xmlReader = factory.newSAXParser().getXMLReader();

8.创建一个我们之前自定义的ContentHandler实例,并将它设置给解析器

ContentHandler handler = new ContentHandler();
//将ContentHandler的实例设置到XMLReader中
xmlReader.setContentHandler(handler);

9.开始解析

xmlReader.parse(new InputSource(new StringReader(xmlData)));

同样的,xmlData为请求网络返回的String类型数据,将其封装为Reader类型之后传给解析器解析。

10.获取解析结果

handler.getResult().toString();

这里的getResult()方法是我自定义ContentHandler时,创建的一个用于获取解析结果的方法:

public StringBuilder getResult(){
    return contentResult;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值