ajax|web|web服务|脚本
for each (var p in x.person) {
if (p.height.measure=="metric")
p.height=metricToImperial(p.height);
}
print (x);
这里是输出内容:
<people>
<person gender="male">
<name>Ant</name>
<hair>Shaggy</hair>
<eyes>Blue</eyes>
<height measure="imperial">
<feet>5</feet>
<inches>11</inches>
</height>
</person>
<person gender="male">
<name>Paul</name>
<hair>Spiky</hair>
<eyes>Grey</eyes>
<height measure="imperial">
<feet>5</feet>
<inches>12</inches>
</height>
</person>
</people>
E4X 中的 XML 命名空间(Namespace)
如果您是一名 XML 高手,那么此时您可能想知道如何使用该语法来管理 XML 命名空间。这里有三种方式来实现该操作:
首先,您可以使用内嵌的 XML 语法:
var soapMsg = <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"/>;
print(soapMsg.namespace());
http://www.w3.org/2003/05/soap-envelope
第二个方法是在创建元素之前设置缺省的 XML 命名空间:
default xml namespace = new Namespace("http://www.w3.org/2003/05/soap-envelope");
您可以将它设置为空字符串,以便对该缺省的命名空间进行重新设置,例如:
default xml namespace = ""
最后一种方法是使用 :: 运算符
var f = new Namespace("http://fremantle.org");
soapMsg.Body.f::GetStockQuote="IBM";
print(soapMsg);
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Body>
<frem:GetStockQuote xmlns:frem="http://fremantle.org">
IBM
</frem:GetStockQuote>
</s:Body>
</s:Envelope>
E4X 所具有的一个明显的优点是它完全支持 XML,包括排序功能。许多从 XML 文档到相应编程语言对象的直接映射仅仅支持符合常规对象语义的 XML 语义子集——因此就失去了不仅能够表示对象而且还表示文档的功能。但是对本文来说,它是不合适的,只要简单查看一下该规范就可以看出,E4X XML 对象具有的内置功能能够对 XML 元素进行细致准确的排序。
在 XML 中使用 Javascript 表达式
在转向 Web 服务之前,我们向您介绍的最后一个内容——使用大括号“{}”以上我们介绍了“内嵌的”XML。E4X 也允许您重新进入 JavaScript 环境,并且可以包括了计算后的表达式值。例如:
var num = 36;
var p = <paul><age>{num}</age></paul>
print(p);
<paul>
<age>36</age>
</paul>
到目前为止,我们已经介绍了 E4X 的基础知识,下面我们就可以使用这些基本知识进行以下操作。
使用 E4X 来调用 Web 服务
本节中,我们将描述如何在以下两个环境中使用 E4X:
1. 使用 XMLHttpRequest 的 Mozilla 1.8
2. Java/Rhino
您可以很容易地在浏览器中使用 E4X 来调用 Web 服务。但是这里存在问题!到目前为止,唯一的支持 E4X 的浏览器是 Mozilla 1.8 的专业版。不过我们并没有将其作为一种可移植的跨浏览器的解决方案来推荐,以下的实例演示了 E4X 如何以一种简单的方式来调用 Web 服务。在下一节中,我们将查看运行在 Rhino JavaScript 引擎中的另一种方法。
AJAX
该样本实例显示了向 SOAP 服务器发送和接收 SOAP 消息的浏览器。为了实现该操作,我们通过 XMLHttpRequest 对象来使用 E4X 。这个对象非常的有用,而且 Mozilla 和 Internet Explorer 浏览器都支持它,它允许运行在浏览器内部的脚本语言在后台中生成 HTTP 请求。实际上,这就是为什么 Google 的 GMail 能做到任何事情的原因。这种架构最近被命为 Asynchronous JavaScript+XML(AJAX)。
从根本上来说,AJAX 的目的是要通过一种比标准 HTML 和 HTTP 的“页面”模型更为灵活的方式与服务器进行交互,以此来提高 Web 页面的响应能力和可用性。有关这方面一个很好的样本是 Google Maps beta,它明显地比以前的映射 Web 站点更具交互性。
令人鼓舞的是,根据新闻报道,结合了 E4X 的 AJAX 的性能更优!我们将向您展示浏览器应用的两种版本。第一个版本演示了交互操作,而第二个版本隐藏了 Web 页面上的按钮和内部的工作过程,以此来展示交互性和异步性。
浏览器的安全性
为了演示浏览器的安全性,我们使用了 xmethods.net 上可用的标准 Web 服务。但是,这里还存在一个问题,因为一般来说,浏览器的安全性规则不允许脚本程序或者 Java applet 程序创建网络连接,除非是与生成该页面的服务器建立网络连接。否则,您需要有一个监控页面,它将您的按键操作“复制”到另外一个服务器。
但是您可以避开这种操作。为实现该操作,您需要进行两步。首先,您必须启用 Mozilla 配置中的用于脚本程序的升级特权。(假定您已经下载并安装了 Mozilla 1.8 beta)。
在该浏览器的地址栏中输入 about:config,然后将 signed.applets.codebase_principal_support 的值从 false 更新为 true。(出于安全性考虑,请记得在完成全部操作后设回原值。)
然后在脚本程序中,您可以请求使用升级特权。当该脚本语言运行时,将会提示用户使用这些特权。代码行为:
netscape.security.PrivilegeManager.enablePrivilege( "UniversalXPConnect UniversalBrowserAccess");
其它的选择就是将服务和 Web 页面部署到诸如 IBM® WebSphere® Application Server 或者 Tomcat 之类的 Web 应用程序服务器中。例如,这种方式适用 Apache Axis 和 Axis 自带的缺省股票报价机样本实例。
股票报价客户端样本
该脚本程序属于 stockclient.html 的一部分。如果您从本文下载了 ws-ajax1code.zip 文件,将其中的 zip 内容解压,然后使用 Mozilla 打开 stockclient.html,您将会看到如下内容:
图 1. Mozilla 中的 stockclient.html
为了对其进行验证,首先单击 Update URL。该操作通过使用 XMLHttpRequest 对象从 http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl(或者您在 WSDL 框中键入的任意 URL)获取 WSDL 文件,然后使用 E4X 从那里获取端口地址 URL。现在单击 Send,您将会看到 SOAP 请求被填写了。一两秒钟之后,此 SOAP 响应应该同结果字段一起被更新。我们查看一下这些代码。
股票报价客户端的脚本程序
该脚本程序带着对 IBM 的股票价格的 request 调用指定的URL。如果您正在使用 Axis 服务器,那么我们建议使用股票行情自动收录机符号 XXX,这是一种特殊的符号——部署的服务将总是返回一个固定的响应用于该收录机,而不是产生 Web 请求来得到真正的股票价格——因此使用该符号进行测试会好些。
您必须完成的第一个操作就是定义您希望使用的 E4X:
<script type="text/javascript;e4x=1">
当您按下 Send 按钮时,该脚本程序显示如下:
var s = new Namespace(
"s",
"http://schemas.xmlsoap.org/soap/envelope/");
var envelope = <s:Envelope xmlns:s={s}/>;
envelope.s::Body="";
var body = envelope.s::Body;
该操作对任何的 SOAP 请求都是通用的。它只是简单地创建了一个 SOAP 信封,而没有包括任何消息体。该操作的一个等价实现方式如下所示:
var envelope =
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body/>
</s:Envelope>
但是,前面的代码会容易些,而且也为您提供了指向主体元素的指针。
下一步是要创建消息的主体:
var x = new Namespace("x","urn:xmltoday-delayed-quotes");
body.x::getQuote = <x:getQuote xmlns:x={x}/>;
最后,你必须添加正确的符号:
var symbol = document.getElementById("symbol").value;
var getQuote = body.x::getQuote;
getQuote.symbol=symbol;
现在您已经有了一个完全成形的 SOAP 请求消息。如果您想要测试该消息信封,那么需要按照以下操作:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<x:getQuote xmlns:x="urn:xmethods-delayed-quotes">
<symbol>XXX</symbol>
</x:getQuote>
</s:Body>
</s:Envelope>
为了发送它,你必须使用 XMLHTTPRequest 对象我们创建了一个简单的辅助函数,以支持使用 XMLHttpRequest 对象来调用使用 E4X 的服务。此 execService 函数不仅支持异步方式而且也支持同步方式。
function execService(url, xml, callback) {
var xmlhttp = new XMLHttpRequest();
var async=false;
if (arguments.length==3) async=true;
xmlhttp.open("POST", url, async);
xmlhttp.setRequestHeader("SOAPAction", "\"\"")
xmlhttp.setRequestHeader("Content-Type", "text/xml")
if (async) {
var f = function() {
if (xmlhttp.readyState==4) {
callback(new XML(xmlhttp.responseText));
}
}
xmlhttp.onreadystatechange = f;
}
xmlhttp.send(xml.toString());
if (!async) return new XML(xmlhttp.responseText);
}
下面我们来详细地看看这些代码。首先,这些代码支持两种调用方式。您可以使用其中一种:
XML execService(String url, XML envelope);或者void execService(String url, XML envelope, function callback);
在这种情况下,回调函数应该是 void callback(XML x)。
于是您可以使用该函数直接调用 XML 服务,并且等待响应,或者您也可以传送一个函数,使用 XML 响应消息调用该函数。
该函数基于参数的数量来决定它是异步还是同步(3 是异步),然后简单地使用 XMLHttpRequest 对象以 POST 请求方式来把 XML 消息放到 HTTP 请求信息,并把请求发送到指定的 URL。