生活随笔
收集整理的這篇文章主要介紹了
Android中解析XML---数据存储
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
http://blog.csdn.net/liuhe688/article/details/6415593
XML在各種開發中都廣泛應用,Android也不例外。作為承載數據的一個重要角色,如何讀寫XML成為Android開發中一項重要的技能。今天就由我向大家介紹一下在Android平臺下幾種常見的XML解析和創建的方法。
在Android中,常見的XML解析器分別為SAX解析器、DOM解析器和PULL解析器,下面,我將一一向大家詳細介紹。
SAX解析器:
SAX(Simple API for XML)解析器是一種基于事件的解析器,它的核心是事件處理模式,主要是圍繞著事件源以及事件處理器來工作的。當事件源產生事件后,調用事件處理器相應的處理方法,一個事件就可以得到處理。在事件源調用事件處理器中特定方法的時候,還要傳遞給事件處理器相應事件的狀態信息,這樣事件處理器才能夠根據提供的事件信息來決定自己的行為。
SAX解析器的優點是解析速度快,占用內存少。非常適合在Android移動設備中使用。
DOM解析器:
DOM是基于樹形結構的的節點或信息片段的集合,允許開發人員使用DOM API遍歷XML樹、檢索所需數據。分析該結構通常需要加載整個文檔和構造樹形結構,然后才可以檢索和更新節點信息。
由于DOM在內存中以樹形結構存放,因此檢索和更新效率會更高。但是對于特別大的文檔,解析和加載整個文檔將會很耗資源。
PULL解析器:
PULL解析器的運行方式和SAX類似,都是基于事件的模式。不同的是,在PULL解析過程中,我們需要自己獲取產生的事件然后做相應的操作,而不像SAX那樣由處理器觸發一種事件的方法,執行我們的代碼。PULL解析器小巧輕便,解析速度快,簡單易用,非常適合在Android移動設備中使用,Android系統內部在解析各種XML時也是用PULL解析器。
以上三種解析器,都是非常實用的解析器,我將會一一介紹。我們將會使用這三種解析技術完成一項共同的任務。
我們新建一個項目,項目結構如下:
我會在項目的assets目錄中放置一個XML文檔books.xml,內容如下:
?
[xhtml] ? view plaincopy
<? xml ? version = "1.0" ? encoding = "utf-8" ?> ?? < books > ?? ????< book > ?? ????????< id > 1001 </ id > ?? ????????< name > Thinking?In?Java </ name > ?? ????????< price > 80.00 </ price > ?? ????</ book > ?? ????< book > ?? ????????< id > 1002 </ id > ?? ????????< name > Core?Java </ name > ?? ????????< price > 90.00 </ price > ?? ????</ book > ?? ????< book > ?? ????????< id > 1003 </ id > ?? ????????< name > Hello,?Andriod </ name > ?? ????????< price > 100.00 </ price > ?? ????</ book > ?? </ books > ?? ?
然后我們分別使用以上三種解析技術解析文檔,得到一個List<Book>的對象,先來看一下Book.java的代碼:
?
[java] ? view plaincopy
package ?com.scott.xml.model;?? ?? public ? class ?Book?{?? ????private ? int ?id;?? ????private ?String?name;?? ????private ? float ?price;?? ?????? ????public ? int ?getId()?{?? ????????return ?id;?? ????}?? ?? ????public ? void ?setId( int ?id)?{?? ????????this .id?=?id;?? ????}?? ?? ????public ?String?getName()?{?? ????????return ?name;?? ????}?? ?? ????public ? void ?setName(String?name)?{?? ????????this .name?=?name;?? ????}?? ?? ????public ? float ?getPrice()?{?? ????????return ?price;?? ????}?? ?? ????public ? void ?setPrice( float ?price)?{?? ????????this .price?=?price;?? ????}?? ?? ????@Override ?? ????public ?String?toString()?{?? ????????return ? "id:" ?+?id?+? ",?name:" ?+?name?+? ",?price:" ?+?price;?? ????}?? }?? ?
最后,我們還要把這個集合對象中的數據生成一個新的XML文檔,如圖:
生成的XML結構跟原始文檔略有不同,是下面這種格式:
?
[xhtml] ? view plaincopy
<? xml ? version = "1.0" ? encoding = "UTF-8" ?> ?? < books > ?? ??< book ? id = "1001" > ?? ????< name > Thinking?In?Java </ name > ?? ????< price > 80.0 </ price > ?? ??</ book > ?? ??< book ? id = "1002" > ?? ????< name > Core?Java </ name > ?? ????< price > 90.0 </ price > ?? ??</ book > ?? ??< book ? id = "1003" > ?? ????< name > Hello,?Andriod </ name > ?? ????< price > 100.0 </ price > ?? ??</ book > ?? </ books > ?? ?
接下來,就該介紹操作過程了,我們先為解析器定義一個BookParser接口,每種類型的解析器需要實現此接口。BookParser.java代碼如下:
?
[java] ? view plaincopy
package ?com.scott.xml.parser;?? ?? import ?java.io.InputStream;?? import ?java.util.List;?? ?? import ?com.scott.xml.model.Book;?? ?? public ? interface ?BookParser?{?? ????? ? ? ? ? ?? ????public ?List<Book>?parse(InputStream?is)? throws ?Exception;?? ?????? ????? ? ? ? ? ?? ????public ?String?serialize(List<Book>?books)? throws ?Exception;?? }?? ?
好了,我們就該一個一個的實現該接口,完成我們的解析過程。
使用SAX解析器:
SaxBookParser.java代碼如下:
?
[c-sharp] ? view plaincopy
package?com.scott.xml.parser;?? ?? import?java.io.InputStream;?? import?java.io.StringWriter;?? import?java.util.ArrayList;?? import?java.util.List;?? ?? import?javax.xml.parsers.SAXParser;?? import?javax.xml.parsers.SAXParserFactory;?? import?javax.xml.transform.OutputKeys;?? import?javax.xml.transform.Result;?? import?javax.xml.transform.Transformer;?? import?javax.xml.transform.TransformerFactory;?? import?javax.xml.transform.sax.SAXTransformerFactory;?? import?javax.xml.transform.sax.TransformerHandler;?? import?javax.xml.transform.stream.StreamResult;?? ?? import?org.xml.sax.Attributes;?? import?org.xml.sax.SAXException;?? import?org.xml.sax.helpers.AttributesImpl;?? import?org.xml.sax.helpers.DefaultHandler;?? ?? import?com.scott.xml.model.Book;?? ?? public ? class ?SaxBookParser?implements?BookParser?{?? ?????? ????@Override?? ????public ?List<Book>?parse(InputStream? is )?throws?Exception?{?? ????????SAXParserFactory?factory?=?SAXParserFactory.newInstance();???? ????????SAXParser?parser?=?factory.newSAXParser();???????????????????? ????????MyHandler?handler?=?new ?MyHandler();???????????????????????? ?? ????????parser.parse(is ,?handler);?????????????????????????????????? ?? ????????return ?handler.getBooks();?? ????}?? ?? ????@Override?? ????public ?String?serialize(List<Book>?books)?throws?Exception?{?? ????????SAXTransformerFactory?factory?=?(SAXTransformerFactory)?TransformerFactory.newInstance();?? ????????TransformerHandler?handler?=?factory.newTransformerHandler();????????????? ????????Transformer?transformer?=?handler.getTransformer();??????????????????????? ????????transformer.setOutputProperty(OutputKeys.ENCODING,?"UTF-8" );???????????? ?? ????????transformer.setOutputProperty(OutputKeys.INDENT,?"yes" );???????????????? ?? ????????transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION,?"no" );??? ?? ?????????? ????????StringWriter?writer?=?new ?StringWriter();?? ????????Result?result?=?new ?StreamResult(writer);?? ????????handler.setResult(result);?? ?????????? ????????String?uri?=?"" ;???? ?? ????????String?localName?=?"" ;?? ?? ?????????? ????????handler.startDocument();?? ????????handler.startElement(uri,?localName,?"books" ,? null );?? ?????????? ????????AttributesImpl?attrs?=?new ?AttributesImpl();???? ?? ????????char []?ch?=? null ;?? ????????for ?(Book?book?:?books)?{?? ????????????attrs.clear();???? ????????????attrs.addAttribute(uri,?localName,?"id" ,? "string" ,?String.valueOf(book.getId())); ?? ????????????handler.startElement(uri,?localName,?"book" ,?attrs);???? ?? ?????????????? ????????????handler.startElement(uri,?localName,?"name" ,? null );? ?? ????????????ch?=?String.valueOf(book.getName()).toCharArray();?? ????????????handler.characters(ch,?0,?ch.length);????? ????????????handler.endElement(uri,?localName,?"name" );?? ?????????????? ????????????handler.startElement(uri,?localName,?"price" ,? null ); ?? ????????????ch?=?String.valueOf(book.getPrice()).toCharArray();?? ????????????handler.characters(ch,?0,?ch.length);????? ????????????handler.endElement(uri,?localName,?"price" );?? ?????????????? ????????????handler.endElement(uri,?localName,?"book" );?? ????????}?? ????????handler.endElement(uri,?localName,?"books" );?? ????????handler.endDocument();?? ?????????? ????????return ?writer.toString();?? ????}?? ?????? ?????? ????private ? class ?MyHandler?extends?DefaultHandler?{?? ?? ????????private ?List<Book>?books;?? ????????private ?Book?book;?? ????????private ?StringBuilder?builder;?? ?????????? ?????????? ????????public ?List<Book>?getBooks()?{?? ????????????return ?books;?? ????????}?? ?????????? ????????@Override?? ????????public ? void ?startDocument()?throws?SAXException?{?? ????????????super.startDocument();?? ????????????books?=?new ?ArrayList<Book>();?? ????????????builder?=?new ?StringBuilder();?? ????????}?? ?? ????????@Override?? ????????public ? void ?startElement(String?uri,?String?localName,?String?qName,?Attributes?attributes)?throws?SAXException?{?? ????????????super.startElement(uri,?localName,?qName,?attributes);?? ????????????if ?(localName.equals( "book" ))?{?? ????????????????book?=?new ?Book();?? ????????????}?? ????????????builder.setLength(0);????? ????????}?? ?????????? ????????@Override?? ????????public ? void ?characters( char []?ch,? int ?start,? int ?length)?throws?SAXException?{?? ????????????super.characters(ch,?start,?length);?? ????????????builder.append(ch,?start,?length);???? ????????}?? ?????????? ????????@Override?? ????????public ? void ?endElement(String?uri,?String?localName,?String?qName)?throws?SAXException?{?? ????????????super.endElement(uri,?localName,?qName);?? ????????????if ?(localName.equals( "id" ))?{?? ????????????????book.setId(Integer.parseInt(builder.toString()));?? ????????????}?else ? if ?(localName.equals( "name" ))?{?? ????????????????book.setName(builder.toString());?? ????????????}?else ? if ?(localName.equals( "price" ))?{?? ????????????????book.setPrice(Float.parseFloat(builder.toString()));?? ????????????}?else ? if ?(localName.equals( "book" ))?{?? ????????????????books.add(book);?? ????????????}?? ????????}?? ????}?? }?? ?
代碼中,我們定義了自己的事件處理邏輯,重寫了DefaultHandler的幾個重要的事件方法。下面我為大家著重介紹一下DefaultHandler的相關知識。DefaultHandler是一個事件處理器,可以接收解析器報告的所有事件,處理所發現的數據。它實現了EntityResolver接口、DTDHandler接口、ErrorHandler接口和ContentHandler接口。這幾個接口代表不同類型的事件處理器。我們著重介紹一下ContentHandler接口。結構如圖:
這幾個比較重要的方法已被我用紅線標注,DefaultHandler實現了這些方法,但在方法體內沒有做任何事情,因此我們在使用時必須覆寫相關的方法。最重要的是startElement方法、characters方法和endElement方法。當執行文檔時遇到起始節點,startElement方法將會被調用,我們可以獲取起始節點相關信息;然后characters方法被調用,我們可以獲取節點內的文本信息;最后endElement方法被調用,我們可以做收尾的相關操作。
最后,我們需要調用SAX解析程序,這個步驟在MainActivity中完成:
?
[java] ? view plaincopy
package ?com.scott.xml;?? ?? import ?java.io.FileOutputStream;?? import ?java.io.InputStream;?? import ?java.util.List;?? ?? import ?android.app.Activity;?? import ?android.content.Context;?? import ?android.os.Bundle;?? import ?android.util.Log;?? import ?android.view.View;?? import ?android.widget.Button;?? ?? import ?com.scott.xml.model.Book;?? import ?com.scott.xml.parser.BookParser;?? import ?com.scott.xml.parser.SaxBookParser;?? ?? public ? class ?MainActivity? extends ?Activity?{?? ?????? ????private ? static ? final ?String?TAG?=? "XML" ;?? ?????? ????private ?BookParser?parser;?? ????private ?List<Book>?books;?? ?????? ????@Override ?? ????public ? void ?onCreate(Bundle?savedInstanceState)?{?? ????????super .onCreate(savedInstanceState);?? ????????setContentView(R.layout.main);?? ?????????? ????????Button?readBtn?=?(Button)?findViewById(R.id.readBtn);?? ????????Button?writeBtn?=?(Button)?findViewById(R.id.writeBtn);?? ?????????? ????????readBtn.setOnClickListener(new ?View.OnClickListener()?{?? ????????????@Override ?? ????????????public ? void ?onClick(View?v)?{?? ????????????????try ?{?? ????????????????????InputStream?is?=?getAssets().open("books.xml" );?? ????????????????????parser?=?new ?SaxBookParser();?? ?? ????????????????????books?=?parser.parse(is);???? ????????????????????for ?(Book?book?:?books)?{?? ????????????????????????Log.i(TAG,?book.toString());?? ????????????????????}?? ????????????????}?catch ?(Exception?e)?{?? ????????????????????Log.e(TAG,?e.getMessage());?? ????????????????}?? ????????????}?? ????????});?? ????????writeBtn.setOnClickListener(new ?View.OnClickListener()?{?? ????????????@Override ?? ????????????public ? void ?onClick(View?v)?{?? ????????????????try ?{?? ????????????????????String?xml?=?parser.serialize(books);???? ????????????????????FileOutputStream?fos?=?openFileOutput("books.xml" ,?Context.MODE_PRIVATE);?? ????????????????????fos.write(xml.getBytes("UTF-8" ));?? ????????????????}?catch ?(Exception?e)?{?? ????????????????????Log.e(TAG,?e.getMessage());?? ????????????????}?? ????????????}?? ????????});?? ????}?? }?? ?
界面就兩個按鈕,順便給大家貼上:
?
點擊“readXML”按鈕,將會調用SAX解析器解析文檔,并在日志臺打印相關信息:
然后再點擊“writeXML”按鈕,將會在該應用包下的files目錄生成一個books.xml文件:
使用DOM解析器:
DomBookParser.java代碼如下:
?
[java] ? view plaincopy
package ?com.scott.xml.parser;?? ?? import ?java.io.InputStream;?? import ?java.io.StringWriter;?? import ?java.util.ArrayList;?? import ?java.util.List;?? ?? import ?javax.xml.parsers.DocumentBuilder;?? import ?javax.xml.parsers.DocumentBuilderFactory;?? import ?javax.xml.transform.OutputKeys;?? import ?javax.xml.transform.Result;?? import ?javax.xml.transform.Source;?? import ?javax.xml.transform.Transformer;?? import ?javax.xml.transform.TransformerFactory;?? import ?javax.xml.transform.dom.DOMSource;?? import ?javax.xml.transform.stream.StreamResult;?? ?? import ?org.w3c.dom.Document;?? import ?org.w3c.dom.Element;?? import ?org.w3c.dom.Node;?? import ?org.w3c.dom.NodeList;?? ?? import ?com.scott.xml.model.Book;?? ?? public ? class ?DomBookParser? implements ?BookParser?{?? ?? ????@Override ?? ????public ?List<Book>?parse(InputStream?is)? throws ?Exception?{?? ????????List<Book>?books?=?new ?ArrayList<Book>();?? ????????DocumentBuilderFactory?factory?=?DocumentBuilderFactory.newInstance();???? ????????DocumentBuilder?builder?=?factory.newDocumentBuilder();??? ????????Document?doc?=?builder.parse(is);????? ????????Element?rootElement?=?doc.getDocumentElement();?? ????????NodeList?items?=?rootElement.getElementsByTagName("book" );?? ????????for ?( int ?i?=? 0 ;?i?<?items.getLength();?i++)?{?? ????????????Book?book?=?new ?Book();?? ????????????Node?item?=?items.item(i);?? ????????????NodeList?properties?=?item.getChildNodes();?? ????????????for ?( int ?j?=? 0 ;?j?<?properties.getLength();?j++)?{?? ????????????????Node?property?=?properties.item(j);?? ????????????????String?nodeName?=?property.getNodeName();?? ????????????????if ?(nodeName.equals( "id" ))?{?? ????????????????????book.setId(Integer.parseInt(property.getFirstChild().getNodeValue()));?? ????????????????}?else ? if ?(nodeName.equals( "name" ))?{?? ????????????????????book.setName(property.getFirstChild().getNodeValue());?? ????????????????}?else ? if ?(nodeName.equals( "price" ))?{?? ????????????????????book.setPrice(Float.parseFloat(property.getFirstChild().getNodeValue()));?? ????????????????}?? ????????????}?? ????????????books.add(book);?? ????????}?? ????????return ?books;?? ????}?? ?? ????@Override ?? ????public ?String?serialize(List<Book>?books)? throws ?Exception?{?? ????????DocumentBuilderFactory?factory?=?DocumentBuilderFactory.newInstance();?? ????????DocumentBuilder?builder?=?factory.newDocumentBuilder();?? ????????Document?doc?=?builder.newDocument();????? ?????????? ????????Element?rootElement?=?doc.createElement("books" );?? ?? ????????for ?(Book?book?:?books)?{?? ????????????Element?bookElement?=?doc.createElement("book" );?? ????????????bookElement.setAttribute("id" ,?book.getId()?+? "" );?? ?????????????? ????????????Element?nameElement?=?doc.createElement("name" );?? ????????????nameElement.setTextContent(book.getName());?? ????????????bookElement.appendChild(nameElement);?? ?????????????? ????????????Element?priceElement?=?doc.createElement("price" );?? ????????????priceElement.setTextContent(book.getPrice()?+?"" );?? ????????????bookElement.appendChild(priceElement);?? ?????????????? ????????????rootElement.appendChild(bookElement);?? ????????}?? ?????????? ????????doc.appendChild(rootElement);?? ?????????? ????????TransformerFactory?transFactory?=?TransformerFactory.newInstance();?? ????????Transformer?transformer?=?transFactory.newTransformer();?????? ????????transformer.setOutputProperty(OutputKeys.ENCODING,?"UTF-8" );???????????? ?? ????????transformer.setOutputProperty(OutputKeys.INDENT,?"yes" );???????????????? ?? ????????transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION,?"no" );??? ?? ?????????? ????????StringWriter?writer?=?new ?StringWriter();?? ?????????? ????????Source?source?=?new ?DOMSource(doc);? ?? ????????Result?result?=?new ?StreamResult(writer); ?? ????????transformer.transform(source,?result);???? ?????????? ????????return ?writer.toString();?? ????}?? ?? }?? ?
然后再MainActivity中只需改一個地方:
?
[java] ? view plaincopy
?????readBtn.setOnClickListener( new ?View.OnClickListener()?{?? @Override ?? public ? void ?onClick(View?v)?{?? ????try ?{?? ????????InputStream?is?=?getAssets().open("books.xml" );?? ??? ????????parser?=?new ?DomBookParser();?? ????????books?=?parser.parse(is);?? ????????for ?(Book?book?:?books)?{?? ????????????Log.i(TAG,?book.toString());?? ????????}?? ????}?catch ?(Exception?e)?{?? ????????Log.e(TAG,?e.getMessage());?? ????}?? }?? );?? ?
執行結果是一樣的。
使用PULL解析器:
PullBookParser.java代碼如下:
?
[java] ? view plaincopy
package ?com.scott.xml.parser;?? ?? import ?java.io.InputStream;?? import ?java.io.StringWriter;?? import ?java.util.ArrayList;?? import ?java.util.List;?? ?? import ?org.xmlpull.v1.XmlPullParser;?? import ?org.xmlpull.v1.XmlSerializer;?? ?? import ?android.util.Xml;?? ?? import ?com.scott.xml.model.Book;?? ?? public ? class ?PullBookParser? implements ?BookParser?{?? ?????? ????@Override ?? ????public ?List<Book>?parse(InputStream?is)? throws ?Exception?{?? ????????List<Book>?books?=?null ;?? ????????Book?book?=?null ;?? ?????????? ?? ?? ?????????? ????????XmlPullParser?parser?=?Xml.newPullParser();??? ????????parser.setInput(is,?"UTF-8" );??????????????? ?? ?? ????????int ?eventType?=?parser.getEventType();?? ????????while ?(eventType?!=?XmlPullParser.END_DOCUMENT)?{?? ????????????switch ?(eventType)?{?? ????????????case ?XmlPullParser.START_DOCUMENT:?? ????????????????books?=?new ?ArrayList<Book>();?? ????????????????break ;?? ????????????case ?XmlPullParser.START_TAG:?? ????????????????if ?(parser.getName().equals( "book" ))?{?? ????????????????????book?=?new ?Book();?? ????????????????}?else ? if ?(parser.getName().equals( "id" ))?{?? ????????????????????eventType?=?parser.next();?? ????????????????????book.setId(Integer.parseInt(parser.getText()));?? ????????????????}?else ? if ?(parser.getName().equals( "name" ))?{?? ????????????????????eventType?=?parser.next();?? ????????????????????book.setName(parser.getText());?? ????????????????}?else ? if ?(parser.getName().equals( "price" ))?{?? ????????????????????eventType?=?parser.next();?? ????????????????????book.setPrice(Float.parseFloat(parser.getText()));?? ????????????????}?? ????????????????break ;?? ????????????case ?XmlPullParser.END_TAG:?? ????????????????if ?(parser.getName().equals( "book" ))?{?? ????????????????????books.add(book);?? ????????????????????book?=?null ;?????? ????????????????}?? ????????????????break ;?? ????????????}?? ????????????eventType?=?parser.next();?? ????????}?? ????????return ?books;?? ????}?? ?????? ????@Override ?? ????public ?String?serialize(List<Book>?books)? throws ?Exception?{?? ?? ?? ?????????? ????????XmlSerializer?serializer?=?Xml.newSerializer();??? ????????StringWriter?writer?=?new ?StringWriter();?? ????????serializer.setOutput(writer);????? ????????serializer.startDocument("UTF-8" ,? true );?? ????????serializer.startTag("" ,? "books" );?? ????????for ?(Book?book?:?books)?{?? ????????????serializer.startTag("" ,? "book" );?? ????????????serializer.attribute("" ,? "id" ,?book.getId()?+? "" );?? ?????????????? ????????????serializer.startTag("" ,? "name" );?? ????????????serializer.text(book.getName());?? ????????????serializer.endTag("" ,? "name" );?? ?????????????? ????????????serializer.startTag("" ,? "price" );?? ????????????serializer.text(book.getPrice()?+?"" );?? ????????????serializer.endTag("" ,? "price" );?? ?????????????? ????????????serializer.endTag("" ,? "book" );?? ????????}?? ????????serializer.endTag("" ,? "books" );?? ????????serializer.endDocument();?? ?????????? ????????return ?writer.toString();?? ????}?? }?? ?
然后再對MainActivity做以下更改:
?
[java] ? view plaincopy
????????readBtn.setOnClickListener( new ?View.OnClickListener()?{?? ????????????@Override ?? ????????????public ? void ?onClick(View?v)?{?? ????????????????try ?{?? ????????????????????InputStream?is?=?getAssets().open("books.xml" );?? ?? ?? ????????????????????parser?=?new ?PullBookParser();?? ????????????????????books?=?parser.parse(is);?? ????????????????????for ?(Book?book?:?books)?{?? ????????????????????????Log.i(TAG,?book.toString());?? ????????????????????}?? ????????????????}?catch ?(Exception?e)?{?? ????????????????????Log.e(TAG,?e.getMessage());?? ????????????????}?? ????????????}?? ????????});?? ?
和其他兩個執行結果都一樣。
對于這三種解析器各有優點,我個人比較傾向于PULL解析器,因為SAX解析器操作起來太笨重,DOM不適合文檔較大,內存較小的場景,唯有PULL輕巧靈活,速度快,占用內存小,使用非常順手。讀者也可以根據自己的喜好選擇相應的解析技術。
轉載于:https://www.cnblogs.com/shuiyun/archive/2012/10/17/2728483.html
總結
以上是生活随笔 為你收集整理的Android中解析XML---数据存储 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。