1.引子:DOM
這篇文章寫得挺好
http://www.cnblogs.com/yexiaochai/archive/2013/05/28/3102674.html
document object model 文檔對象模型,用於訪問xml html的標準
document對象的常用方法
節點常用屬性
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Generator" content="EditPlus®">
<meta name="Author" content="">
<meta name="Keywords" content="">
<meta name="Description" content="">
<title>Dom概述</title>
</head>
<body>
<h1>明天休息</h1>
<script>
//alert(document.getElementsByTagName("h1")[0].firstChild.nodeValue);
//alert(document.getElementsByTagName("h1")[0].lastChild.nodeValue);
//alert(document.getElementsByTagName("h1")[0].childNodes[0].nodeValue );
//alert(document.getElementsByTagName("h1")[0].innerHTML);
</script>
</body>
</html>
由於這裏只有一個子節點,first=last ,都能彈出明天休息的框框
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Generator" content="EditPlus®">
<meta name="Author" content="">
<meta name="Keywords" content="">
<meta name="Description" content="">
<title>打印ul裏面的li子節點信息</title>
<script>
function getLi(){
var bjNode= document.getElementById("bj");
var childnum = bjNode.childNodes.length;
//alert(childnum);
for(var i=0;i<childnum ;i++)
alert( bjNode.childNodes[i].nodeName+","+bjNode.childNodes[i].nodeType+","+
bjNode.childNodes[i].nodeValue );
//#text 3 北京
//h1 1
//#text 3 奧運
}
</script>
</head>
<body>
<ul>
<li id="bj" value="beijing">
北京
<h1>海淀</h1>
奧運
</li>
<li id="sh" value="shanghai">
上海
</li>
<br/>
<input type="button" value="li取值" οnclick="getLi()"/>
</ul>
</body>
</html>
這裏第一個節點下有3個子節點,第一個是文本節點,北京,第二個是一個元素節點,變大了的海淀,第三個是文本節點,奧運
所以依次輸出了
#text,3,北京
H1,1,null
#text,3,奧運
由上面這兩個例子就大概可以看出xml解析需要的基本知識,按節點獲取,至於增刪改查之類的這裏不多說了~
2.關於xml
如果想系統、深入的學習xml的知識,最好看看Javascript的相關知識,包括各種BOM、DOM、xml約束、解析什麼的
xml,可標記語言,用來傳輸數據,至於展示數據需要別的軟件解析
例如數據結構的樹形數據結構,如何才能交給PC處理?
xml的標籤
一個標籤中只能有一個主標籤;一個標籤下由若干子標籤,但是不能互相嵌套;主題內容中的空格也會被讀取,如果不處理,跑起來容易掛掉
3.着重看下如何解析,做安卓開發主要還是用,SAX DOM PULL
首先簡單說下SAX和DOM解析的異同,而PULL解析是安卓特有,單獨說
首先解析方式上,主要是以下兩種,幾乎所有商用的xml 解析器都同時實現了這兩個接口
(1) JAXP,
(2)DOM4J解析
看名字就知道這個是DOM模式解析,脫胎於更早期的JDOM
Document document = reader.read(new File("input.xml"));
Document document = DocumentHelper.parseText(text);
//創建根節點
獲取節點對象
List nodes = rootElm.elements("member");
for (Iterator it = nodes.iterator(); it.hasNext();) {
Element elm = (Element) it.next();
// do something
}
for(Iterator it=root.elementIterator();it.hasNext();){
Element element = (Element) it.next();
// do something
}
Element ageElm = newMemberElm.addElement("age");
element.setText("29");
//childElm是待刪除的節點,parentElm是其父節點
Element contentElm = infoElm.addElement("content");
contentElm.addCDATA(diary.getContent());
節點對象屬性
Element root=document.getRootElement();
//屬性名name
String text=attribute.getText();
Attribute attribute=root.attribute("size");
root.remove(attribute);
Element root=document.getRootElement();
for(Iterator it=root.attributeIterator();it.hasNext();){
Attribute attribute = (Attribute) it.next();
String text=attribute.getText();
System.out.println(text);
}
newMemberElm.addAttribute("name", "sitinspring");
Attribute attribute=root.attribute("name");
attribute.setText("sitinspring");
將文檔寫入XML
XMLWriter writer = new XMLWriter(new FileWriter("output.xml"));
writer.write(document);
writer.close();
OutputFormat format = OutputFormat.createPrettyPrint();
指定XML編碼
XMLWriter writer = new XMLWriter(new FileOutputStream ("output.xml"),format);
writer.write(document);
writer.close();
來對比下:
SAX這種基於事件的處理方式,一邊讀數據一邊解析,無需保存數據,在需要的時候直接停止亦可
而DOM這種基於樹的處理方式,需要先把數據完全讀入,可以對他的數據、結構進行修改,但是另一方面來說,對於比較大的文檔,他的內存消耗就比較大了
所以:
如果想對數據更改並輸出爲xml,DOM更合適;對於大文件,XML更合適,另外如果對速度有要求,同樣XML是更好的選擇
實例:
正好看到一篇好文,直接引用了。http://www.cnblogs.com/JerryWang1991/archive/2012/02/24/2365507.html
<?xml version="1.0" encoding="utf-8"?>
<channel>
<item id="0" url="http://www.baidu.com">百度</item>
<item id="1" url="http://www.qq.com">騰訊</item>
<item id="2" url="http://www.sina.com.cn">新浪</item>
<item id="3" url="http://www.taobao.com">淘寶</item>
</channel>
4.最後關於PULL解析
在android系統中,很多資源文件中,很多都是xml格式,在android系統中解析這些xml的方式,是使用pul解析器進行解析的,它和sax解析一樣(個人感覺要比sax簡單點),也是採用事件驅動進行解析的,當pull解析器,開始解析之後,我們可以調用它的next()方法,來獲取下一個解析事件(就是開始文檔,結束文檔,開始標籤,結束標籤),當處於某個元素時可以調用XmlPullParser的getAttributte()方法來獲取屬性的值,也可調用它的nextText()獲取本節點的值。
跟SAX不同的是, Pull解析器產生的事件是一個數字,而非方法,因此可以使用一個switch對感興趣的事件進行處理。當元素開始解析時,調用parser.nextText()方法可以獲取下一個Text類型節點的值pull本來是一個開源項目
Android SDK中已經集成了Pull解析器,無需添加任何jar文件
• 使用Pull解析器解析XML文件
– 1. Xml.newPullParser() 獲得解析器
– 2 parser.setInput(in, "UTF-8") 設置輸入流以及編碼
– 3. parser.next() 獲取下一個解析事件,得到一個事件代碼
– 4. XmlPullParser中定義了常量來標識各種解析事件
START_DOCUMENT、
END_DOCUMENT 、
START_TAG 、
END_TAG 、
TEXT<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map><string name='nickname'>hellokitty</string><boolean name='autostart' value='false' /><float name='autoclose' value='1000.0' /></map>
bean
package com.example.bean;
public class Book {
private String bookname;
private String author;
private String priceString;
@Override
public String toString() {
return "Book [bookname=" + bookname + ", author=" + author
+ ", priceString=" + priceString + "]";
}
public String getBookname() {
return bookname;
}
public void setBookname(String bookname) {
this.bookname = bookname;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getPriceString() {
return priceString;
}
public void setPriceString(String priceString) {
this.priceString = priceString;
}
}
public class MainActivity extends Activity {
public static String TAG = "pullparser";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void parsebyPull(View v) throws IOException{
//得到解析器XmlPullParser
XmlPullParser pullparser = Xml.newPullParser();
List<Book> booklist= new ArrayList<Book>();
Book book = null;
try {
//設置讀取文件,要與xml裏的編碼格式一致
InputStream in = new FileInputStream("data/data/com.example.pullparser/files/books.xml");
pullparser.setInput(in, "UTF-8");
//類型
int evenType = pullparser.getEventType();
while(evenType!=XmlPullParser.END_DOCUMENT){
if (evenType==XmlPullParser.START_DOCUMENT) {
Log.i(TAG, "START_DOCUMENT") ;
}
if (evenType==XmlPullParser.START_TAG){
Log.i(TAG, "START_TAG"+pullparser.getName()) ;
if ("book".equals(pullparser.getName())) {
book = new Book();
}
if ("bookname".equals(pullparser.getName())) {
book.setBookname(pullparser.nextText());
}
if ("author".equals(pullparser.getName())) {
book.setAuthor(pullparser.nextText());
}
if ("price".equals(pullparser.getName())) {
book.setPriceString(pullparser.nextText());
}
}
if (evenType==XmlPullParser.TEXT) {
Log.i(TAG, "TEXT" +pullparser.getText()) ;
}
if (evenType==XmlPullParser.END_TAG) {
Log.i(TAG, "END_TAG"+pullparser.getName()) ;
if ("book".equals(pullparser.getName())) {
booklist.add(book);
book = null;
}
}
evenType=pullparser.next();
}
if (evenType==XmlPullParser.END_DOCUMENT) {
Log.i(TAG, "END_DOCUMENT") ;
}
for ( Book book2 : booklist) {
Log.i(TAG, book2.toString() ) ;
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
5.JSON
<?xmlversion="1.0"encoding="utf-8"?>
<country>
<name>中國</name>
<province>
<name>黑龍江</name>
<cities>
<city>哈爾濱</city>
<city>大慶</city>
</cities>
</province>
<province>
<name>廣東</name>
<cities>
<city>廣州</city>
<city>深圳</city>
<city>珠海</city>
</cities>
</province>
<province>
<name>臺灣</name>
<cities>
<city>臺北</city>
<city>高雄</city>
</cities>
</province>
<province>
<name>新疆</name>
<cities>
<city>烏魯木齊</city>
</cities>
</province>
</country>
var pro ={
"name":"中國",
"province":[{"name":"黑龍江","cities":{"city":["哈爾濱","大慶"]}},
{"name":"廣東","cities":{"city":["廣州","深圳","珠海"]}},
{"name":"臺灣","cities":{"city":["臺北","高雄"]}},
{"name":"新疆","cities":{"city":["烏魯木齊"]}}
]
}
可讀性上,JSON更簡潔,xml更規範
擴展性上沒有區別
解析上,事先知道結構的時候,JSON顯然更有優勢
傳輸效率上,JSON無需閉合標籤,總數據量會少一些,傳輸壓力更小
查詢手機號,利用網絡上的服務提供數據,先看一下解析出來的數據格式
xml
http://api.k780.com:88/?app=phone.get&phone=13800138000&appkey=14114&sign=ede788f7bf8d0678e281f660654ef995&format=xml
JSON格式
public class MainActivity extends Activity {
public static final String TAG = "phonenumberqurey";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
Handler hanlder = new Handler(){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
switch (msg.what) {
case 1:
//正確的連到服務器就要獲取出來,而不是toast
TextView tv_loaction = (TextView) findViewById(R.id.tv_location);
tv_loaction.setText((String)msg.obj);
break;
case 2:
Toast.makeText(MainActivity.this, (String)msg.obj, 0).show();
break;
default:
break;
}
}
};
public void query(View v){
//先獲取電話號碼
EditText et_number = (EditText) findViewById(R.id.et_number);
String number = et_number.getText().toString();
final String path ="http://api.k780.com:88/?app=phone.get&phone="+number+"&appkey=14114&sign=ede788f7bf8d0678e281f660654ef995&format=xml";
//發請求的線程
Thread thread = new Thread(){
public void run() {
try {
URL url = new URL(path);
HttpURLConnection conn= (HttpURLConnection) url.openConnection();
//
conn.setReadTimeout(5000);
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
//
conn.connect();
//
String city =null;
String operator = null;
if(conn.getResponseCode()==200){
//登陸成功
//登陸失敗?
InputStream is= conn.getInputStream();
//String text = WebUtils.gettextFromInputStream(is, null);
XmlPullParser pullparser = Xml.newPullParser();
pullparser.setInput(is, "UTF-8");
//得到讀取到的某部分的類型
int evenType = pullparser.getEventType();
while(evenType!=XmlPullParser.END_DOCUMENT){
if (evenType==XmlPullParser.START_TAG) {
Log.i(TAG, "START_TAG"+pullparser.getName()) ;
if ("operators".equals(pullparser.getName())) {
operator=pullparser.nextText();
}
if ("style_citynm".equals(pullparser.getName())) {
city=pullparser.nextText();
}
}
evenType=pullparser.next();
}
Log.i(TAG,operator+":"+city);
Message msg = hanlder.obtainMessage();
msg.what=1;
if(city==null||operator==null)
msg.obj="沒有查詢到結果";
else
msg.obj= city+":"+operator;
hanlder.sendMessage(msg);
}
else {
Message msg = hanlder.obtainMessage();
msg.what=2;
msg.obj="沒有鏈接到服務器";
hanlder.sendMessage(msg);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
};
};
thread.start();
}
public void querybyjson(View v){
//先獲取電話號碼
EditText et_number = (EditText) findViewById(R.id.et_number);
String number = et_number.getText().toString();
final String path ="http://api.k780.com:88/?app=phone.get&phone="+number+"&appkey=14114&sign=ede788f7bf8d0678e281f660654ef995&format=json";
//發請求的線程
Thread thread = new Thread(){
public void run() {
try {
URL url = new URL(path);
HttpURLConnection conn= (HttpURLConnection) url.openConnection();
conn.setReadTimeout(5000);
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
conn.connect();
String city =null;
String operator = null;
if(conn.getResponseCode()==200){
InputStream is= conn.getInputStream();
//json需要提取出文本
String text = WebUtils.gettextFromInputStream(is, null);
JSONObject jsonObject = new JSONObject(text);
JSONObject result = jsonObject.getJSONObject("result");
city= result.getString("style_citynm");
operator = result.getString("operators");
Log.i(TAG,operator+":"+city);
Message msg = hanlder.obtainMessage();
msg.what=1;
if(city==null||operator==null)
msg.obj="沒有查詢到結果";
else
msg.obj= city+":"+operator;
hanlder.sendMessage(msg);
}
else {
Message msg = hanlder.obtainMessage();
msg.what=2;
msg.obj="沒有鏈接到服務器";
hanlder.sendMessage(msg);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
};
};
thread.start();
}
class Myhandler extends AsyncHttpResponseHandler {
@Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
// TODO Auto-generated method stub
String city =null;
String operator = null;
//String text = WebUtils.gettextFromInputStream(is, null);
XmlPullParser pullparser = Xml.newPullParser();
//onSuccess的最後一個參數傳遞的是數組,這裏需要一個把數組轉成流的方法~
ByteArrayInputStream bais= new ByteArrayInputStream(responseBody);
try {
pullparser.setInput(bais, "utf-8");
//得到讀取到的某部分的類型
int evenType = pullparser.getEventType();
while(evenType!=XmlPullParser.END_DOCUMENT){
if (evenType==XmlPullParser.START_TAG) {
Log.i(TAG, "START_TAG"+pullparser.getName()) ;
if ("operators".equals(pullparser.getName())) {
operator=pullparser.nextText();
}
if ("style_citynm".equals(pullparser.getName())) {
city=pullparser.nextText();
}
}
evenType=pullparser.next();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//json
JSONObject jsonObject =null;
try {
jsonObject = new JSONObject(new String(responseBody));
JSONObject result = jsonObject.getJSONObject("result");
city= result.getString("style_citynm");
operator = result.getString("operators");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
TextView tv_loaction = (TextView) findViewById(R.id.tv_location);
tv_loaction.setText(city+":"+operator);
}
@Override
public void onFailure(int statusCode, Header[] headers,
byte[] responseBody, Throwable error) {
// TODO Auto-generated method stub
}
}
public void querybyxml_async(View v){
EditText et_number = (EditText) findViewById(R.id.et_number);
String number = et_number.getText().toString();
final String path ="http://api.k780.com:88/?app=phone.get&phone="+number+"&appkey=14114&sign=ede788f7bf8d0678e281f660654ef995&format=xml";
AsyncHttpClient asyncHttpClient = new AsyncHttpClient();
asyncHttpClient.post(path, new Myhandler());
}
public void querybyjson_aysnc(View v){
EditText et_number = (EditText) findViewById(R.id.et_number);
String number = et_number.getText().toString();
final String path ="http://api.k780.com:88/?app=phone.get&phone="+number+"&appkey=14114&sign=ede788f7bf8d0678e281f660654ef995&format=json";
AsyncHttpClient asyncHttpClient = new AsyncHttpClient();
asyncHttpClient.post(path, new Myhandler());
}
}
最後再對比下
關於輕量級和重量級
輕量級和重量級是相對來說的,那麼XML相對於JSON的重量級體現在哪呢?應該體現在解析上,XML目前設計了兩種解析方式:DOM和 SAX。
<1>.DOM
DOM是把一個數據交換格式XML看成一個DOM對象,需要把XML文件整個讀入內存,這一點上JSON和XML的原理是一樣的,但是XML要考慮父節點和子節點,這一點上JSON的解析難度要小很多,因爲JSON構建於兩種結構:key/value,鍵值對的集合;值的有序集合,可理解爲數組;
<2>.SAX
SAX不需要整個讀入文檔就可以對解析出的內容進行處理,是一種逐步解析的方法。程序也可以隨時終止解析。這樣,一個大的文檔就可以逐步的、一點一點的展現出來,所以SAX適合於大規模的解析。這一點,JSON目前是做不到得。
所以,JSON和XML的輕/重量級的區別在於:
JSON只提供整體解析方案,而這種方法只在解析較少的數據時才能起到良好的效果;
XML提供了對大規模數據的逐步解析方案,這種方案很適合於對大量數據的處理。