`
liudaoru
  • 浏览: 1575961 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

在 Ajax 中进行 XML 处理,第 3 部分: 使用 JSON 并避免使用代理[z]

    博客分类:
  • Ajax
阅读更多
From: http://www.ibm.com/developerworks/cn/xml/x-xmlajaxpt3/index.html?ca=drs-cn&ca=dkw-Ajax Mark Pruett (mark.l.pruett@dom.com), 系统构架师, Dominion 2008 年 4 月 15 日 Ajax 风格的服务器调用不一定使用 XMLHttp 请求。本系列的最后一部分介绍天气面板的最后一种方法,利用 Web 公共服务 JavaScript Object Notation (JSON) 和动态脚本标记来实现。 前两部分介绍了三种方法创建可重用的天气面板。这些方法都采用了 Asynchronous JavaScript™ + XML (Ajax) 技术,特别是 JavaScript XMLHttpRequest 对象来实现天气面板库。这些方法都使用了某种形式的 Web 代理将 XML 天气数据从 National Weather Service (NWS) XML 搬到我的服务器上,以避免 Ajax 的同一域问题。 本系列中的其他文章 在 Ajax 中进行 XML 处理,第 1 部分:4 种方法 在 Ajax 中进行 XML 处理,第 2 部分:两种使用 Ajax 和 XSLT 的方法 本系列的 第 1 部分 详细讨论了同一域 问题,出于安全上的考虑将 XMLHttp 请求限制到提供原始 Web 页面的同一台服务器上。实际上,很多 Ajax 应用程序都需要超出一台服务器范围之外的其他数据。因此设计的时候必须确定访问 Web 服务器配置(比如创建 Apache ProxyPass 规则)还是创建专门的服务器脚本。 实践证明,还有另一种办法。它避免了同一域问题,程序员不需要处理上面所述的任务。 常用缩写术语 DOM:文档对象模型 HTML:超文本标记语言 RSS:富站点摘要 XML:可扩展标记语言 XSLT:可扩展样式表语言转换 方法 4 需要的工具 详细讨论天气面板库的最后一种实现之前,首先介绍一下所需的工具: Yahoo! Pipes JSON 动态脚本标记 Yahoo! Pipes Yahoo! Pipes 是一种基于 Web 的工具,可以聚合能够通过 Web 访问的不同类型的数据,比如 RSS 提要。Yahoo! Pipes 使用图形化编辑器(如 图 1)编辑器创建,该编辑器可在标准 Web 浏览器中运行,如 Windows® Internet Explorer® 或 Firefox。 图 1. Yahoo! Pipes 编辑器 可通过把模块从工具面板上拖拉布置到画布上来创建管道。模块输出到另一个模块输入之间的管道将模块联系起来。 完成的 Yahoo! Pipe 有一个惟一的 URL。访问该 URL 时,Pipe 逻辑在 Yahoo! 服务器上执行。服务器处理所有的数据访问,执行数据操作并输出结果。默认情况下数据以 RSS 格式输出,但是允许在 URL 中指定其他数据格式,包括 JSON。很快将看到能够以 JSON 格式输出数据这一点至关重要。 天气面板模块使用的 NWS 数据可作为 Yahoo! Pipes 的数据源。四字符 NWS 站点 ID 可作为 Yahoo! Pipe URL 的参数。 图 1 显示了最后一种天气面板实现所使用的管道。虽然 Yahoo! Pipes 能够完成非常复杂的数据处理功能,但这里只有一个目的:将 NWS 数据从 XML 转换成 JSON。 JSON 前面已经多次提到过 JSON。它是什么,我为何要在天气面板应用程序中使用呢? JSON 即 JavaScript Object Notation,JavaScript 语言本身支持的一种数据格式。和需要 JavaScript 程序解析的 XML 不同,JSON 就是 JavaScript 代码。 作为 JSON 和 XML 的比较,首先看看弗吉尼亚州 Richmond NWS 数据的 XML 版本,如 清单 1 所示。 清单 1. XML 格式的 NWS 数据 <?xml version="1.0" encoding="ISO-8859-1"?> <current_observation version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation= "http://www.weather.gov/data/current_obs/current_observation.xsd"> <location>Richmond International Airport, VA</location> <station_id>KRIC</station_id> <observation_time> Last Updated on Jan 26, 1:54 pm EST </observation_time> <weather>Mostly Cloudy</weather> <temperature_string>41 F (5 C)</temperature_string> <relative_humidity>32</relative_humidity> <wind_string>Calm</wind_string> <visibility_mi>10.00</visibility_mi> <icon_url_base> http://weather.gov/weather/images/fcicons/ </icon_url_base> <icon_url_name>bkn.jpg</icon_url_name> </current_observation> 清单 2 是这些数据的 JSON 版本。 清单 2. 转化成 JSON 格式的 NWS 数据 { "count": 1, "value": {"title": "NOAA Regional Weather", "description": "Pipes Output", "link": "http:\/\/pipes.yahoo.com\/pipes\/pipe.info?_id=CI6HgSh43BGP8nmJouNLYQ", "callback": "", "items": [ { "location": "Richmond International Airport, VA", "station_id": "KRIC", "observation_time": "Last Updated on Jan 26, 1:54 pm EST", "weather": "Mostly Cloudy", "temperature_string": "41 F (5 C)", "relative_humidity": "32", "wind_string": "Calm", "visibility_mi": "10.00", "icon_url_base": "http:\/\/weather.gov\/weather\/images\/fcicons\/", "icon_url_name": "bkn.jpg", } ] } } 简单地说,JSON 就是一种 JavaScript 数据结构。上面清单中的 JSON 可以方便地赋给 JavaScript 变量然后引用,如 清单 3 所示。 清单 3. 在 JavaScript 代码中访问 JSON 数据结构 var weather = { "count": 1, "value": { "items": [ { "location": "Richmond International Airport, VA", ... } ] } }; alert (weather.value.items[0].location); 上述 JavaScript 代码片段将缩减后的 JSON 数据赋给 JavaScript 变量 weather。location 元素作为 JavaScript alert() 函数的参数引用。地点数据显示在弹出的警告窗口中,如 图 2 所示。 图 2. 通过 JSON 显示在 alert() 中的地点 和访问等价的 XML DOM 结构相比,多数 JavaScript 程序员认为引用 JSON 数据结构更简单更直观。这也足以说明为何在 Ajax 应用程序中这种数据结构越来越普遍。 但是 JSON 吸引 Ajax 开发人员还有另一个原因:通过某种 JavaScript 技巧,JSON 可以避免代理数据。 动态脚本标记 前述三种天气面板库的实现方法有一个共同的特点。浏览器中运行的 JavaScript 程序必须(通过 XMLHttp 请求)从我自己的 服务器上请求数据。这是由于 XMLHttp 请求的同一域限制造成的。 此前有两种方法使用 Apache ProxyPass 规则来解决这个问题,还有一种使用专用的服务器端脚本从 NWS 服务器上获取数据。 但是如果不能改变服务器配置或者不能运行服务器端脚本怎么办呢? 有一种技术允许 JavaScript 程序访问其他域中服务器上的数据。这种技术有时候被称为脚本标记 hack。 为了说明其工作原理,首先来看看 HTML 脚本标记。通常嵌入 Web 页面作为包含 JavaScript 代码库的一种办法,如 清单 4 所示。 清单 4. HTML script 标记 <html> <head> <title>An Example</title> <script language="JavaScript" src="some_javascript_code.js"></script> 清单 4 显示了一个 Web 页面中的前面几行。最后一行的脚本标记说明,将从服务器上加载名为 some_javascript_code.js 的 JavaScript 源文件。src 属性指定了脚本位置的 URL。该例中的脚本位于同一台服务器上,但并非必须如此。可以包含任务服务器上的 JavaScript 代码。 这就意味着使用脚本标记可把 JSON 数据加载到浏览器中,后者恰恰是 JavaScript 代码。对于天气面板应用程序来说似乎意义不大,因为脚本标记本身就是打开页面时加载的 HTML 的一部分。对于 Ajax 解决方案,需要在页面加载之后 发送服务器请求。 不过 JavaScript 代码可以操纵 Web 页面 DOM。可以添加和修改 Web 页面中的数据。如果在 JavaScript 代码中动态创建脚本标记并添加到 DOM 中会怎么样呢?结果如 清单 5 所示。 清单 5. 动态创建 script 标记 var head = document.getElementsByTagName("head").item(0); var script = document.createElement ("script"); script.src = "some_javascript_code.js"; head.appendChild (script); 执行后将在当前页面的 head 标记中增加一个新的 script 标记。它相当于 清单 4 中的 HTML 片段,只不过 some_javascript_code.js 中的 JavaScript 代码是在页面加载之后又加载的。 方法 4:JSON 和动态脚本标记 您可能怀疑这对于天气面板库来说有什么价值。假设 some_javascript_code.js 文件的内容如下: alert ("Hello!"); 一旦 JavaScript 文件加载到浏览器中, JavaScript 解释器就会运行包含的任何可执行代码。因此会立刻显示一个警告窗口。 由于从 Yahoo! Pipes 生成的 JSON 数据是 JavaScript 代码,所以也可通过上述技术动态加载。但 Yahoo! Pipes JSON 数据不是可执行 JavaScript 代码,而仅仅是一种 JavaScript 数据结构。可以加载到浏览器,但是如何知道什么时候加载的? 在创建动态标记之前设置某种定时器,然后假定 JSON 在某个时间,比如说 3 秒之后到达,这种方法初看起来似乎可行。从好的方面说这种方法不可靠,而且实践证明这是不必要的。 每个 Yahoo! Pipe 都有惟一的 URL。清单 6 显示了 NWS 管道的 URL。 清单 6. NWS Yahoo! Pipe URL http://pipes.yahoo.com/pipes/pipe.run? &_id=CI6HgSh43BGP8nmJouNLYQ &textinput1=KRIC &_run=1 &_render=json &_callback=myfunction 为了更清楚的看到不同的参数,我将 URL 分成了几行。_id 参数标识了这是我使用的管道,textinput1 给出了 NWS 站点 ID。_run 参数说明希望执行该管道,_render 告诉 Yahoo! Pipes 服务器以 JSON 格式输出数据。 最后一个参数 _callback 做什么呢?它告诉 Yahoo! 服务器将数据封装到指定的函数调用中,即 myfunction()。Yahoo! Pipes 返回 JavaScript 程序的结果如下: myfunction ( {"count":1, ... } ); 为了简化我省略了大部分 JSON 数据,但道理您应该清楚了。和前面加载包含 alert() 调用的 JavaScript 文件一样,JavaScript 解释器执行上述代码,调用 myfunction() 并把请求的全部数据传递给该函数调用。 利用回调函数完全不需要知道服务器什么时候完成 JSON 数据的加载。 那么回调函数中有什么?对于我的天气面板库,它完成天气数据的格式化,和方法 1 中的 XMLHttpRequest 响应函数非常类似。在方法 1 中,我从 responseXML DOM 对象中提取需要的数据。这里只需要访问 JSON 数据结构,如 清单 7 中的 jsonHandler 方法所示,这就是天气面板 JSON 方法的全部代码。 清单 7. 天气面板库的 JSON/Yahoo! Pipes 实现:weather_badge_ypipes_json.js var yp = new Array(); var idx = 0; function weather_badge (nws_id, div_name) { var callback_obj = "yp[" + idx + "]"; var url = "http://pipes.yahoo.com/pipes/pipe.run?" + "&_id=CI6HgSh43BGP8nmJouNLYQ" + "&textinput1=" + nws_id + "&_run=1" + "&_render=json"; yp[idx] = new YPipesWeather (url, div_name, callback_obj); yp[idx].requestJSON (); idx++; } // The YPipesWeather constructor function YPipesWeather (ypipes_url, div_name, obj_name) { this.url = ypipes_url + "&_callback=" + obj_name + ".jsonHandler"; this.div_name = div_name; } // The requestJSON method: it builds the script tag // that launches our request to the Yahoo! server. YPipesWeather.prototype.requestJSON = function () { // Dynamically create a script tag. This initiates // a request to the Yahoo! server. var head = document.getElementsByTagName("head").item(0); var script = document.createElement ("script"); script.src = this.url; head.appendChild (script); } // The jsonHandler method: this is our callback function. // It's called when the JSON is returned to our browser // from Yahoo!. YPipesWeather.prototype.jsonHandler = function (json) { var div = document.getElementById (this.div_name); var weather = json.value.items[0]; var html = ""; html += "<center>\n"; html += "<b>" + weather.location + "</b><br>\n"; html += weather.weather + "<br>"; html += "<img border='0' src='" + weather.icon_url_base + weather.icon_url_name + "'><br>"; html += weather.temperature_string + "<br>"; html += "Wind: " + weather.wind_string + "<br>"; html += "Humidity: " + weather.relative_humidity + "%<br>"; html += "Visibility: " + weather.visibility_mi + " miles<br>"; html += "<br><span style='font-size: 0.8em; font-weight: bold;'>" + weather.observation_time + "</span><br>"; html += "</center>\n"; div.innerHTML = html; } 和前面的所有方法一样,也实现了 weather_badge() 函数。并向该函数传递四字符的 NWS 站点 ID 和 HTML DIV 标记名称。DIV 标记就是呈现天气面板的页面区域。 其他代码定义了名为 YPipesWeather 的 JavaScript 对象。该对象包括三个函数:构造器、动态创建脚本标记(从而运行 Yahoo! Pipe)的方法和一个回调函数。 结果是一个 JavaScript 库,虽然没有用 XMLHttpRequest 对象,但行为和前面三种方法相同。 图 3 显示了最后这种方法的数据管道。除了最开始打开页面,不需要再访问我的 Web 服务器。 图 3. JSON 和动态脚本标记 清单 8 显示了利用天气面板库的 JSON 版本的示例 HTML Web 页面。 清单 8. 在 Web 页面中使用 JSON 天气面板库 <html> <head> <title>JSON Script Tag Example</title> <link rel="stylesheet" type="text/css" href="weather.css" /> <script language="JavaScript" src="weather_badge_ypipes_json.js"> </script> <script> function init () { weather_badge ("KRIC", "target1"); } </script> </head> <body onload="init();"> <h3>JSON Script Tag Example</h3> <div class="wbadge" id="target1"> Loading... </div> </body> </html> 这四种方法的比较 回顾一下,我介绍了实现 Ajax 天气面板库的四种不同方法 从 NWS 服务器读取 XML 数据 解析 XML 数据提取需要的部分 将提取的数据格式化为 HTML 在 Web 页面中显示 HTML 表 1 描述了这四种方法。 表 1. 天气面板库的四种版本 方法说明 1:遍历 DOM 树 服务器上的简单 Web 代理从 NWS 服务器获取数据并发送给浏览器。在浏览器中,JavaScript 解释器从返回的 responseXML DOM 树提取数据,设置 HTML 格式并插入 Web 页面的 DIV 标记。 2:服务器上的 XSLT 服务器端脚本从 NWS 服务器获取数据,使用 XSLT 将其转换成 HTML,然后将 HTML 片段返回浏览器。浏览器直接将其插入 DIV 标记。 3:客户端 XSLT 这种方法使用简单的 Web 代理(和方法 1 相同)将 XML 数据返回浏览器。和方法 1 不同的是,它利用 XSLT 将 XML 转换成 HTML 并插入 DIV 标记。 4:JSON 和动态脚本标记 使用外部服务(Yahoo! Pipes)将 NWS 数据从 XML 转换为 JSON。天气面板库利用专门的 JSON 和 JavaScript 语言把转换后的数据返回浏览器 — 不需要代理。 哪种方法最好?即便像这样一个简单的程序,答案也不是显而易见的。最佳解决方案有什么特点? 最后一种办法使用 JSON 避免了通过代理的需要。如果情况不允许修改服务器配置或者不能编写服务器脚本,这种办法实现起来最简单。但副作用是必须捆绑到第三方 Web 服务 Yahoo! Pipes。如果 Yahoo! 改变了服务,是否会破坏我的解决方案? 在服务器端将 XML 转换成 HTML 的方法 2 又如何呢?把大部分工作交给服务器是否合适?结论和您在多大程度上信赖 JavaScript 语言(跨越多种浏览器版本)有关。方法 3 说明了如何将大部分处理放到浏览器上。但是和能够控制的服务器脚本不同,用户使用的浏览器可能千差万别。而且如第 2 部分所述,不同的浏览器采用不同的方式完成 XSLT 处理这类任务。和后端服务器脚本相比,JavaScript 代码的调试更困难。除非所有浏览器上的 JavaScript 语言都是标准的,尽量减少 JavaScript 代码是一种谨慎的策略。 XSLT 又怎么样呢?使用 XSLT 抽象 XML 到 HTML 转换是否合理?方法 1 给出了一种替代方案,在 JavaScript 代码中访问 XML DOM 树;方法 4 给出了另一种方法,利用软件服务把 XML 转换成 JSON 然后访问 JSON 数据结构。使用 XSLT 很容易把转换从服务器转移到浏览器,反之亦然,不需要改变 XSLT 代码。XSLT 抽象层的代价是什么?我打赌方法 1 比方法 3 更快,因为前者直接访问大量已经解析的 XML 数据。浏览器端 XSLT 版本需要对这些 XML 数据运行 XSLT 处理程序 — 无疑需要更多的处理。 没有一种答案绝对正确,即便是天气面板这么简单的问题。可以客观的分析算法效率和执行速度,但实践中最终会遇到某些主观的问题。XSLT 抽象是否抵得上速度上的损失?对这类问题还需要考虑速度吗?在浏览器上运行更合理吗?可靠、简单和容易维护重要吗? 我使用哪种方法? 分享这篇文章…… 提交到 Digg 发布到 del.icio.us Slashdot 一下! 那么,如果我不是为了介绍这些技术来举天气面板的例子,我会用哪种方法呢?如果我能够肯定这不是一个实验性的解决方案,我会选择对方法 1 略加修改,即访问 XMLHttpRequest 返回的 XML DOM 树。如果这是很多面板应用程序中的第一个(可能还有用于股市图或者通用新闻提要显示的应用程序),我会选择更抽象的方法,比如那两种 XSLT 解决方案。如果希望别人在很多不同的服务器上使用面板,我将选择 JSON/Yahoo! Pipes 方法。如果这些需求互相交叉,我宁愿回到最初的解决方案。
分享到:
评论

相关推荐

    AJAX技术Ajax.7z

    3. **XML**:尽管名字中含有XML,但实际传输的数据并不一定是XML,也可以是JSON、HTML或纯文本等格式,因为JSON更轻量级且易于处理,现在更常见。 **二、AJAX的工作流程** 1. **创建XMLHttpRequest对象**:这是...

    疯狂Ajax讲义(第3版) 1-12章 源代码 完整版

    这一章将介绍JSON格式,以及如何在Ajax中使用JSON进行数据传输,包括序列化和反序列化JSON数据。 4. 第4章:DOM操作 Document Object Model(DOM)是HTML和XML文档的结构表示,Ajax常用DOM来动态更新页面内容。本...

    json常用方法,json解析

    服务器端可以接收通过 AJAX 发送的 JSON 数据,并进行相应的处理。 ```javascript $.ajax({ type: "GET", url: "/getData", success: function (data) { console.log(data.name); // 输出 "John" } }); ``` #...

    z-tree-2.6,json,ajaxz-tree-2.6,json,ajax

    AJAX(Asynchronous JavaScript and XML)技术允许网页在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页内容。在zTree中,AJAX常用于实现节点的懒加载,即当用户首次打开页面时,只加载根节点,当用户...

    ajax笔记+源代码.7z

    Ajax(Asynchronous JavaScript and XML)是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。这一技术通过在后台与服务器进行少量数据交换,使网页实现异步更新,极大地提升了用户体验。Ajax的核心是...

    根据经纬度对离线地图进行标点示例(用Ajax调用后台接口返回Json数据)

    在本示例中,我们将探讨如何使用经纬度坐标在离线地图上标注点,并通过Ajax调用后台接口来获取Json数据。这个过程涉及到的技术栈包括Java、JavaScript、OpenLayers、HTML和CSS,这些都是构建Web地图应用的关键技术。...

    基于javaweb和ajax的省市联动实现

    Ajax是Web2.0技术的重要组成部分,它通过在后台与服务器进行少量数据交换,使网页实现局部刷新。这种方式避免了整个页面的重新加载,提高了交互性。在JavaWeb中,通常使用JavaScript库如jQuery或者原生的...

    Ajax实现下拉列表从数据库读取数据级联

    在网页开发中,Ajax(Asynchronous JavaScript and XML)技术被广泛用于实现页面的无刷新更新,提高用户体验。本文将深入探讨如何使用Ajax实现下拉列表(Dropdown List)从数据库读取数据并实现级联效果。级联下拉...

    Ztree操作 AJAX

    在本案例中,我们使用AJAX从服务器获取JSON格式的服务分类数据,并将其渲染到Ztree上。 ### 结合Ztree与AJAX 为了实现Ztree与AJAX的结合,首先需要配置Ztree的设置对象`setting`,然后通过AJAX请求获取数据并初始...

    Ajax购物车实例(Ajax cart).7z

    Ajax(Asynchronous JavaScript and XML)是一种创建动态网页的技术,通过在后台与服务器进行少量数据交换,可以在不重新加载整个网页的情况下更新部分网页内容。Ajax的核心是XMLHttpRequest对象,它允许JavaScript...

    demo6(2).zip_ajax_direction166_html_javaweb_silverl8z

    在IT行业中,Ajax(Asynchronous JavaScript and XML)是一种在无需刷新整个网页的情况下更新部分网页内容的技术。本项目“demo6(2).zip_ajax_direction166_html_javaweb_silverl8z”是一个关于使用Ajax实现JavaWeb...

    ajax+一般处理程序登录案例,附带数据库.7z

    在IT行业中,Ajax(Asynchronous JavaScript and XML)技术是一种用于创建快速、动态网页的重要方法,它允许网页在不重新加载整个页面的情况下与服务器交换数据并更新部分网页内容。结合C#编程语言和ASP.NET框架,...

    AJAX 开发简略.7z

    **AJAX(Asynchronous JavaScript and XML)是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。它通过在后台与服务器进行少量数据交换,使网页实现异步更新。这一技术的核心在于JavaScript,XML则通常...

    json转换工具

    6. 数据交互:在Web开发中,前端通过Ajax(异步JavaScript和XML)与后端进行JSON数据的交互,通常使用HTTP的GET、POST等方法。 7. RESTful API设计:JSON是RESTful API中常用的数据交换格式,因为它的简单性和广泛...

    Ajax评论系统(SimpleAJAXCommenting).7z

    3. **JSON格式**:尽管Ajax最初与XML关联,但在实际应用中,数据通常以JSON(JavaScript Object Notation)格式传输,因为它更轻量级且易于解析。服务器返回的评论数据可能就是JSON格式,前端JavaScript可以轻松解析...

    南充海涛AJAX文章系统.7z

    服务器接收到请求后处理数据,然后将结果以XML或JSON格式返回。JavaScript解析返回的数据并更新DOM,进而改变页面的部分内容。 3. **优点**: - 提升用户体验:页面无需完全刷新,仅更新所需内容,减少用户等待...

    Java+ajax写的登录实例.7z

    2. **Ajax技术**:Ajax全称为"Asynchronous JavaScript and XML",它允许网页在不刷新整个页面的情况下与服务器进行数据交换。在登录实例中,Ajax用于异步发送登录请求,更新页面内容。通常使用XMLHttpRequest对象...

    php+ajax实现瀑布流特效代码.7z

    AJAX(Asynchronous JavaScript and XML)是Web开发的一种技术,允许网页在不重新加载整个页面的情况下与服务器交换数据并更新部分网页内容。在瀑布流特效中,AJAX通常用来异步请求新数据,以便在用户滚动到页面底部...

    中通快递查询源码-AJAX

    3. 监听服务器响应:使用onreadystatechange事件处理函数,当服务器返回响应时进行处理。 4. 解析响应数据:服务器返回的数据可能是XML、JSON或其他格式,需要解析成JavaScript对象以便操作。 5. 更新DOM:将解析后...

Global site tag (gtag.js) - Google Analytics