XML:可扩展标记语言。一般用于数据存储,SharedPreference就是使用xml文件保存信息的,SQLite底层也是xml文件,在网络方面通常作为信息的载体,把数据包装成xml来传递。

XML解析方式:SAX、DOM、PULL。

SAX解析XML数据

  SAX解析速度快,占用内存少,非常适合Android等移动设备。SAX解析采用的是事件驱动,不需要解析整个文档,而是在解析过程中,判断读到的字符是否符合xml语法的某个部分(文档开始、结束,标签开始、结束),符合则出触发事件(回调方法),这些方法定义在ContentHandler接口中,为便于使用Android提供了一个DefaultHandler帮助类,只要继承这个类,重写相应的方法即可。

  重写的方法:

    startDocument():文档开始时触发,做初始化工作。

    endDocument():文档结束时触发,完成善后工作。

    startElement():元素开始时触发。

    endElement():元素结束时触发。  

    characters(ch,start,length):处理在xml中读到的内容,ch存放文件内容、start和length读到内容在数组中的起始位置和长度。使用new String(ch,start,length)可以获取内容。

  核心代码

public class SaxHelper extends DefaultHandler {
private Person person;
private ArrayList<Person> persons; //当前解析的元素标签
private String tagName = null; /**
* 当读取到文档开始标志是触发,通常在这里完成一些初始化操作
* @throws SAXException
*/
@Override
public void startDocument() throws SAXException {
this.persons = new ArrayList<Person>();
Log.i("SAX", "读取到文档头,开始解析xml"); } /**
* 读到一个开始标签时调用,第二个参数为标签名,最后一个参数为属性数组
* @param uri
* @param localName
* @param qName
* @param attributes
* @throws SAXException
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (localName.equals("person")){
person = new Person();
person.setId(Integer.parseInt(attributes.getValue("id")));
Log.i("SAX", "开始处理person元素~"); }
this.tagName = localName; } /**
* 读到到内容,第一个参数为字符串内容,后面依次为起始位置与长度
* @param ch
* @param start
* @param length
* @throws SAXException
*/
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
//判断当前标签是否有效
if (this.tagName != null){
String data = new String(ch, start, length); //读取标签中的内容
if (this.tagName.equals("name")){
this.person.setName(data);
Log.i("SAX", "处理name元素内容"); }else if (this.tagName.equals("age")){
this.person.setAge(Integer.parseInt(data));
Log.i("SAX", "处理age元素内容"); } } } /**
* 处理元素结束时触发,这里将对象添加到结合中
* @param uri
* @param localName
* @param qName
* @throws SAXException
*/
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (localName.equals("person")){
this.persons.add(person);
person = null;
Log.i("SAX", "处理person元素结束~"); }
this.tagName = null; } /**
* 读取到文档结尾时触发,
* @throws SAXException
*/
@Override
public void endDocument() throws SAXException {
super.endDocument();
Log.i("SAX", "读取到文档尾,xml解析结束");
} //获取persons集合
public ArrayList<Person> getPersons(){
return persons;
} }

在MainActivity.java中写上这样一个方法,然后要解析XML的时候调用下

private ArrayList<Person> readxmlForSAX() throws Exception { 

      //获取文件资源建立输入流对象
InputStream is = getAssets().open("person1.xml"); //①创建XML解析处理器
SaxHelper ss = new SaxHelper(); //②得到SAX解析工厂
SAXParserFactory factory = SAXParserFactory.newInstance(); //③创建SAX解析器
SAXParser parser = factory.newSAXParser(); //④将xml解析处理器分配给解析器,对文档进行解析,将事件发送给处理器
parser.parse(is, ss); is.close();
return ss.getPersons();
}

DOM解析XML数据

  DOM解析xml文件时,会将文件中所有内容以文档树的形式存放到内存中,然后使用DOM API遍历、检索数据。DOM解析比较直观,编码较为简单,但是内存消耗大。

  DOM中的api:

    DocumentBuilderFactory()(解析工厂类):创建:DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();

    DocumentBuilder(解析器类):通过解析工厂来获得:DocumentBuilder dbBuilder = dbFactory.newDocumentBuilder();

    Document(文档树模型):将要解析的xml文件读入DOM解析器Document doc = dbBuilder.parse(context.getAssets().open("person2.xml"));

    NodeList(结点列表类):含有方法:item(index)、getLength()

    Node()(结点类):DOM中最基本的对象,抽象结点,一般使用它的子对象,Element、Attr、Text等

    Element()(元素类):方法:getAttribute()、getTagName()

    Attr()(属性类):某个元素的属性。

  核心代码

public class DomHelper {
public static ArrayList<Person> queryXML(Context mContent){ ArrayList<Person> persons = new ArrayList<Person>(); try {
//①获得DOM解析器的工厂示例:
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); //②从Dom工厂中获得dom解析器
DocumentBuilder builder = dbFactory.newDocumentBuilder(); //③把要解析的xml文件读入Dom解析器
Document document = builder.parse(mContent.getAssets().open("person2.xml"));
System.out.println("处理该文档的DomImplemention对象=" + document.getImplementation()); //④得到文档中名称为person的元素的结点列表
NodeList nodeList = document.getElementsByTagName("person"); //⑤遍历该集合,显示集合中的元素以及子元素的名字
for (int i = 0; i < nodeList.getLength(); i ++){
//先从Person元素开始解析
Element personElement = (Element)nodeList.item(i);
Person person = new Person();
person.setId(Integer.valueOf(personElement.getAttribute("id"))); //获取person下的name和age的Note集合
NodeList childList = personElement.getChildNodes();
for (int j = 0; j < childList.getLength(); j ++){ Node childNode = childList.item(j); //判断子note类型是否为元素Note
if (childNode.getNodeType() == Node.ELEMENT_NODE){ Element childElement = (Element)childNode; if ("name".equals(childElement.getNodeName())){
person.setName(childElement.getFirstChild().getNodeValue()); }else if("age".equals(childElement.getNodeName())){
person.setAge(Integer.valueOf(childElement.getFirstChild().getNodeValue())); } } }
persons.add(person); } } catch (Exception e) {
e.printStackTrace();
}
return persons; }

PULL解析XML数据

  Android中内置了PULL解析器,PULL解析同样采用事件驱动,编码简单,只需处理开始和结束事件,通常使用switch语句,根据事件的类型,匹配不同的处理方法。

  事件类型:START_DOCUMENT、START_TAG、TEXT、END_TAG、END_DOCUMENT。

  PULL解析返回的是数字,需要我们自己获取产生的事件,然后做相应的操作。

  PULL解析xml文件流程: 

public static ArrayList<Person> getPersons(InputStream xml) throws Exception{
  ArrayList<Person> persons = null;
  Person person = null;
  // 1、创建一个xml解析的工厂
XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); //2、获得xml解析类的引用
XmlPullParser parser = factory.newPullParser();
parser.setInput(xml, "UTF-8"); //3、获得事件的类型
int eventType = parser.getEventType();
  //4、用switch对不同的事件进行不同的处理
while (eventType != XmlPullParser.END_DOCUMENT){
switch (eventType){
case XmlPullParser.START_DOCUMENT:{
persons = new ArrayList<Person>();
break; }
case XmlPullParser.START_TAG:{
if ("person".equals(parser.getName())){
person = new Person(); // 取出属性值
int id = Integer.parseInt(parser.getAttributeValue(0));
person.setId(id); }else if("name".equals(parser.getName())){
// 获取该节点的内容
String name = parser.nextText();
person.setName(name); }else if("age".equals(parser.getName())){
int age = Integer.parseInt(parser.nextText());
person.setAge(age); }
break; }
case XmlPullParser.END_TAG:{
if ("person".equals(parser.getName())){
persons.add(person);
person = null; }
break; } }
eventType = parser.next(); }
return persons; }

PULL生成xml文件流程

public static void save(List<Person> persons, OutputStream outputStream) throws Exception{
  //创建XmlSerializer实例
XmlSerializer serializer = Xml.newSerializer();
  //为XmlSerializer设置输入流和编码格式
serializer.setOutput(outputStream, "UTF-8");
  //设置xml的编码格式
serializer.startDocument("UTF-8", true);
  //设置根元素
serializer.startTag(null, "persons");
  //遍历元素依次写入标签和属性
for (Person person: persons) {
serializer.startTag(null, "person");
serializer.attribute(null, "id", person.getId() + ""); serializer.startTag(null, "name");
serializer.text(person.getName());
serializer.endTag(null, "name"); serializer.startTag(null, "age");
serializer.text(person.getAge() + "");
serializer.endTag(null, "age");

    //设置完结元素标签
serializer.endTag(null, "person"); }
serializer.endTag(null, "persons");
  //结束文档
serializer.endDocument();
  //flush()刷新,将数据写入文件,关闭输出流
outputStream.flush();
outputStream.close();
}

参考文献:http://www.jianshu.com/p/2fe796ca638c                        

    

最新文章

  1. 如何安全的将VMware vCenter Server使用的SQL Server Express数据库平滑升级到完整版
  2. Yocto开发笔记之《串口驱动调试》(QQ交流群:519230208)
  3. [ JS 进阶 ] test, exec, match, replace
  4. clearfix清除浮动进化史
  5. PHP Zend Studio9.0怎么把代码搞成和服务器端的同步(就是直接在服务器端修改)
  6. Perfect Squares
  7. 习题3.10 约瑟夫环 josephus问题
  8. Qt 5中信号和槽的新语法
  9. node服务端口被占用Error listen EADDRINUSE :::3000
  10. MariaDB报错Plugin &#39;InnoDB&#39; init function returned error.解决方案
  11. Ubuntu14.04 安装 Sublime Text 3
  12. [HNOI2019]校园旅行
  13. January 03rd, 2018 Week 01st Wednesday
  14. Fedora 19安装mysql
  15. pip 报错
  16. PAT 乙级 1062 最简分数(20) C++版
  17. Entity Framework 入门:准备工作
  18. Storm Trident API
  19. ES6----Proxy(一)
  20. 关于anroid设置webview背景方法探讨(转)

热门文章

  1. Asynchronous Programming Model (APM)异步编程模型
  2. Model/ModelMap 和 ModelAndView 的区别使用
  3. qt Cannot connect creator comm socket /tmp/qt_temp.S26613/stub-socket: No such
  4. CSS3全新的背景图片方案
  5. kmp&amp;扩展kmp
  6. translate函数
  7. SQL竖列变横列
  8. jQuery 参数详解
  9. 如何在未越狱的ios系统安装ipa文件
  10. iOS-----MFMessageCompose 和 MFMailComposeViewController的使用方法