溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

怎么在Android中使用SAX對XML數(shù)據(jù)進(jìn)行增刪改查操作

發(fā)布時間:2021-01-21 16:04:20 來源:億速云 閱讀:148 作者:Leah 欄目:移動開發(fā)

本篇文章為大家展示了怎么在Android中使用SAX對XML數(shù)據(jù)進(jìn)行增刪改查操作,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。

前言

解析XML的方式有很多種,大家比較熟悉的可能就是DOM解析。

DOM(文件對象模型)解析:解析器讀入整個文檔,然后構(gòu)建一個駐留內(nèi)存的樹結(jié)構(gòu),然后代碼就可以根據(jù)DOM接口來操作這個樹結(jié)構(gòu)了。

  優(yōu)點(diǎn):整個文檔讀入內(nèi)存,方便操作:支持修改、刪除和重現(xiàn)排列等多種功能。

  缺點(diǎn):將整個文檔讀入內(nèi)存中,保留了過多的不需要的節(jié)點(diǎn),浪費(fèi)內(nèi)存和空間。

  使用場合:一旦讀入文檔,還需要多次對文檔進(jìn)行操作,并且在硬件資源充足的情況下(內(nèi)存,CPU)。

為了解決DOM解析存在的問題,就出現(xiàn)了SAX解析。其特點(diǎn)為:

  優(yōu)點(diǎn):不用實現(xiàn)調(diào)入整個文檔,占用資源少。尤其在嵌入式環(huán)境中,如android,極力推薦使用SAX解析。

  缺點(diǎn):不像DOM解析一樣將文檔長期駐留在內(nèi)存中,數(shù)據(jù)不是持久的。如果事件過后沒有保存數(shù)據(jù),數(shù)據(jù)就會丟失。

  使用場合:機(jī)器有性能限制。

本文將給大家詳細(xì)介紹關(guān)于Android利用SAX對XML增刪改查的相關(guān)內(nèi)容,分享出來供大家參考學(xué)習(xí)價值,下面話不多說了,來一起看看詳細(xì)的介紹吧。

1.概述

SAX是一中事件驅(qū)動類型的XML解析方式。說白了,就是通過復(fù)寫一個Default類去告知,解析的結(jié)果。SAX并不會想DOM那樣把整個的XML加載到內(nèi)存中,而它會像IO流那樣,一個一個標(biāo)簽地去解析。

簡單地說就是對文檔進(jìn)行順序掃描,當(dāng)掃描到文檔(document)開始與結(jié)束、元素(element)開始與結(jié)束、文檔(document)結(jié)束等地方時通知事件處理函數(shù),由事件處理函數(shù)做相應(yīng)動作,然后繼續(xù)同樣的掃描,直至文檔結(jié)束。

為了方便說明,先約定好一個XML如下:

<?xml version="1.0" encoding="UTF-8"?>
<persons>
 <person id="1" key="33" type="type">
  <name>zhangsan</name>
  <age>21</age>
 </person>
</persons>

2.基本讀?。ú椋?/strong>

代碼如下

SAXParserFactory factory = SAXParserFactory.newInstance();//創(chuàng)建SAX解析工廠
SAXParser saxParser;
try {
 File file = new File(xmlFilePath);
 InputStream inputStream = new FileInputStream(file);//得到輸入流
 saxParser = factory.newSAXParser();//創(chuàng)建解析器
 saxParser.parse(inputStream,new DefaultHandler(){//開始解析
  //文檔開始標(biāo)記
  @Override
  public void startDocument() throws SAXException {
   super.startDocument();
   Log.i("loadWithSax","startDocument");
  }
  //文檔結(jié)束標(biāo)記
  @Override
  public void endDocument() throws SAXException {
   super.endDocument();
   FileUtils.closeIO(inputStream);
   Log.i("loadWithSax","endDocument");
  }
  //解析到標(biāo)簽
  @Override
  public void startElement(String uri, String localName, String qName, Attributes attributes) throws SA
   super.startElement(uri, localName, qName, attributes);
   Log.i("loadWithSax","startElement"+",uri:"+uri+",localName:"+localName+",qName:"+qName);
   if (attributes!=null) {
    for (int i = 0; i < attributes.getLength(); i++) {
     Log.i("loadWithSax",attributes.getLocalName(i)+","+attributes.getValue(i)+","+attributes.
    }
   }
  }
  //標(biāo)簽解析結(jié)束
  @Override
  public void endElement(String uri, String localName, String qName) throws SAXException {
   super.endElement(uri, localName, qName);
   Log.i("loadWithSax","endElement"+",uri:"+uri+",localName:"+localName+",qName:"+qName);
  }
  /**
   * 文本
   * 該方法中的ch把所解析的xml的所有數(shù)據(jù)都保存進(jìn)來,且ch初始化為2K數(shù)據(jù)。 start是一個節(jié)點(diǎn)">"的位置。length就是">"到下一個"<"的長度。
   * <namesList>
   *  <name>michael</name>
   * </namesList>
   * 執(zhí)行namesList節(jié)點(diǎn)時,因為沒有文本,
   * 不會執(zhí)行到該方法。
   */
  @Override
  public void characters(char[] ch, int start, int length) throws SAXException {
   super.characters(ch, start, length);
   Log.i("loadWithSax","characters"+",start:"+start+",length:"+length);
   for (int i = 0; i < ch.length; i++) {
    Log.i("loadWithSax","char:"+ch[i]+",ASCII:"+(int)ch[i]);
   }
  }
  //警告回調(diào)
  @Override
  public void warning(SAXParseException e) throws SAXException {
   super.warning(e);
   Log.i("loadWithSax","warning"+","+e.getMessage());
  }
  //錯誤回調(diào)
  @Override
  public void error(SAXParseException e) throws SAXException {
   super.error(e);
   Log.i("loadWithSax","error1"+","+e.getMessage());
  }
 });
} catch (ParserConfigurationException | SAXException | IOException e) {
 e.printStackTrace();
 Log.i("loadWithSax","error2"+","+e.getMessage());
}
  • 傳入:DefaultHandler的實體,通過復(fù)寫其中的方法,查詢到文檔,標(biāo)簽的內(nèi)容:

  • startDocument 和 endDocument是掃描文檔的開始和結(jié)束

  • startElement,是解析到了標(biāo)簽,localName就是標(biāo)簽的名稱,如本文所示例的,當(dāng)解析到第一個人名的時候,

<person id="1" key="33" type="type">
 <name>zhangsan</name>
 <age>21</age>
</person>

解析到<person></person>回調(diào):startElement,標(biāo)簽內(nèi)的參數(shù)是Attributes attributes,一個for循環(huán)就可以遍歷讀取。

characters,解析到標(biāo)簽的內(nèi)容時候回調(diào),接著上面例子,解析<person></person>,回調(diào)startElement,然后不會回調(diào)此方法,因為內(nèi)容不是文本,而是包含了標(biāo)簽,所以,解析到其子標(biāo)簽:<name>zhangsan</name>的時候,又會先回調(diào)回調(diào)startElement,然后,才回調(diào)characters,告訴你,這個標(biāo)簽里面有文本內(nèi)容!參數(shù)說明如下:

  • char[] : 內(nèi)容字符數(shù)組里面。如:<name>zhangsan</name>,char[]就是:{'z','h','a','n','g','s','a','n'}

  • start :0,文本的開始

  • length :文本的長度。

  • endElement,標(biāo)簽結(jié)束。

使用上面的代碼,得到的部分log如下:

I/loadWithSax: startDocument
I/loadWithSax: startElement,uri:,localName:persons,qName:persons
I/loadWithSax: characters,start:0,length:1
I/loadWithSax: char:
    ,ASCII:10
I/loadWithSax: characters,start:0,length:1
I/loadWithSax: char: ,ASCII:9
I/loadWithSax: startElement,uri:,localName:person,qName:person
I/loadWithSax: id,1,CDATA
I/loadWithSax: key,33,CDATA
I/loadWithSax: type,type,CDATA
I/loadWithSax: characters,start:0,length:1
I/loadWithSax: char:
    ,ASCII:10
I/loadWithSax: characters,start:0,length:2
I/loadWithSax: char: ,ASCII:9
I/loadWithSax: char: ,ASCII:9
I/loadWithSax: startElement,uri:,localName:name,qName:name
I/loadWithSax: characters,start:0,length:8
I/loadWithSax: char:z,ASCII:122
I/loadWithSax: char:h,ASCII:104
I/loadWithSax: char:a,ASCII:97
I/loadWithSax: char:n,ASCII:110
I/loadWithSax: char:g,ASCII:103
I/loadWithSax: char:s,ASCII:115
I/loadWithSax: char:a,ASCII:97
I/loadWithSax: char:n,ASCII:110
I/loadWithSax: endElement,uri:,localName:name,qName:name

startDocument,開始解析xml

解析到第一個標(biāo)簽的開始:<persons>

然后解析到了內(nèi)容???characters?按照我上面的分析,<persons>標(biāo)簽內(nèi)沒有文字內(nèi)容,應(yīng)該不會回調(diào)。其實,這里回調(diào)的是換行符。log中打出了ASCII碼,10就是換行。然后,還有一個tab符。

然后就是<persons>里面的<person>,有三個參數(shù):id,key,type,巴拉巴拉。。。

3.保存

sax的保存有點(diǎn)麻煩。具體是XmlSerializer的使用。

初始化一個XmlSerializer:

StringWriter stringWriter = new StringWriter();
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlSerializer xmlSerializer = factory.newSerializer();
xmlSerializer.setOutput(stringWriter);

聲明文檔的開始和結(jié)束:

xmlSerializer.startDocument("utf-8", false);//false,是聲明:standalone的值。
xmlSerializer.endDocument();

標(biāo)簽的開始結(jié)束,和寫入內(nèi)容:

xmlSerializer.startTag(null, "name");//開始,第一個參數(shù)是namespace,命名空間。
xmlSerializer.text(person.name);//寫入內(nèi)容
xmlSerializer.endTag(null, "name");

實戰(zhàn):

假如,我們需要構(gòu)建如下的XML:

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<persons>
 <person id="1" key="33" type="type">
  <name>zhangsan</name>
  <age>21</age>
 </person>
 <person>
  <name>lisi</name>
  <age>12</age>
 </person>
 <person>
  <name>wangwu</name>
  <age>23</age>
 </person>
</persons>

首先你得定義好一個Bean類,Person:

public class Person {
 public int id = -1;
 public String key = null;
 public String type = null;
 public String name;
 public int age;
 public Person(String name, int age) {
  this.name = name;
  this.age = age;
 }
}

然后開擼:最后的stringWriter就是你想要的數(shù)據(jù),注意就是,一些換行和tab符。

StringWriter stringWriter = new StringWriter();
try {
  XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
  XmlSerializer xmlSerializer = factory.newSerializer();
  xmlSerializer.setOutput(stringWriter);
  //制造假數(shù)據(jù):
  ArrayList<Person> personArrayList = new ArrayList<>();
  Person person1 = new Person("zhangsan",21);
  person1.id=1;
  person1.key="33";
  person1.type="type";
  Person person2 = new Person("lisi",12);
  Person person3 = new Person("wangwu",23);
  personArrayList.add(person1);
  personArrayList.add(person2);
  personArrayList.add(person3);
  //star document
  xmlSerializer.startDocument("utf-8", true);
  xmlSerializer.text("\n");
  xmlSerializer.startTag(null, "persons");
  for(Person person:personArrayList){
    //star tag
    xmlSerializer.text("\n");
    xmlSerializer.text("\t");
    xmlSerializer.startTag(null, "person");
    //添加參數(shù)
    if (person.id!=-1) {
      xmlSerializer.attribute(null,"id",String.valueOf(person.id));
    }
    if (person.key!=null) {
      xmlSerializer.attribute(null,"key",person.key);
    }
    if (person.type!=null) {
      xmlSerializer.attribute(null,"type",person.type);
    }
    //添加內(nèi)容:name
    xmlSerializer.text("\n");
    xmlSerializer.text("\t");
    xmlSerializer.text("\t");
    xmlSerializer.startTag(null, "name");
    xmlSerializer.text(person.name);
    xmlSerializer.endTag(null, "name");
    //添加內(nèi)容:age
    xmlSerializer.text("\n");
    xmlSerializer.text("\t");
    xmlSerializer.text("\t");
    xmlSerializer.startTag(null, "age");
    xmlSerializer.text(String.valueOf(person.age));
    xmlSerializer.endTag(null, "age");
    //end tag
    xmlSerializer.text("\n");
    xmlSerializer.text("\t");
    xmlSerializer.endTag(null, "person");
  }
  //end document
  xmlSerializer.text("\n");
  xmlSerializer.endTag(null, "persons");
  xmlSerializer.endDocument();
} catch (Exception e) {
  e.printStackTrace();
}

XmlSerializer的初始化需要傳入一個write對象,你可以傳入一個FileWrite,寫到文件里面:

// 創(chuàng)建文件對象
File fileText = new File(saveFilePath);
// 向文件寫入對象寫入信息
FileWriter stringWriter;
xmlSerializer.setOutput(stringWriter);
//...同上
//記得close
if (stringWriter != null) {
  stringWriter.close();
}

4.增刪

增加和刪除,那么你需要先對XML進(jìn)行映射,映射成一堆的Bean,然后增加刪除Bean,再保存即可。

上述內(nèi)容就是怎么在Android中使用SAX對XML數(shù)據(jù)進(jìn)行增刪改查操作,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI