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提供了对大规模数据的逐步解析方案,这种方案很适合于对大量数据的处理。