javascript|web|xml|数据|网页
B/S结构的程序每执行一个操作往往都需要刷新页面,在刷新过程中,服务器不但要将数据发送到客户端,还需要将一些格式信息,比如说表格、图片、标题等重新发送,占用了大量带宽。尽管IE提供了页面缓存的功能,但对于时刻发生变化的动态网页,本地缓存基本上不起什么作用。如果能够让Web服务器只传送关键数据,不传送格式就可以减少带宽占用。当然,在我的系统开发过程中,使用了智能卡进行关键数据加、解密,出于速度考虑,尽可能减少被加密的数据就可以提高信息的显示速度。
我们可以使用微软提供的webservice.htc实现通过JavaScript调用WebService,同时利用XML和XSL实现数据与格式相分离。主要技术要点如下:
一、WebService的调用:
首先从微软网站上下载webservice.htc,使用方法就不说了,网上有详细的调用说明。在网页BODY中添加一个DIV,实现对webservice.htc的引用,如下:
<div id="htcWService" url( ../../global/webservice.htc)"></div>
同时添加两个DIV,用来显示错误信息以及结果信息:
<DIV class="homemed" id="SearchResult"><b>说明:</b>输入户号,用鼠标点击“检索”按钮开始检索。</DIV>
<DIV class="homemed" id="ErrorMessage"></DIV>
编写JavaScript,实现对WebService的引用:
function openWebService()
{
htcWService.useService("../../WebServices/Garkcx.asmx?WSDL","Garkcx");
}
WebService返回经过编码的XML(在这里我们对信息进行了智能卡加密),在客户端解码后,我们可以借助MSXML实现对XML解析以备并进行格式处理。
二、异步调用WebService,解析XML
声明两个变量,用来存储ActiveX对象:
var objXMLData; //存储要解析的 XML 文档
var objXMLStyle; //存储 XSLT STYLE
通过JavaScript调用WebService的代码如下:
function doSearch()
{
var iCallID;
iCallID = htcWService.Garkcx.callService(dataArrived, "DoSearch", strUserGUID, strSearchMethod, strDataBaseName, strSearchCondition, encodeMethod);
}
因为是异步调用,所以当远程服务调用完成后会触发dataArrived方法。”DoSearch”后的内容是调用WebService所跟的参数。下面我们看看dataArrived代码:
function dataArrived(objResult)
{
if(objResult.error)
{
var strErrorCode = objResult.errorDetail.code;
var strErrorMsg = objResult.errorDetail.string;
var strErrorRaw = objResult.errorDetail.raw;
document.all('ErrorMessage').innerHTML = '<b>* 错误 -</b> 无法找到指定身份证号的用户。<br />' + strErrorMsg;
}
else
{
try
{
objXMLData = new ActiveXObject('MSXML2.FreeThreadedDOMDocument');
}
catch(e){}
// 判断解析器对象是否可以使用
if (objXMLData == null)
{
document.all('ErrorMessage').innerHTML = '* <b>错误: 不正确的 XML 解析器版本.</b><br />';
return;
}
//此处有一些解码的代码,省略
strResult = objResult.value;
// 事件不断被触发,检测XML数据是否装载完成
objXMLData.onreadystatechange = dataLoaded;
objXMLData.validateOnParse = true;
objXMLData.async = true;
// 装载从 Web Service 返回的结果
objXMLData.loadXML(strResult);
}
}
function dataLoaded()
{
// 异步访问,如果 XML 解析器的 readyState 属性为 4, 表示装载结束。
if (objXMLData.readyState == 4)
{
if (objXMLData.parseError.errorCode != 0)
// 装载过程出现错误
document.all('ErrorMessage').innerHTML = '<b>* 错误</b> - 无法解析 XML 数据结果.';
else
{
document.all('SearchResult').innerHTML = '';
ApplyXslStyle(); // 应用 XSLT 样式
}
}
}
下面将传递过来的XML应用XSL样式并显示在IE浏览器中,这是通过调用ApplyXslStyle()方法实现的。该方法使用“MSXML2.XSLTemplate”组件实现解析操作。因为XSL样式通常不会发生变化,所以本地缓存有助于提高XSL访问效率。代码如下:
function ApplyXslStyle()
{
objXMLStyle = new ActiveXObject('MSXML2.FreeThreadedDOMDocument');
objXMLStyle.async = false;
objXMLStyle.resolveExternals = false;
strXslt = '../../XSLT/Czrk.xsl';
objXMLStyle.load(strXslt);
if (objXMLStyle.readyState == 4)
{
if (objXMLStyle.parseError.errorCode != 0)
document.all('ErrorMessage').innerHTML = '<b>* 错误</b> - 无法解析 XSLT 格式.';
else
{
document.all('SearchResult').innerHTML = '';
// 格式化并输出结果
DisplayResult();
}
}
}
function DisplayResult()
{
// 创建一个新的 XSLTemplate 对象并设置样式表
var objTemplate = new ActiveXObject('MSXML2.XSLTemplate');
objTemplate.stylesheet = objXMLStyle;
// 创建处理器来处理 XML 数据
var objProc = objTemplate.createProcessor();
// 指明使用的 XML 数据对象
objProc.input = objXMLData;
// 应用 XSL 样式,并将结果赋值给字符串
if (objProc.transform() == true)
{
var strResult = objProc.output
document.all('SearchResult').innerHTML = strResult;
}
else
document.all('ErrorMessage').innerHTML = '<b>* 错误</b> - 无法对查询结果应用 XSLT 格式.';
}
这样,通过WebService传递过来的XML数据就经过XSL格式处理后显示在IE里面。下面给出几个截图:
图片(1)检索数据前
..............................................................................................
图片(2)检索数据后
..............................................................................................
图片(3)自定义检索条件
评论
# re: 用JavaScript与WebService实现网页部分数据XML传送 2004-07-18 13:52 Rover 不错,建议别用document.all来引用,最好用documeng.getElementById('控件ID')来引用,遵循w3c,还有相关的资料吗?给个链接或者资料什么的?一篇看着不过瘾 回复 更多评论# re: 用JavaScript与WebService实现网页部分数据XML传送 2004-07-18 13:59 香辣教师 用WebService Behavior有一些局限性,只有IE 5.0,IE 5.5,IE 6.0,IE 6.0 SP1支持,其他的浏览器都不支持,最近的Windows XP SP2上面的IE 6.0好像也禁用Behavior了。而且它不能垮域调用的Web Service。所以不能把WebForm和Web Service来分开部署。 回复 更多评论
# re: 用JavaScript与WebService实现网页部分数据XML传送 2004-07-18 15:24 吕震宇
相关资料的话,可以参考《ASP.NET分布式数据库应用程序高级编程》,Alex Homer DaveSussman著,清华大学出版社出版。
实际上,我这里仅仅是将项目中的一小部分摘录出来而已。当一个访问请求到达网站时,我先通过代码测试客户端IE浏览器版本以及是否支持JavaScript(代码见下),如果发现客户端不支持的话,那没将导向另外一个页面,这个页面将在服务器端将XML与XSL生成HTML(如何用C#代码实现对XML的XSL格式处理就不用多说了吧),然后将结果返回给用户,不过性能肯定收到影响。因为出于系统安全等方面的考虑,在我的系统中,使用这种方式检索的信息是受到限制的。
客户端是否支持JavaScript的检测代码:
<%
String strClientType = Request.QueryString["client"];
%>
<html>
<head>
<meta http-equiv="refresh" content="1;url=no-client-script.aspx?client=<% = strClientType %>" />
<title>检测客户端是否支持 Script 脚本</title>
<script language="JavaScript">
<!--
function jumpScripting() {
// jump to page using client-side JavaScript - if jump not executed
// then client does not have scripting available or it is disabled
window.location.href='SearchForm/<% = strClientType %>/default.htm';
}
//-->
</script>
</head>
<body onload="jumpScripting()">
<font size="2" face="宋体">检测客户端是否支持 Script 脚本 </font>
</body>
</html>
检测客户端类型的代码:
public int ClientType() {
// return an integer indicating the type of device
// 0 = Not Supported by Application
// 1 = HTML 3.2. client
// 2 = Internet Explorer 4
// 3 = Internet Explorer 5 or above
// 4 = Small Screen HTML ( < 50 chars per line or < 400px wide)
// 5 = WML Supporting Device (i.e. cellphone)
// 9 = Error While Detecting Type
// create integer variable to hold client type
int intType;
try {
// get reference to Browser Capabilities
System.Web.Mobile.MobileCapabilities objBCaps
= (System.Web.Mobile.MobileCapabilities) Request.Browser;
// check the preferred rendering type of the device
String strRenderType = objBCaps.PreferredRenderingType.ToLower();
if (strRenderType.IndexOf("wml") != -1)
intType = 5; // type is WML device
else if (strRenderType.IndexOf("html") != -1) {
intType = 1; // assume it's an HTML 3.2 device
// next check the screen size
if (objBCaps.ScreenPixelsWidth < 400 || objBCaps.ScreenCharactersWidth < 50)
intType = 4; // it's a small screen HTML device
else {
// assume it's a normal browser - check if its IE
if (objBCaps.Browser == "IE") {
// check the version number
if (objBCaps.MajorVersion >= 5)
intType = 3; // IE 5.x or above
else if (objBCaps.MajorVersion == 4)
intType = 2; // IE 4.x
}
}
}
else // not WML or HTML
intType = 0; // not recognized or supported
}
catch(Exception objErr) {
intType = 9; // error during detection
}
return intType;
}
首页Default.aspx代码:
<% Page Language="C#"%>
<!-- register the user control that contains the detection code -->
<%Register TagPrefix="GARK" TagName="GetClientType" Src="global/client-detect.ascx" %>
<!-- insert user control into the page -->
<GARK:GetClientType id="ClientDetect" runat="server" />
<script language="C#" runat="server">
void Page_Load() {
switch (ClientDetect.ClientType()) {
case 0: // not supported
Response.Clear();
Response.ContentType = "text/text";
Response.Write("Sorry, this application does not support your client type: " + Request.UserAgent);
Response.End();
break;
case 2: // IE 4.x
Response.Clear();
Response.Redirect("client-script-check.aspx?client=ie4");
Response.End();
break;
case 3: // IE 5.x and above
Response.Clear();
Response.Redirect("client-script-check.aspx?client=ie5");
Response.End();
&nb, sp; break;
case 4: // small-screen HTML device or WML client
case 5:
Response.Clear();
Server.Transfer("SearchForm/mobile/default.aspx");
break;
default: // assume HTML 3.2 client
Response.Clear();
Response.Redirect("client-script-check.aspx?client=html32");
Response.End();
break;
}
}
</script>
回复 更多评论
# re: 用JavaScript与WebService实现网页部分数据XML传送 2004-07-21 13:57 一点一滴 这个web服务怎么进行验证呢? 回复 更多评论
# re: 用JavaScript与WebService实现网页部分数据XML传送 2004-07-21 14:32 吕震宇 我没有考虑使用现有验证(Form验证、Windows验证等),而是将验证放在了智能卡中,在客户端与服务器间传送的关键数据是经过签名并加密的,系统通过对这个加密信息的验证进而实现对用户身份的验证。智能卡中的密钥是永远也读不出来的,而且智能卡从制卡到密钥分发到传送等都有一套规范的体系。 回复 更多评论
# re: 用JavaScript与WebService实现网页部分数据XML传送 2004-08-25 17:21 beloved 在MSDN上可以看出,微软在很早以前就已经放弃对webservices.htc的支持了。
最要命的是现在装了IE SP2的机器对调用ActiveX进行了限制,每次你在客户建立一个Object的时候都会提示你。这样很是不爽。不知道有没有更好的办法来解决这个问题。 回复 更多评论
# re: 用JavaScript与WebService实现网页部分数据XML传送 2004-08-25 22:18 吕震宇 beloved
谁也限制不了微软改变策略。我想微软大概将程序员赶向.net平台以及智能客户端吧。我想Flex、智能客户端以及未来微软基于XML的代码开发恐怕会占主导地位。虽然这可以解决上述问题,但我们不得不学习、学习再学习了... 回复 更多评论
# re: 用JavaScript与WebService实现网页部分数据XML传送 2004-09-10 09:10 赏梅斋 看到你的文章受益颇多,觉得这种方式被微软所放弃有点可惜. 回复 更多评论
# re: 用JavaScript与WebService实现网页部分数据XML传送 2004-09-14 10:17 aspsir 关于验证,最基本的可以使用Session来验证,同时通过WEB SERVICE的EnableSession=true来使WebMethod支持Session 回复 更多评论
# re: 用JavaScript与WebService实现网页部分数据XML传送 2004-09-19 08:25 luoluo 这个方面flash是更好的选择,比ms jscript有更好的跨平台性,flash对xml和webservice都有很好的支持。 回复 更多评论
# re: 用JavaScript与WebService实现网页部分数据XML传送 2004-09-19 12:55 吕震宇 我想Macromedia 的flex以及微软提倡的智能客户端在这方面都有很好的前景 回复 更多评论
# re: 用JavaScript与WebService实现网页部分数据XML传送 2004-09-27 08:40 赏梅斋 不过,感觉微软提倡的智能客户端过于重量级,对于轻型应用似于过于复杂. 回复 更多评论
# re: 用JavaScript与WebService实现网页部分数据XML传送 2005-02-23 02:52 PuzzledJavascriptMan 如果服务器端Webservice是Java写的,Javascript代码怎么写呀? 回复 更多评论
# re: 用JavaScript与WebService实现网页部分数据XML传送 2005-02-23 12:20 吕震宇 这个我就不清楚了。因为不能使用webservice.htc。不过你可以下载webservice.htc,然后研究一下里面的JavaScript代码,应当有所帮助。 回复 更多评论
# re: 用JavaScript与WebService实现网页部分数据XML传送 2005-03-18 14:32 cxuqiang 留下手印。。。。 回复 更多评论
# re: 用JavaScript与WebService实现网页部分数据XML传送 2005-04-09 03:21 一滴水 好搞深!! 回复 更多评论
# re: 用JavaScript与WebService实现网页部分数据XML传送 2005-06-10 18:23 li 我用的是Windows XP SP2上面的IE 6.0,有许多网页无法浏览,且无法观看视频,必须更换版本吗? 回复 更多评论
# re: 用JavaScript与WebService实现网页部分数据XML传送 2005-07-11 15:40 拙劣的程序员 研究研究 回复 更多评论
# re: 用JavaScript与WebService实现网页部分数据XML传送 2005-09-01 13:10 tonyzhang 如果这种方式只能用微软的东东开发的webservices那也太有局限性了。我用java+axis开发的webservice按照微软官方网站提供的方式进行了试验,没有成功。 回复 更多评论
# re: 用JavaScript与WebService实现网页部分数据XML传送 2005-11-03 09:37 bobox 本来是抱着很幸运的心情来看这篇文章的,因为看道htc感觉发现了我需要的钥匙。但是看完以上评述后,心又冷了。
ms webservice既然又慢。而且对真正异构系统的支持又这么烂。似乎只有用ms自己的产品系列的客户端才对它有很好的支持,微软提供了一个不错的代理。失望之情不言而喻啊。。。
回复 更多评论
# re: 用JavaScript与WebService实现网页部分数据XML传送 2005-11-28 15:04 白菜 有人说XP的SP2限制了这个东西?
我怎么没感觉到... 回复 更多评论
# re: 用JavaScript与WebService实现网页部分数据XML传送 2005-12-02 15:39 Oxygen 可以垮域,不过就是有提示,现在所有的方法,都是有提示的. 回复 更多评论
# re: 用JavaScript与WebService实现网页部分数据XML传送 2005-12-02 15:39 Oxygen 可以垮域,不过就是有提示,现在所有的方法,都是有提示的. 回复 更多评论
# re: 用JavaScript与WebService实现网页部分数据XML传送 2006-04-24 10:48 sac 那么在sp2下面能不能使用呢?
我使用的时候总是提示useService不是方法
回复 更多评论
# re: 用JavaScript与WebService实现网页部分数据XML传送 2006-05-29 11:17 e旋风 我也是使用这种
怎么代码执行完 // 装载从 Web Service 返回的结果
objXMLData.loadXML(strResult);
就不再执行function dataLoaded() 了呢 回复 更多评论