请将下面的代码完整复制到soapclient.js中
/**//*****************************************************************************
AJAX
Javascript "SOAP Client" library
Thank to Mr.Matteo Casati, Ihar Voitka - http://www.guru4.net/
Author: ZhangLiang, E-Mail:cheungmine@gmail.com
Date: 2006-8-31
*****************************************************************************/
function _debug(rownum, msg) ...{ alert(rownum+":"+msg); }
var SOAP_SUCCESS = 0;
var SOAP_FAULT = 1;
var _sr_env_hdr_ = "<soap:Envelope " +
"xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" " +
"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" " +
"xmlns:xsd="http://www.w3.org/2001/XMLSchema" " +
"xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">";
var _sr_body_hdr_ = "<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">";
var _soap_header_m_token_ = ""; // global varible, soap_header: m_token
function SOAPParams(callid, url, method, async, callback, username, password)
...{
this.callid = callid;
this.url = url; // "http://localhost/MtkWebgisServer/MtkWebgis.dll?Handler=GenMtkWebgisWSDL";
this.svc = null; //"http://cl2/MtkWebgisServer/MtkWebgis.dll?Handler=Default"; // 未完
this.method = method;
if (async+"" == "undefined")
this.async = true; // default value
else
this.async = async;
if (this.async)...{
if (callback+"" == "undefined")
this.callback = soap_callback;
else
this.callback = callback;
}
this.username = null;
if (username+"" != "")
this.username = username;
this.password = null;
if (password+"" != "")
this.password = password;
this.wsdl = null;
this.result = SOAP_FAULT;
this.xmlhttp = null; // xmlhttp object returned
this._pl = new Array(); // input parameters list
this.add = function(name, value)...{
this._pl[name] = value;
return this;
}
this.toXml = function()...{
var xml = "";
for(var p in this._pl)...{
var t = typeof(this._pl[p]);
if (t == "object" || t == "function")
xml += "<" + p + ">" + this._pl[p].toXml() + "</" + p + ">";
else
xml += "<" + p + ">" + this._pl[p].toString().replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">") + "</" + p + ">";
}
return xml;
}
this.setToken = function()...{
if (this.method=="login")...{
_soap_header_m_token_ = this.getval("snp:m_token");
}
}
this.getToken = function()...{
return _soap_header_m_token_;
}
this.getval = function(name)...{
var ret = SOAPClient._getElementsByTagName(this.xmlhttp.responseXML.documentElement, name).item(0);
return ret.text;
}
this.retval = function()...{
return this.getval("return");
}
// SOAP:Fault
this.faultcode = function()...{
return this.getval("faultcode");
}
this.faultstring = function()...{
return this.getval("faultstring");
}
this.faultdetail = function()...{
return this.getval("detail");
}
}
function SOAPClient()...{}
SOAPClient.invoke = function(params)
...{
params.result = SOAP_FAULT;
if(params.async)
SOAPClient._loadWsdl(params);
else
return SOAPClient._loadWsdl(params);
}
// private: wsdl cache
SOAPClient_cacheWsdl = new Array();
// private: invoke async
SOAPClient._loadWsdl = function(params)
...{
// load from cache?
params.wsdl = SOAPClient_cacheWsdl[params.url];
if(params.wsdl + "" != "" && params.wsdl + "" != "undefined")...{
params.svc = SOAPClient._getService(params.wsdl);
return SOAPClient._sendSoapRequest(params);
}
// get wsdl
var _xmlhttp = SOAPClient._getXmlHttp();
if (params.username+"" != "undefined")
_xmlhttp.open("GET", params.url, params.async, params.username, params.password);
else
_xmlhttp.open("GET", params.url, params.async);
if(params.async)...{
_xmlhttp.onreadystatechange = function()...{
if(_xmlhttp.readyState == 4)
SOAPClient._onLoadWsdl(params, _xmlhttp);
}
}
_xmlhttp.send(null);
if (!params.async)
return SOAPClient._onLoadWsdl(params, _xmlhttp);
}
SOAPClient._onLoadWsdl = function(params, req)
...{
if (req.readyState == 4 && req.status == 200)...{
params.wsdl = req.responseXML;
params.svc = SOAPClient._getService(params.wsdl);
SOAPClient_cacheWsdl[params.url] = params.wsdl; // save a copy in cache
return SOAPClient._sendSoapRequest(params);
}
return SOAP_FAULT;
}
SOAPClient._sendSoapRequest = function(params)
...{
// get namespace, ok
var ns = SOAPClient._getAttribValue(params.wsdl.documentElement, "targetNamespace");
// 构造SOAP请求, SOAP 2.0
var sr = _sr_env_hdr_ + "<soap:Header><snp:m_token xmlns:snp=""+ns+"">" +
_soap_header_m_token_ + "</snp:m_token></soap:Header>" +
_sr_body_hdr_ + "<snp:" + params.method + " xmlns:snp="" + ns + "">" +
params.toXml() + "</snp:" + params.method + "></soap:Body></soap:Envelope>";
// send request
params.xmlhttp = SOAPClient._getXmlHttp();
params.xmlhttp.open("POST", params.svc, params.async);
params.xmlhttp.setRequestHeader("SOAPAction", ""#"+params.method+"""); // SOAPAction: "#HelloWorld"
params.xmlhttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
if(params.async)...{
params.xmlhttp.onreadystatechange = function()...{
if(params.xmlhttp.readyState == 4)
SOAPClient._onSendSoapRequest(params);
}
}
try...{
params.xmlhttp.send(sr);
}
catch(ex)...{}
if (!params.async)
return SOAPClient._onSendSoapRequest(params);
}
SOAPClient._onSendSoapRequest = function(params)
...{
if (params.xmlhttp.readyState == 4 && params.xmlhttp.status == 200)...{
params.result = SOAP_SUCCESS; // 未完...
params.setToken(); // 设置全局变量: _soap_header_m_token_
}
if(params.async && params.callback)
params.callback(params.result, params);
if (!params.async)
return params.result;
}
// private: utils
SOAPClient._getElementsByTagName = function(document, tagName, ns)
...{
try...{
// trying to get node omitting any namespaces (latest versions of MSXML.XMLDocument)
var lst = document.selectNodes(".//*[local-name()=""+ tagName +""]");
if (lst.length == 0)
throw 0;
return lst;
}
catch (ex)...{}
// old XML parser support
if (ns+"" == "undefined")
return document.getElementsByTagName(tagName);
return document.getElementsByTagName(ns+":"+tagName);
}
SOAPClient._getService = function(wsdl)
...{
var soap_address = SOAPClient._getElementsByTagName(wsdl.documentElement, "address", "soap").item(0);
return SOAPClient._getAttribValue(soap_address, "location");
}
SOAPClient._getAttribValue = function(node, name)
...{
return (node.attributes[name]+"" == "undefined") ? node.attributes.getNamedItem(name).nodeValue : node.attributes[name].value;
}
// private: xmlhttp factory
SOAPClient._getXmlHttp = function()
...{
try...{
if(window.XMLHttpRequest)...{
var req = new XMLHttpRequest();
// some versions of Moz do not support the readyState property and the onreadystate event so we patch it!
if(req.readyState == null)
...{
req.readyState = 1;
req.addEventListener("load",
function()
...{
req.readyState = 4;
if(typeof req.onreadystatechange == "function")
req.onreadystatechange();
},
false);
}
return req;
}
else if(window.ActiveXObject) ...{
return new ActiveXObject(SOAPClient._getXmlHttpProgID());
}
}
catch (ex) ...{}
throw new Error("Your browser does not support XmlHttp objects");
}
SOAPClient._getXmlHttpProgID = function()
...{
if(SOAPClient._getXmlHttpProgID.progid)
return SOAPClient._getXmlHttpProgID.progid;
var progids = ["Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"];
var o;
for(var i = 0; i < progids.length; i++)
...{
try
...{
o = new ActiveXObject(progids[i]);
return SOAPClient._getXmlHttpProgID.progid = progids[i];
}
catch (ex) ...{};
}
throw new Error("Could not find an installed XML parser");
}
假设ATL XML WebServices实现方法如下:
[id(1), helpstring("登入系统, 获得用户令牌和全图URL, 以后任何方法调用必须给出令牌")]
HRESULT login([in] BSTR Username, [in] BSTR Password);
id(2), helpstring("刷新地图, 取地图imgURL")]
HRESULT refresh([out] DOUBLE* Scale, [out, retval] BSTR *imgURL);
客户端IE中调用如下:
<HTML>
<HEAD>
<TITLE>WebGis Demo Page - WebGis AJAX Client</TITLE>
<script language="javascript" src="ajax/soapclient.js"></script>
<script language="javascript">
// WebService URL
var g_url = "http://cl2/mtkwebgis/MtkWebgis.dll?Handler=GenMtkWebgisWSDL";
function soap_callback(rcode, params)
...{
if (rcode == SOAP_SUCCESS)
...{
switch (params.callid)
...{
case "刷新":
imgMap.src = params.retval(); // retval() 取得[out,retval]参数
alert( "当前比例:" + params.getval("Scale") ); // getval(...) 取得[out]参数
break;
}
}
else
...{
alert(params.callid+":发生错误");
}
}
function Login()
...{
// 同步调用, 获得令牌
var soap = new SOAPParams("登录", g_url, "login", false);
soap.add("Username", "cheung");
soap.add("Password", "mine");
if (SOAP_SUCCESS == SOAPClient.invoke(soap))
refresh();
else
alert("登录失败");
}
function Refresh()
...{
// 异步调用刷新, 默认回调函数soap_callback
var soap = new SOAPParams("刷新", g_url, "refresh");
SOAPClient.invoke(soap);
}
</script>
</HEAD>
<BODY onload="Login();">
<div id="divMap"><img id="imgMap"></div>
</BODY>
</HTML>
使用soapclient.js需要注意,我假设XML WebServices必须存在如上面所示的login方法,用于验证用户,而且m_token必须是soap头。login原型如下:
[ soap_method ]
[ soap_header( value = "m_token", out = true ) ]
HRESULT login(/**//*[in]*/ BSTR Username, /**//*[in]*/ BSTR Password)
...{
CHAR szID[MAX_TOKEN_LEN + 1];
*szID = 0;
DWORD dwSize = MAX_TOKEN_LEN;
HRESULT hr = m_spSessionSvc->CreateNewSession(szID, &dwSize, &m_spSession);
CHECK_FAILED(hr);
szID[dwSize] = 0;
m_token = CComBSTR(szID).Detach();
return hr;
}
这样,用户就可以通过soapclient.js在IE中直接调用ATL Server写的XML WebServices了。