- 作者: Jonathan Fenocchi
- 译者:Sheneyan(子乌)
- 时间:2005.10.26
- 英文原文:http://www.webreference.com/programming/javascript/jf/column13/
在上一篇文章中,我们讨论了如何通过javascript从一个远程XML文件中取得数据。在这篇文章中,我们将学会怎样对数据作更复杂的处理。作为一个示例,我们会准备一组XML数据,将数据分割成独立的片断并以不同的方式展示这些片断(取决于它们是如何被标识的)。
这篇文章是建立在上一篇文章中构造的示例代码的基础之上,所以如果你不能理解我们现在的代码,你可以回过头去读第一篇文章。
开始~
让我们开始我们的第一步:构造XML。我们准备写一个XML文档,它组织了一系列准备让javascript处理的数据,所以我们将一起组织一些节点和子节点(或者,元素和子元素)。在这个例子里,我们将使用一些家庭宠物的名字:
<?xml version="1.0" encoding="UTF-8"?> <data> <pets> <pet>猫</pet> <pet>狗</pet> <pet>鱼</pet> </pets> </data>
在上面,我们有这个XML声明(标明这个文档是一个XML 1.0 文档,使用UTF-8编码),一个根元素()将下面所有的元素组合在一起,一个
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html lang="zh" dir="ltr"> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <title>使用Ajax开发Web应用程序 - 示例</title> <script type="text/javascript"><!-- function ajaxRead(file){ var xmlObj = null; if(window.XMLHttpRequest){ xmlObj = new XMLHttpRequest(); } else if(window.ActiveXObject){ xmlObj = new ActiveXObject("Microsoft.XMLHTTP"); } else { return; } xmlObj.onreadystatechange = function(){ if(xmlObj.readyState == 4){ processXML(xmlObj.responseXML); } } xmlObj.open ('GET', file, true); xmlObj.send (''); } function processXML(obj){ var dataArray = obj.getElementsByTagName('pet'); var dataArrayLen = dataArray.length; var insertData = ' <table style="width:150px; border: solid 1px #000"> <tr> <th>' + 'Pets</th> </tr> '; for (var i=0; i<dataArrayLen; i++){ insertData += ' <tr> <td>' + dataArray[i].firstChild.data + '</td> </tr> '; } insertData += '</table> '; document.getElementById ('dataArea').innerHTML = insertData; } //--></script> </head> <body> <h1>使用Ajax开发web应用程序</h1> 这个页面演示了AJAX技术如何通过动态读取一个远程文件来更新一个网页的内容--不需要任何网页的重新加载。注意:这个例子对于禁止js的用户来说没有效果。 这个页面将演示如从取回并处理成组的XML数据。被取回的数据将会以表格形式输出到底下。 <a href="#" onclick="ajaxRead('data_2.xml'); return false">查看演示</a>. <div id="dataArea"></div> </body> </html>
(Sheneyan注:完整代码示例见example_2.html,XML文件见data_2.xml)
你会注意到我们和上次一样以同样的方式(通过一个超链接)调用了这个函数,而且我们将数据放入一个DIV(这次这个东东叫做dataArea)。这个ajaxRead()函数和上次很接近,除了一点不同:onreadystatechange函数。让我们先看一下这个函数:
xmlObj.onreadystatechange = function(){ if(xmlObj.readyState == 4){ processXML(xmlObj.responseXML); } }
我们取消了updateObj函数并用一个叫做processXML()的新函数来代替它。这个函数将得到XML文档本身(也就是被ajaxRead函数取回的)并处理它。(这XML文档本身我指的是参数xmlObj.responseXML)
现在让我们分析一下这个函数processXML。下面是它的代码:
function processXML(obj){ var dataArray = obj.getElementsByTagName('pet'); var dataArrayLen = dataArray.length; var insertData = ' <table style="width:150px; border: solid 1px #000"> <tr> <th>' + 'Pets</th> </tr> '; for (var i=0; i<dataArrayLen; i++){ insertData += ' <tr> <td>' + dataArray[i].firstChild.data + '</td> </tr> '; } insertData += '</table> '; document.getElementById ('dataArea').innerHTML = insertData; }
首先,我们定义了一些变量。dataArray作为所有
我们的第二步则是遍历所有的
新数据行添加完后,我们插入一个
结束标签到变量insertData。这完成了这个表格,然后我只剩这最后一步来达成我们的目标:我们需要将这个表格放到页面上。幸运的是,我们得感谢innerHTML属性,这很简单。我们通过函数document.getElementById()取得DIVdataArea并将变量insertData中的HTML插进去。嗯,这个表格冒出来了!
我们继续之前……
我得指出两点:
首先,你会注意到我们并没有使用节点
另外一种方式是给每一个宠物放一个指定的标签,比如:
<?xml version="1.0" encoding="UTF-8"?> <data> <pets> <猫 /> <狗 /> <鱼 /> </pets> </data>
然后我们能够遍历元素
function processXML(obj){ var dataArray = obj.getElementsByTagName('pets')[0].childNodes; var dataArrayLen = dataArray.length; var insertData = ' <table style="width:150px; border: solid 1px #000"> <tr> <th>' + 'Pets</th> </tr> '; for (var i=0; i<dataArrayLen; i++){ if(dataArray[i].tagName){ insertData += ' <tr> <td>' + dataArray[i].tagName + '</td> </tr> '; } } insertData += '</table> '; document.getElementById ('dataArea').innerHTML = insertData; }
(Sheneyan注:修改后的示例见:example_2_1.html,XML文件见:data_2_1.xml)
这里所作的修改就是我们指向了
还有另外一种方式来完成我们上面的工作,就是给每一个
<?xml version="1.0" encoding="UTF-8"?> <data> <pets> <pet type="猫" /> <pet type="狗" /> <pet type="鱼" /> </pets> </data>
你只需要稍微修改一下你的processXML函数,它变成这样子了:
function processXML(obj){ var dataArray = obj.getElementsByTagName('pet'); var dataArrayLen = dataArray.length; var insertData = ' <table style="width:150px; border: solid 1px #000"> <tr> <th>' + 'Pets</th> </tr> '; for (var i=0; i<dataArrayLen; i++){ insertData += ' <tr> <td>' + dataArray[i].getAttribute('type') + '</td> </tr> '; } insertData += '</table> '; document.getElementById ('dataArea').innerHTML = insertData; }
(Sheneyan注:修改后的示例见:example_2_2.html,XML文件见:data_2_2.xml)
关键的不同在于我们通过dataArray[i].getAttribute('type')取得值,它返回了当前
继续…
现在我们已经知道了一些从一个单独的XML数据组中取回数据的有效方法,让我们看看如何从多个组中取回数据。和只是列出一个pets所拥有的内容不同,我们假设我们有一个针对我们宠物的日课表。因为它们都有不同的需要,每一只宠物都得仔细的照顾。面对这种情况,动物的看管员需要一个每日依据。现在来让我们将这些放入一个良好格式的XML:
<?xml version="1.0" encoding="UTF-8"?> <data> <pets> <pet>猫 <task>喂食</task> <task>饮水</task> <task>抓跳蚤</task> </pet> <pet>狗 <task>喂食</task> <task>饮水</task> <task>带出去遛遛</task> </pet> <pet>鱼 <task>喂食</task> <task>检查氧气,水的纯度,其它</task> </pet> </pets> </data>
也许这个看起来很奇怪,但这就是我们正在创建的子组(sub-group)。每一个
在我继续之前,你也许希望将你的表格用一些css美化一下,比如:
table, tr, th, td { border: solid 1px #000; border-collapse: collapse; padding: 5px; }
这让这个表格更容易读取。现在让我们去研究函数processXML:
function processXML(obj){ var dataArray = obj.getElementsByTagName('pet'); var dataArrayLen = dataArray.length; var subAry, subAryLen; var insertData = ' <table> <tr> <th>' + 'Pets</th> <th>Tasks</th> </tr> '; for (var i=0; i<dataArrayLen; i++){ insertData += ' <tr> <td>' + dataArray[i].firstChild.data + '</td> '; subAry = dataArray[i].getElementsByTagName('task'); subAryLen = subAry.length; insertData += ' <td>'; for(var j=0; j<subAryLen; j++){ insertData += subAry[j].firstChild.data; if( subAryLen != j+1 ) { insertData += ', '; } } insertData += '</td> </tr> '; } insertData += '</table> '; document.getElementById ('dataArea').innerHTML = insertData; }
(Sheneyan注:修改后的示例见:example_2_3.html,XML文件见:data_2_3.xml)
新增加的内容,首先是两个新变量的声明:subAry和subAryLen。它们和之前的变量dataArray和dataArrayLen类似,除了它们指向不同的数组(特别是它们将指向那些task元素-当dataArray和dataArrayLen指向pet元素的时候)。
我们也改变了变量insertData的初始值-我们增加了一个表格头(
下一步改变在于循环:我们把值赋给subAry和subAryLen变量。变量subAry成为当前
我们创建了一个内嵌的循环来处理所有的
接下来,我们检验当前
j+1(或者,当循环再次开始的时候j的值)等于subAryLen(当前
j+1不等于subAryLen,我们直到我们可以安全的加入逗号到insertData,为下一个一旦内循环结束,我们关闭task数据格以及pet行。外部循环会重新开始创建一个新行以及移动到下一个
有其他方法吗?
你也许会想:“那javascript变得相当复杂了,但它只会随着XML越来越复杂而跟着变复杂,也许我们能够简化XML,然后,简化javascript”。如果你这么想,很棒,因为你完全正确。我之前展示的不同方法之一,我详细说明的那个也许能够成为最合适的。我们怎么使用属性来对应每一只宠物以及相应任务?XML看起来会变成怎样?
<?xml version="1.0" encoding="UTF-8"?> <data> <pets> <pet type="猫" tasks="喂食, 饮水, 抓跳蚤" /> <pet type="狗" tasks="喂食, 饮水, 带出去遛遛" /> <pet type="鱼" tasks="喂食, 检查氧气,水的纯度,其它" /> </pets> </data>
哇哦!看起来简单多了。让我们看看我们的processXML函数如何修改:
function processXML(obj){ var dataArray = obj.getElementsByTagName('pet'); var dataArrayLen = dataArray.length; var insertData = ' <table> <tr> <th>' + 'Pets</th> <th>Tasks</th> </tr> '; for (var i=0; i<dataArrayLen; i++){ insertData += ' <tr> <td>' + dataArray[i].getAttribute('type') + '</td> ' + ' <td>' + dataArray[i].getAttribute('tasks') + '</td> </tr> '; } insertData += '</table> '; document.getElementById ('dataArea').innerHTML = insertData; }
(Sheneyan注:修改后的示例见:example_2_4.html,XML文件见:data_2_4.xml)
就像你猜的一样,函数简单多了。因为代码变得简单,它也会变得更有效率。和我们比较老的函数的唯一的不同在于这个变量insertData现在插入更多的HTML,尤其是两个新变量“type”和“tasks”。就如我们较早之前所学的,那些属性是我们从XML文档的
最后的XML格式化的方法是将两部分混合。现在,我们将使用属性和不同的标签。让我们看一下示例XML:
<?xml version="1.0" encoding="UTF-8"?> <data> <pets> <猫 tasks="喂食, 饮水, 抓跳蚤" /> <狗 tasks="喂食, 饮水, 带出去遛遛" /> <鱼 tasks="喂食, 检查氧气,水的纯度,其它" /> </pets> </data>
这也许是最便于理解的XML。让我们分析一下我们为了让processXML函数运作起来所作的变更:
function processXML(obj){ var dataArray = obj.getElementsByTagName('pets')[0].childNodes; var dataArrayLen = dataArray.length; var insertData = ' <table> <tr> <th>' + 'Pets</th> <th>Tasks</th> </tr> '; for (var i=0; i<dataArrayLen; i++){ if(dataArray[i].tagName){ insertData += ' <tr> <td>' + dataArray[i].tagName + '</td> ' + ' <td>' + dataArray[i].getAttribute('tasks') + '</td> </tr> '; } } insertData += '</table> '; document.getElementById ('dataArea').innerHTML = insertData; }
(Sheneyan注:修改后的示例见:example_2_5.html,XML文件见:data_2_5.xml)
dataArray现在指向了
还是一样,每个节点之间的有空格,所以在我们的处理过程中得排除掉文本节点。我们能够检验标签名是否存在-文本节点是节点但没有标签,而<猫 />,<狗 />,<鱼 />节点都是标签。所以如果一个标签有名字,那我们能够将数据插入变量insertData。我们插入的数据是一个表格并有两个表格数据格。这第一个单元格是标签名,也就是宠物的类型(猫,狗或鱼),而第二个单元格则是指定动物的“tasks”属性值(比如“喂食或饮水”)。
结束语
在这篇文章里,我演示了这个例子的很多变化,你可以随意试验它们来检验哪个更适合你。只要记住一点,XML是可扩展的,所以没有错误的方法来组合你的数据,虽然经常有一个最好的方法。而且,要注意让你的XML保持格式良好。记住很多问题来自于忘记结束一个标签(比如<狗 />而不是<狗>;除非这个节点中有数据,比如下面的<狗>这里有数据哦狗>)。
我意图使XML和javascript的应用不糊涂而变得明朗。一步步的学习处理更多的数据,你能够将ajax运用于更大的用途。我希望看到ajax更多的应用于企业网站,及其它。所以如果你将这些知识应用于实践,我很高兴了解到你学到了什么。
关于作者
Jonathan Fenocchi是一个网络开发者,主攻web设计,客户端脚本,php脚本。他的网站位于:http://www.slightlyremarkable.com
Tagged with:
你可能对这些也感兴趣
Leave a comment for: "如何使用ajax开发web应用程序(2)"
Tag Cloud
- 翻译
- tweet
- 教程
- javascript
- php
- 读书
- wordpress
- wordpress插件
- 情感
- 电影
- 生活
- 音乐
- 单车
- java
- ajax
- 摄影
- 50个摄影相关教程
- PX
- 厦门
- 学习
- 工作
- css
- 笑话
- 散步
- 图片
- 游戏
- ubuntu
- photoshop
- 英语
- 编辑器
- 布局
- 短信
- 幽默
- 新闻
- oracle
- 总结
- 计划
- 爱
- 七夕
- 正则
- 人生
- opera
- 错误
- 悼念
- 效率
- 循环
- 签名
- 评论
- flash
- dj
- 王小波
- 函数
- 表格
- mysql
- html实体
- 宝宝
- 怀孕
- gfw
- 心情
- 软件
- 黑白摄影
- 宕机
- 蝴蝶
- 励志
- 李连杰
- 最后一天
- 跟风
- 活动
- 童声
- 面向对象
- xhtml
- web标准
- 下载
- 防火墙
- aptana
- web2.0
- sed
- 情商
- 测试
- 乱弹
- 缺点
- 过去
- xkx
- 考试
- 加班
- 蓝色理想
- 孙悦
- sitemap
- 算法
- msn
- emacs
- 护肤
- 三行两列
- 生日
- 鼓浪屿
- 方向
- socket
- cvs
- 锁死
- 技术
- 旅游
- 城市印象
- 苏州
- beksinski
- 网站
- quixplorer
- 黄手带
- 莫比乌斯圈
- 环保
- abstract
- 构造函数
- tag
- 禁语
- 条件编译
- 隐私
- 汇总
- 小野丽莎
- tinyurl
- 权限
- 江村经济
- html
- 编码
- wap
- ip
- sina
- 代码
- 围棋
- 休闲
- memory limit
- server error
- igoogle
- 灵数
- 圣诞
- 礼物
- 车模
- 手工
- 我们仨
- 新年
- 互联网
- 思想
- 言论
- 陈冠中
- 分享
- 中国
- 盛世
- SQL
- 查询
- phpmyadmin
- 自由
- 冯正虎
- 墙
- Lily Allen
- 政治
- 胎动
- 多态
- 运行时
- 接口
- I/O
- 流
- 事件处理
- android
- 经历
- nokia
- e72
- 失败
- 马赛克
- 图片处理
- pixelize
- tomcat
- feature
- tomcat 7
- 微软
- windows Live
- blog
- ibus
- fcitx
- spam
- akismet
- 浏览器
- Google Chrome浏览器
- midori
- microformat
- gmail
- open source
- 招聘
- 素质
- 程序员
- 壁纸
- linux
- vim
- 结婚
- 周年纪念
- 家庭
- wp-syntax
- 时间
- 网站设计
- css3
- 风景摄影
- 运动摄影
- 域名
- 域名迁移
- godaddy
- hdr
- flickr
- 街头摄影
- 自拍
- 漫画
- 感人
- demo
- christmas
- sqlite
- calibre
- kindle
- iPad draftcraft wordpress


