Android 使用SAX读取XML文件
2013-04-13 15:49
483 查看
SAX是一个解析速度快并且占用内存少的xml解析器,非常适合用于Android等移动设备。关于它的详细介绍请参考http://www.saxproject.org/
SAX解析XML文件采用的是事件驱动,也就是说,它并不需要解析完整个文档,在按内容顺序解析文档的过程中,SAX会判断当前读到的字符是否合法XML语法中的某部分,如果符合就会触发事件。所谓事件,其实就是一些回调(callback)方法,这些方法(事件)定义在ContentHandler接口。
下面是一些ContentHandler接口常用的方法:
startDocument() 当遇到文档的开头的时候,调用这个方法,可以在其中做一些预处理的工作。
endDocument() 和上面的方法相对应,当文档结束的时候,调用这个方法,可以在其中做一些善后的工作。
startElement(String namespaceURI, String localName, String qName, Attributes atts) 当读到一个开始标签的时候,会触发这个方法。namespaceURI就是命名空间,localName是不带命名空间前缀的标签名,qName是带命名空间前缀的标签名。通过atts可以得到所有的属性名和相应的值。要注意的是SAX中一个重要的特点就是它的流式处理,当遇到一个标签的时候,它并不会纪录下以前所碰到的标签,也就是说,在startElement()方法中,所有你所知道的信息,就是标签的名字和属性,至于标签的嵌套结构,上层标签的名字,是否有子元属等等其它与结构相关的信息,都是不得而知的,都需要你的程序来完成。这使得SAX在编程处理上没有DOM来得那么方便。
endElement(String uri, String localName, String name) 这个方法和上面的方法相对应,在遇到结束标签的时候,调用这个方法。
characters(char[] ch, int start, int length) 这个方法用来处理在XML文件中读到的内容,第一个参数用于存放文件的内容,后面两个参数是读到的字符串在这个数组中的起始位置和长度,使用new String(ch,start,length)就可以获取内容。
假设我们要解析的xml文件内容如下:
解析itcast.xml触发的事件为:
读到的标签及内容 触发事件
{文档开始} startDocument()
<persons> startElement(, "persons", null, "{Attributes}")
"\n\t" characters("<persons>...</persons>", "12", "2")
<person> startElement(, "person", null, "{Attributes}")
"\n\t\t" characters("<persons>...</persons>", "31", "3")
<name> startElement(, "name", null, "{Attributes}")
"李明" characters("<persons>...</persons>", "40", "2")
</name> endElement("", "name", null)
"\n\t\t" characters("<persons>...</persons>", "50", "3")
<age> startElement(, "age", null, "{Attributes}")
"30" characters("<persons>...</persons>", "58", "2")
</age> endElement("", "age", null)
"\n\t" characters("<persons>...</persons>", "67", "2")
</person> endElement("", "person", null)
"\n\t" characters("<persons>...</persons>", "79", "2")
<person> startElement(, "person", null, "{Attributes}")
"\n\t\t" characters("<persons>...</persons>", "98", "3")
<name> startElement(, "name", null, "{Attributes}")
"李向梅" characters("<persons>...</persons>", "107", "3")
</name> endElement("", "name", null)
"\n\t\t" characters("<persons>...</persons>", "118", "3")
<age> startElement(, "age", null, "{Attributes}")
"25" characters("<persons>...</persons>", "126", "2")
</age> endElement("", "age", null)
"\n\t" characters("<persons>...</persons>", "135", "2")
</person> endElement("", "person", null)
"\n" characters("<persons>...</persons>", "147", "1")
</persons> endElement("", "persons", null)
{文档结束} endDocument()
下面我们给出一个读取xml文件的实例:
首先新建一个person类,用来存放xml结构的数据
person.java
然后继承ContentHandler,并重载用到的函数:
XMLContentHandler.java
然后在mianAcitvity里添加一个解析xml的API readXml
最终须有在mainAcitvity里测试该接口能否完成任务:
MainActivity.java
至此,基本完成使用SAX解析xml的完整例子。
该demo运行的结果是可以从log中看到 xml里保存的两个person 的in、name、 age。
SAX解析XML文件采用的是事件驱动,也就是说,它并不需要解析完整个文档,在按内容顺序解析文档的过程中,SAX会判断当前读到的字符是否合法XML语法中的某部分,如果符合就会触发事件。所谓事件,其实就是一些回调(callback)方法,这些方法(事件)定义在ContentHandler接口。
下面是一些ContentHandler接口常用的方法:
startDocument() 当遇到文档的开头的时候,调用这个方法,可以在其中做一些预处理的工作。
endDocument() 和上面的方法相对应,当文档结束的时候,调用这个方法,可以在其中做一些善后的工作。
startElement(String namespaceURI, String localName, String qName, Attributes atts) 当读到一个开始标签的时候,会触发这个方法。namespaceURI就是命名空间,localName是不带命名空间前缀的标签名,qName是带命名空间前缀的标签名。通过atts可以得到所有的属性名和相应的值。要注意的是SAX中一个重要的特点就是它的流式处理,当遇到一个标签的时候,它并不会纪录下以前所碰到的标签,也就是说,在startElement()方法中,所有你所知道的信息,就是标签的名字和属性,至于标签的嵌套结构,上层标签的名字,是否有子元属等等其它与结构相关的信息,都是不得而知的,都需要你的程序来完成。这使得SAX在编程处理上没有DOM来得那么方便。
endElement(String uri, String localName, String name) 这个方法和上面的方法相对应,在遇到结束标签的时候,调用这个方法。
characters(char[] ch, int start, int length) 这个方法用来处理在XML文件中读到的内容,第一个参数用于存放文件的内容,后面两个参数是读到的字符串在这个数组中的起始位置和长度,使用new String(ch,start,length)就可以获取内容。
假设我们要解析的xml文件内容如下:
<?xml version="1.0" encoding="UTF-8"?> <persons> <person id="23"> <name>李明</name> <age>30</age> </person> <person id="20"> <name>李向梅</name> <age>25</age> </person> </persons>
解析itcast.xml触发的事件为:
读到的标签及内容 触发事件
{文档开始} startDocument()
<persons> startElement(, "persons", null, "{Attributes}")
"\n\t" characters("<persons>...</persons>", "12", "2")
<person> startElement(, "person", null, "{Attributes}")
"\n\t\t" characters("<persons>...</persons>", "31", "3")
<name> startElement(, "name", null, "{Attributes}")
"李明" characters("<persons>...</persons>", "40", "2")
</name> endElement("", "name", null)
"\n\t\t" characters("<persons>...</persons>", "50", "3")
<age> startElement(, "age", null, "{Attributes}")
"30" characters("<persons>...</persons>", "58", "2")
</age> endElement("", "age", null)
"\n\t" characters("<persons>...</persons>", "67", "2")
</person> endElement("", "person", null)
"\n\t" characters("<persons>...</persons>", "79", "2")
<person> startElement(, "person", null, "{Attributes}")
"\n\t\t" characters("<persons>...</persons>", "98", "3")
<name> startElement(, "name", null, "{Attributes}")
"李向梅" characters("<persons>...</persons>", "107", "3")
</name> endElement("", "name", null)
"\n\t\t" characters("<persons>...</persons>", "118", "3")
<age> startElement(, "age", null, "{Attributes}")
"25" characters("<persons>...</persons>", "126", "2")
</age> endElement("", "age", null)
"\n\t" characters("<persons>...</persons>", "135", "2")
</person> endElement("", "person", null)
"\n" characters("<persons>...</persons>", "147", "1")
</persons> endElement("", "persons", null)
{文档结束} endDocument()
下面我们给出一个读取xml文件的实例:
首先新建一个person类,用来存放xml结构的数据
person.java
package com.example.xmlparsedemo; public class Person { private Integer id; private String name; private Short age; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Short getAge() { return age; } public void setAge(Short age) { this.age = age; } }
然后继承ContentHandler,并重载用到的函数:
XMLContentHandler.java
package com.example.xmlparsedemo; import java.util.ArrayList; import java.util.List; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class XMLContentHandler extends DefaultHandler { private List<Person> persons = null; private Person currentPerson; private String tagName = null;//当前解析的元素标签 public List<Person> getPersons() { return persons; } /* * 接收文档的开始的通知。 */ @Override public void startDocument() throws SAXException { persons = new ArrayList<Person>(); } /* * 接收字符数据的通知。 */ @Override public void characters(char[] ch, int start, int length) throws SAXException { if(tagName!=null){ String data = new String(ch, start, length); if(tagName.equals("name")){ this.currentPerson.setName(data); }else if(tagName.equals("age")){ this.currentPerson.setAge(Short.parseShort(data)); } } } /* * 接收元素开始的通知。 * 参数意义如下: * namespaceURI:元素的命名空间 * localName :元素的本地名称(不带前缀) * qName :元素的限定名(带前缀) * atts :元素的属性集合 */ @Override public void startElement(String uri, String localName, String qName,Attributes attributes)throws SAXException { if(localName.equals("person")){ currentPerson = new Person(); currentPerson.setId(Integer.parseInt(attributes.getValue("id"))); } this.tagName = localName; } /* * 接收文档的结尾的通知。 * 参数意义如下: * uri :元素的命名空间 * localName :元素的本地名称(不带前缀) * name :元素的限定名(带前缀) * */ @Override public void endElement(String uri, String localName, String name) throws SAXException { if(localName.equals("person")){ persons.add(currentPerson); currentPerson = null; } this.tagName = null; } }
然后在mianAcitvity里添加一个解析xml的API readXml
public static List<Person> readXML(InputStream inStream) { try { SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser saxParser = spf.newSAXParser(); //创建解析器 //设置解析器的相关特性,http://xml.org/sax/features/namespaces = true 表示开启命名空间特性 //saxParser.setProperty("http://xml.org/sax/features/namespaces",true); XMLContentHandler handler = new XMLContentHandler(); saxParser.parse(inStream, handler); inStream.close(); return handler.getPersons(); } catch (Exception e) { e.printStackTrace(); } return null; }}
最终须有在mainAcitvity里测试该接口能否完成任务:
MainActivity.java
package com.example.xmlparsedemo; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.net.URL; import java.util.List; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import android.os.Bundle; import android.app.Activity; import android.util.Log; import android.view.Menu; public class MainActivity extends Activity { private List<Person> persons = null; private Person p=null; public static List<Person> readXML(InputStream inStream) { try { SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser saxParser = spf.newSAXParser(); //创建解析器 //设置解析器的相关特性,http://xml.org/sax/features/namespaces = true 表示开启命名空间特性 //saxParser.setProperty("http://xml.org/sax/features/namespaces",true); XMLContentHandler handler = new XMLContentHandler(); saxParser.parse(inStream, handler); inStream.close(); return handler.getPersons(); } catch (Exception e) { e.printStackTrace(); } return null; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); InputStream r =null; r= getClass().getResourceAsStream("test.xml"); if (r==null) { Log.v("com.example.exlparsedemo", "file not found"); return; } URL url = getClass().getResource("test.xml"); String path= url.getPath(); persons=readXML(r); if(null!=persons) { for(int i=0;i<persons.size();i++) { p=persons.get(i); Log.v("id", p.getId().toString()); Log.v("name", p.getName()); Log.v("age", p.getAge().toString()); } } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_main, menu); return true; } }
至此,基本完成使用SAX解析xml的完整例子。
该demo运行的结果是可以从log中看到 xml里保存的两个person 的in、name、 age。
相关文章推荐
- Android --- 使用SAX读取xml文件
- 使用SAX读取XML文件
- Android 使用SAX或者DOM或者pull解析XML文件
- android_xml解析之 使用SAX读取XML文件
- 使用SAX读取XML文件的练习--(将读取的XML文件原样输出)
- android 实用sax 读取xml文件内容
- android_xml解析之 使用PULL读取XML文件 .
- android 实用sax 读取xml文件内容 附源码
- Android_Sax引擎读取xml文件
- Android下使用TinyXml读取xml配置文件(Cocos2d-x游戏开发)
- android应用面试宝典(下);用自定义组件控制循环组件使用bug还添加标志显示答案标志位;通过包名读取配置文件AndroidManifest.xml
- 使用SAX或者DOM或者pull读取XML文件
- android 使用Sax 读取xml
- android 实用sax 读取xml文件内容
- [libexpat]_[XML处理]_[C/C++使用libexpat库以数据流(SAX模型)的方式读取(解析)大XML文件]
- Android下使用TinyXml读取xml配置文件(Cocos2d-x游戏开发)
- [libexpat]_[XML处理]_[C/C++使用libexpat库以数据流(SAX模型)的方式读取(解析)大XML文件]
- android学习——使用SAX、DOM 和 PULL 解析xml文件,及使用pull生成xml文件
- Android读取资源文件——读取原始Xml内容和使用Menu文件
- Android下使用pull解析器生成XML文件、读取XML文件