Introduce
xml 是目前使用范围最广的数据传输类型。这几天在弄的一个项目,就是用xml来进行数据传输的,所以特地把所有的xml 解析方式进行学习总结一下。
DOM 方式解析
Dom方式解析是将整个xml文档一次性全部读取出来,进行解析。可以想象在读入的时候,就已经将整个文档解析好了,之后可以任意地去读取出来了。
优点
这种方式很显然,读取出来方便,写入也方便。
缺点
一次性就将整个文档读取了,so,比较耗费内存。如果文档特别大,那就比较窘迫了。所以该解析方式适合文档相对较小的。对于手机,显然不合适。
代码Sample
xml文档:
<?xml version="1.0" encoding="utf-8"?>
<sample>
<item id="0" >DOM</item>
<item id="1" >SAX</item>
<item id="2" >Pull</item>
</sample>
以下代码都是从网上参考来的,仅供参考。
public static List<channel> getChannelList(InputStream stream)
{
List<channel> list=new ArrayList<channel>();
//得到 DocumentBuilderFactory 对象, 由该对象可以得到 DocumentBuilder 对象
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
try {
//得到DocumentBuilder对象
DocumentBuilder builder=factory.newDocumentBuilder();
//得到代表整个xml的Document对象
Document document=builder.parse(stream);
//得到 "根节点"
Element root=document.getDocumentElement();
//获取根节点的所有items的节点
NodeList items=root.getElementsByTagName("item");
//遍历所有节点
for(int i=0;i<items.getLength();i++)
{
channel chann=new channel();
Element item=(Element)items.item(i);
chann.setId(item.getAttribute("id"));
chann.setUrl(item.getAttribute("url"));
chann.setName(item.getFirstChild().getNodeValue());
list.add(chann);
}
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return list;
}
SAX 方式解析
sax 方式解析,是基于事件驱动的。它分成两部分,一个是xml解析器,一个事件处理器。分别对应XMLReader 和 Handler。
优点
sax不用一次性读取整个文档,很显然基于事件驱动,可以不用一次性耗费那么内存。而且,SAX解析方式更加具有结构性将xml解析器跟事件处理区分开,有人说会更麻烦,个人觉得见人见智吧,其实结构性好了,更方便使用。
缺点
一个节点一个节点地读入,如果遇到文档小,显然没有Dom那么方便。
Sample
private List<Sample> getSampleList() throws ParserConfigurationException, SAXException, IOException
{
//实例化一个SAXParserFactory对象
SAXParserFactory factory=SAXParserFactory.newInstance();
SAXParser parser;
//实例化SAXParser对象,创建XMLReader对象,解析器
parser=factory.newSAXParser();
XMLReader xmlReader=parser.getXMLReader();
//实例化handler,事件处理器
SAXPraserHelper helperHandler=new SAXPraserHelper();
//解析器注册事件
xmlReader.setContentHandler(helperHandler);
//读取文件流
InputStream stream=getResources().openRawResource(R.raw.channels);
InputSource is=new InputSource(stream);
//解析文件
xmlReader.parse(is);
return helperHandler.getList();
}
handle
public class SAXPraserHelper extends DefaultHandler {
final int ITEM = 0x0005;
List<Sample> list;
channel chann;
int currentState = 0;
public List<Sample> getList() {
return list;
}
/*
* 接口字符块通知
*/
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
// super.characters(ch, start, length);
String theString = String.valueOf(ch, start, length);
if (currentState != 0) {
chann.setName(theString);
currentState = 0;
}
return;
}
/*
* 接收文档结束通知
*/
@Override
public void endDocument() throws SAXException {
// TODO Auto-generated method stub
super.endDocument();
}
/*
* 接收标签结束通知
*/
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
// TODO Auto-generated method stub
if (localName.equals("item"))
list.add(chann);
}
/*
* 文档开始通知
*/
@Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
list = new ArrayList<Sample>();
}
/*
* 标签开始通知
*/
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
chann = new channel();
if (localName.equals("item")) {
for (int i = 0; i < attributes.getLength(); i++) {
if (attributes.getLocalName(i).equals("id")) {
chann.setId(attributes.getValue(i));
} else if (attributes.getLocalName(i).equals("url")) {
chann.setUrl(attributes.getValue(i));
}
}
currentState = ITEM;
return;
}
currentState = 0;
return;
}
Pull 方式解析
也是基于事件驱动的,但是与sax不同。它是开始解析后,可以一次一次地调用next来获取下一个解析事件,这样就多了自主地控制了。
优点
从某些角度上来看,Pull显然是要简单些。
缺点
跟SAX 优点类似吧。
Sample
private List<Map<String, String>> getData() {
List<Map<String, String>> list = new ArrayList<Map<String, String>>();
XmlResourceParser xrp = getResources().getXml(R.xml.channels);
try {
// 直到文档的结尾处
while (xrp.getEventType() != XmlResourceParser.END_DOCUMENT) {
// 如果遇到了开始标签
if (xrp.getEventType() == XmlResourceParser.START_TAG) {
String tagName = xrp.getName();// 获取标签的名字
if (tagName.equals("item")) {
Map<String, String> map = new HashMap<String, String>();
String id = xrp.getAttributeValue(null, "id");// 通过属性名来获取属性值
map.put("id", id);
map.put("name", xrp.nextText());
list.add(map);
}
}
xrp.next();// 获取解析下一个事件
}
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return list;
}
参考
- http://www.cnblogs.com/JerryWang1991/archive/2012/02/24/2365507.html
小悟诗词
穷则变,变则通,通则久 —《周易·系辞下》