WAP建站进阶
在对WAP的概念有了初步的了解之后,读者将要重点学习如何使用WML标记语言和WMLScript脚本语言进行开发。本章首先介绍了一些流行的WAP工具包,然后深入浅出地介绍了WML和WMLScript,并且还有详尽的实例供初学者参考。详细的WML标记和WMLScript函数库是难得的中文参考资料。
一、WAP工具包
目前WAP技术还处于初步的发展阶段,但是它的出现引起了公众的强烈兴趣。WAP业务在欧洲开展得较早,目前将有更多的业务在北美和亚洲展开。很多WAP开发商推出了一些WAP应用工具,以进一步加快WAP应用的发展。
WAP工具包
目前WAP技术还处于初步的发展阶段,但是它的出现引起了公众的强烈兴趣。WAP业务在欧洲开展得较早,目前将有更多的业务在北美和亚洲展开。很多WAP开发商推出了一些WAP应用工具,以进一步加快WAP应用的发展。在这里将要介绍一下目前四个主流的WAP工具包:
- Ericsson WapIDE 2.0
- Nokia WAP Toolkit 1.2
- Phone.com UP.SDK 4.0
- Motorola ADK 1.0
虽然这四家公司都是WAP论坛的主要成员,但是他们的开发工具包在很多方面都有所不同。如果读者正打算开发第一个WAP应用,建议使用Nokia WAP Toolkit作为入门工具。阅读工具包中所带的例子是学习WAP好方法。下面主要整体介绍各种工具包,具体的功能与操作可以参考前面对Nokia WAP Toolkit的功能介绍。
Ericsson WapIDE 2.0
Ericsson WapIDE 2.0具有集成化的WAP开发平台。它由一系列能支持设计和WAP测试的应用工具构成。同时它支持自己设计和更换测试设备的外形。WapIDE的SDK目前只能在Windows NT 4.0和Windows 95/98下使用。在WapIDE中还有用于测试服务器应用的程序。这些包括Perl 5.0、Tcl/Tk和Xitami Web Server。安装WapIDE需要首先安装IDE,然后安装SDK。还需要注意的是:如果不安装Xitami Web服务器,那么整个安装过程就失败了。所以如果读者已经有了其他的Web服务器,可以先关闭它。等安装完成后关闭Xitami Web服务器,再恢复原来的Web服务。在安装的时候,最好安装全部功能选项。如果不需要Xitami Web服务器,那么就不要选择Xitami Web服务器自动启动这一项。否则在重新启动机器的时候IIS会与Xitami Web服务器产生冲突!
图 3-1 WapIDE 2.0
图3-1所示是WapIDE的一个界面,其中包括浏览器(用于测试应用程序)、应用设计器(用于编写应用程序)和一系列服务器端工具集(一些工具诸如:WML/WMLScript编译器和一个语义分析器)。
图 3-2 浏览器
浏览器(图3-2)支持使用不同的设备(缺省情况下设备显示的是R320s的样子),允许使用者测试工具包中带有的WAP URLs例子,或测试自己编写的应用,这些WAP应用例子包括金融、股票和日程等的应用。在使用这个浏览器的时候有一个十分有意思的事情:必须按住开机按钮,才能启动浏览器并开始使用。否则,读者就会弄不懂它为什么不工作。
读者的大部分时间将会花费在应用程序设计上。这个部分集成了一个WML编辑器和一个WapIDE浏览器,这样编程序和测试将在一起实现。这是一个十分朴素的开发环境,相关文档也比较少,只有一些Adobe Acrobat的文档可供下载。
Nokia WAP Toolkit 1.2
Nokia的WAP工具包在某些方面很类似于Ericsson的WapIDE。两个产品都有图形开发环境、浏览器和WML/WMLScript编译器。Nokia工具包目前只能在Windows NT 4.0上运行。要注意的是Nokia WAP Toolkit需要Java运行环境。所以需要先到Sun的Java站点下载一个Java 2 SDK或者Java 2 Runtime Environment(JRE)才可以安装和使用Nokia WAP Toolkit。
工具包安装完之后,可以看到WAP工具包程序组中包括一个工具包IDE。还有很多关于WAP、WML和WMLScript的详细文档以及工具包本身的使用指导。该工具包支持在同一个应用下进行编辑、修改和测试WML/WMLScript文件等工作。
用户可以通过输入WAP应用的URLs或通过WAP网关进行浏览网页。Nokia还出售一个独立的基于WAP 服务器的Java Servlet。该产品将应用服务器功能和WAP网关功能集成到一个产品中。总体来说,Nokia WAP产品相对于Ericsson WapIDE产品显得较成熟、实用。
Phone.com UP.SDK 4.0
Phone.com公司的UP.SDK产品适用于Windows 95/98/NT 和 Solaris。与Nokia和Ericsson的产品有稍许区别,它不带有图形的IDE。也没有提供编辑和测试WML/WMLScript程序代码的集成环境。UP.SDK更着重于提供一系列可由不同语言(如:WML、Perl、C、C++和VB等)重复使用的代码库。Phone.com是WAP微浏览器制造的领先者,很多WAP手机中采用的都是Phone.com公司提供的WAP微型浏览器。模拟器UP.Simulator如图3-3所示。模拟器目前只能在Windows平台上运行。
图 3-3 UP.Simulator
UP.Simulator在启动的时候将自动连接Phone.com开发者站点,所以需要保持与Internet的连接。UP.Simulator无法脱机使用,也无法直接打开WML文件。推荐大家去试用一下该产品,它会很直观地让读者感觉到WAP的用途。在一两秒之内就能使用UP.Simulator查到本地的天气情况,看到世界各地的新闻。UP.SDK还包括有供Perl和C语言使用的库函数,可以用来生成WML文件,控制HTTP请求等。另外,UP.SDK有请求并安装SSL证书的安全性工具。Phone.com除了提供标准的WAP功能外,它还扩展了更多的WAP功能如传真、通知等。
Motorola Mobile ADK 1.0
从总体上来说MADK提供了一个完整的集成开发环境和浏览器。使用的时候会发现它的工作方式和Visual Studio的工作方式很像(图3-4)。因此对于习惯于使用微软产品的开发人员来说将是十分顺手的。另外MADK还提供了比较完整的帮助文档,里面除了介绍WML和WMLScript以外,还介绍了VoXML。
图 3-4 MADK集成开发界面
图 3-5 模拟器
如果操作系统为WinNT或者Win98,那么在安装MADK之前必须更新Java虚拟机,否则安装过程就会失败。在安装的过程当中,还将附带地安装Voice Agent。在使用的过程当中,读者会发现MADK不如Nokia WAP Toolkit成熟。例如:如果直接输入中文,就会引起编辑界面的混乱;在每次模拟完成之后,必须停止模拟器(图3-5)再重新打开,否则无法进行新的测试工作;再每次编译之后留下一大堆的WMLC文件;更奇特的是在Nokia WAP Toolkit编译通过的页面,在MADK上就可能通不过。
其他工具包
工具包 |
编辑器 |
模拟器 |
调试工具 |
例子程序 |
在线文档 |
Nokia WAP Toolkit 1.2 |
☆ |
☆ |
☆ |
☆ |
☆ |
MADK 1.0 |
☆ |
☆ |
☆ |
☆ |
☆ |
WapIDE SDK 1.2 |
☆ |
☆ |
☆ |
||
UP.SDK 4.0 |
☆ |
☆ |
☆ |
||
WAPObjects |
☆ |
☆ |
☆ |
☆ |
|
WAPPage 1.0 |
☆ |
☆ |
☆ |
||
CardONE |
☆ |
☆ |
|||
WAP Developer Toolkit 1.0 |
☆ |
☆ |
☆ |
☆ |
☆ |
PWOT WML Tools |
☆ |
☆ |
☆ |
二、WML简介
WML是一种基于XML(扩展标记语言)的一种标记语言。这种语言是为无线设备用户提供交互界面而设计的。这些无线设备包括电话、呼机和个人数字助理(Personal Digital Assistants)等等。
WML是一种基于XML(扩展标记语言)的一种标记语言。这种语言是为无线设备用户提供交互界面而设计的。这些无线设备包括电话、呼机和个人数字助理(Personal Digital Assistants)等等。
WML是为具有以下特点的设备而设计的:
- 体积小(相对于个人计算机)。
- 有限的内存和CPU大小。
- 通讯带宽窄和时延长。
现在支持WML的设备大致分为两大类:
- 电话棗其特点就是只有4~10行的文本屏幕。用户通过电话的按钮进行输入。
- 个人数字助理(PDA)棗其特点就是能支持100×100分辨率(或者更好)。用户能够通过键盘、鼠标或者手写输入。
现在正期待着其他的手持设备同样能支持WML。
因为WML支持许多功能不同的设备,因此文档中列出了这些设备至少应有的功能或者是参考设备。参考设备有以下的特点:
- 有一个显示屏幕,能显示4行字符,每行12个字符。包括保留给功能按钮的那一行。
- 支持ASCII的可打印码。
- 支持数字和字符的输入。
- 支持使用箭头或者数字按钮进行选择。
- 两个可编程功能键,ACCEPT和OPTIONS,并且显示在接近键盘的屏幕下。
- 一个PREV导航键。
- 支持垂直滚动的箭头按键。
- 支持水平滚动(不是使用自动换行)。
字符集
WML使用XML的字符集棗也就是当前使用的通用的字符集ISO/IEC-10646(Unicode 2.0)并且支持其他系列的子集(例如:US-ASCII、ISO-8859-1或者UTF-8)。不必使用整个Unicode(UCS-4)编码,除非正在使用的不是UTF-8编码。
大小写敏感
不象HTML,WML是一种大小写敏感的语言。所有的标签、属性和枚举属性都必须使用小写。在编写WML页面的时候,必须注意到大小写。包括参数的名字和参数的数值都是大小写敏感的。例如:variable1、Variable1和vaRiable1都是不同的参数。
不显示的字符
表3-2中包括了在WML中不显示的字符:
表 3-2 不显示的字符
字符 |
8位十进制值 |
换行 |
10 |
回车 |
13 |
空格 |
32 |
水平制表符 |
9 |
除非特别的指定,WML将一个或多个连续的换行、回车、水平制表和空格转换成一个空格。换句话说,忽略所有的多于一个以上的不显示字符。
例子1:
<wml><card><p>Some text</p></card></wml>
例子2:
<wml>
<card>
<p>
Some text
</p>
</card>
</wml>
上面的例子中,手工地使用换行和回车保证程序的可读性,但不是很必要。
文件开场白
所有的WML页面必须在文件的开头处声明XML文件类型:
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
为了将这个开场白自动地加入到页面中,读者可以使用函数调用来实现。
注意:为了确定WAP浏览器的类型和版本,可以通过捕获HTTP头中的USER_AGENT来进行。
Content Type
为了建立一个有效的WML信息实体(MIME type),必须在文件的开场白之前指定文件的类型:
Content-type: text/vnd.wap.wml
注意:必须(至少)在Content Type和XML文件声明之前保留一段空行。如果省略了,将造成编译器错误。过多的空行同样也会造成错误。
属性
许多WML标记有一个或多个属性标记,有些是必须的,有些是可选择的。属性可以指定附加的信息,用来确定设备如何解释这些标签。WML标记有以下两种使用方式:
- <element a1="value1" a2="value2" ...> content </element>
- <element a1="value1" a2="value2" .../>
必须使用成对的单引号或者双引号将属性值包含在内,每个属性之间使用空格分开。
引用变量
很像UNIX下的Shell变量,可以在格式化的文本、URL、选择文本等等文本内容中使用变量。
使用变量的语法如下:$(myvar)。
特殊字符
WML的保留字符:“<”、“>”、“'”、“"”和“&”。为了在文本中显示这些字符,必须按照表3-3中规定的方式指定。
表 3-3 指定特殊字符
字符 |
指定方式 |
< |
< |
> |
> |
‘ |
' |
" |
" |
& |
& |
$ |
$$ |
连续空格 |
|
- |
­ |
分号是字符标签的一个部分,不能省略。如果省略了,将可能会造成WML编译器错误。
注意:与HTML不同的是,当在URL中使用&的时候必须使用&来代替字符&。
二、WML重点
在对WML有初步了解的基础上,下面将要讲述的是WML语法中的重点部分。了解这些部分就等于对WML有了一个比较全面的了解。
基本规则
WML使用XML文档字符集,目前支持Unicode 2.0。与HTML不同,WML的所有标签、属性和规定的枚举值必须小写。卡片的名字和变量也是区分大小写。和HTML一样,对于连续的空字符,只显示一个空格。标签内属性的值必须用双引号或者单引号括起来。属性名、等号和值之间不能有空格。对于不成对出现的标签,必须在“>”前加“/”。比如:<br/>。在对变量的引用上和HTML基本相同,有以下三种形式:
- $(var1:esc)
- $(var1:noesc)
- $(var1:unesc)
三种形式,具体含义可参见HTML的相关部分。在对保留字符的处理上也基本相同,对应的替代字符请详见“字符实体”。这里要指出的是在URL的传递过程中,用来连接参数的&必须转化为&。
基本格式和文件头
wml文件的一般格式:
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
<head>
<access/>
<meta..../>
</head>
<card>
Some contents...
</card>
<wml>
结构看上去和HTML文件很类似,对于每一个页面,在其文档开头必须指明以下的类型声明:
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
千万注意字母的大小写。对于一个页面,其文件大小最好不要超过1.2K。
<wml>标签和HTML中的<html>标签一样,用来表明这是一个WML的页面。它有一个可选的“xml:lang”属性来制定文档的语言,比如<wml xml:lang="zh">表示文档语言为中文。
和HTML一样<head>标签包含了该页面的相关信息。<head>标签之间可以包含一个<access>标签和多个<meta>标签。
<access domain="域" path="/路径" />相当于HTML中的<BASE>标签,指定该页面的访问控制信息。它用两个可选的属性,domain用来指定域,默认值为当前域;path用来指定路径,默认值为“/”,即根目录。由于<access>单独使用,所以要用“/”结尾,以后对于类似的情况不再赘述。
<meta 属性 content="值" scheme="格式" forua="true|false"/>和HTML中的类似,提供了该页面的meta信息。属性是必选的,包括以下三种情况:
- name="name" UP.Link Server忽略meta数据。
- http-equiv="name" UP.Link Server将meta数据转为HTTP响应头(同HTML)。
- user-agent="agent" UP.Link Server直接将meta数据传给手机设备。
content属性也是必选的,其内容根据属性而定。scheme属性目前尚不支持。forua为可选属性,指定在该wml文件传到客户端之前,<meta>标签是不是被中间代理删除(因为传输的协议可能改变),默认值为false。
目前支持的meta数据:
- <meta http-equiv="Cache-Control" content="max-age=3600"/>
指定页面在手机内存缓存中的存储时间段,默认的为30天(除非内存耗尽)。在此期间,手机对于访问过的页面直接从缓存里调用。如果信息是对时间敏感的,可以用max-age指定页面在缓存里的生存期,最小单位是秒。如果指定为0,则每次都需通过连接服务器来调用该页面
- <meta user-agent="vnd.up.markable" content="false"/>
<meta user-agent="vnd.up.bookmark" content="指定的URL"/>
类似于普通浏览器的书签功能。当用户将一个卡片做了书签后,手机浏览器首先用一个标记记录该卡片。这个标记默认的是<card>标签中的title属性(以后会讲到)。然后当用户选择了该书签以后,浏览器就会打开被记录的URL。但是因为在默认的情况下,手机会记录所有的页面。所以,一般<meta>被用来使手机不要记录当前的URL,即<meta user-agent="vnd.up.markable" content="false"/>。此外,如果要为书签指定不同于当前页面的URL,用<meta user-agent="vnd.up.bookmark" content="指定的URL"/>。
一个页面可以包含多个卡片,每个卡片的内容可能不止一屏显示,注意页面、卡片和屏幕显示范围的关系。一个卡片用<card>和</card>包含。<card>可以包含以下可选的属性:
<card id="name" title="label" newcontext="false" ordered="true" onenterforward="url" onenterbackward="url" ontimer="url">
- id属性用来指定卡片的名字,可用来在卡片间跳转,相当于在HTML中在页内跳转时用<A NAME="jumpHere">。
- title属性用来作为书签的标记,该属性一般不会显示在屏幕上。
- newcontext属性(默认值为false)用来指示当跳转到本卡片时,手机是不是要清除以前保留的信息。包括变量、堆栈里的历史记录、重新设置手机状态等。
- ordered属性(默认值是true)表明该卡片里的内容是按固定的顺序显示,还是按用户的选择顺序来显示。这点和HTML不同,卡片里的内容可以按一定的顺序显示。默认的是按线性顺序显示,即按代码的顺序。但是,要注意的是,以下三个标签必须按以下顺序来写:<onevent>、<timer>、<do>(这和以后要讲的“事件”有关)。这样做是为了方便填表单,当ordered设置为true时,如果一个表单的内容不能在一屏里显示完,就分成多屏显示;当ordered设置为false时,手机可以显示一个概要卡片来总结有效的选项,用户可以从中选取表单选项来填写。
onXXXX属性,类似于HTML标签中的onXXXX属性,用来捕捉事件。当事件被触发时执行指定的操作(任务),在这里是转向某个URL。
显示文本
在文本的显示上WML基本和HTML相同。文字段落包含在<p align="alignment" mode="wrapmode">和</p>之间。align属性指定该段文字的对齐方式,默认的是left。其他可选择right和center;mode属性指定当一行显示不下所有的文字时是否自动换行。默认的是自动换行wrap。如果选nowrap,则在一行中显示,浏览器会通过类似于水平滚动条的机制来显示所有文字。
换行标签也一样为<br/>。这里先提一下,在表单中如果有多个<input>或者<select>,其间不要用<br/>,否则会使手机浏览器认为是断点而把表单分页显示。
文字的修饰标签有<b>、<i>、<u>、<em>、<strong>、<big>和<small>,意义和HTML里的相同。
表格的显示标签也和HTML相近,使用<table title="name" align="left|right|center" columns="列数">、<tr>和<td>来显示。<table>的title属性用来给表格取个名字,columns属性指定表的列数,不能为0。可选的align属性和前面提到的一样是对齐方式。表格中可以包含文字和图片。
请研究下面的例子程序:
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
<card>
<p align="center">
<i>Hello</i>
<b><i>World!</i></b>
<table title="mytable" align="right" columns="2">
<tr>
<td>1-1</td>
<td>1-2</td>
</tr>
<tr>
<td>2-1</td>
<td>2-2</td>
</tr>
</table>
</p>
</card>
</wml>
图3-6是使用Nokia WAP Toolkit的测试结果(表单很漂亮!)。
图 3-6 表单测试结果
显示图片
显示图片(1位黑白BMP图片)的标签一样类似于HTML。
<img alt="text" src="url" localsrc="icon" align="left" height="n" width="n" vspace="n" hspace="n"/>
属性中alt和src是必须要有的,其他是可选的。另外要注意的是<img>要放在<p>里,不能放在<do>和<option>等功能健标签和选单标签里。
- alt属性用来指定当手机不支持图片显示时用来显示的文字。
- src属性指定图片的URL,但当有了以下的localsrc属性时,手机浏览器就忽略src属性。
- localsrc属性用来指定显示存在手机ROM中的图标,如果找不到,则到UP.Link Server上去找。
- 可选的align属性用来表明图片同当前行文本的对齐方式,默认值为bottom,可选to和middle。
- height、width、vspace、hspace属性分别指定图片的长宽和距环绕文字的间距,目前不是所有的WAP手机都支持这些属性。
请研究下面的例子程序:
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
<card>
<p align="center"><img alt=":)" src="xxx.bmp" localsrc="smileyface"/></p>
</card>
</wml>
锚和任务
链接是HTML页面里最基本的功能,在WML里也一样用<a href="url" title="label">和</a>来包括用来建立链接的文字。必选属性href指定了要打开的URL;可选的title属性给该链接取个标记名字,这个名字将作为软按钮之一的ACCEPT键的标记显示在屏幕的软按钮区,所以通常可以将属性作为提示文字使用。
然而,以上的链接在WML里只是任务的一种情况。为了能够使用其他任务,所以引进了新的标签<anchor title="label">任务标签文本</anchor>。<a>其实是当任务标签为<go/>时的简单表示方式。
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
<card>
<p>
<anchor title="Link1"><go href="test1.wml"/>News</anchor><br/>
<a title="Link2" href="test2.wml">Sports</a>
</p>
</card>
</wml>
WML里的任务标签有以下几种,除了用于<anchor>,还可以用在事件中:
· <go>
用来指示浏览器显示指定的URL,包括页面的第一个卡片或者指定的卡片。语法如下:
<go href="url" sendreferer="false|true" method="get|post" accept-charset="charset">
<postfield name="name" value="value"/>
<setvar name="name" value="value"/>
</go>
其中href属性为必选,其他属性为可选。
sendreferer属性表示是否传递调用href所指定的URL的页面的URL。也就是当前页的URL,即HTTP头中的HTTP_REFERER。默认值为false,可选值为true。
method和HTML中的表单FORM的method属性一样,指定表单是以get的方式还是post的方式递交,以便CGI处理。默认的值为get,但如果未指定method但<go>与</go>间存在<postfield>,手机自动以post方式传递。
accept-charset属性可以覆盖HTTP头里指定的字符集。可以写多个字符集,如accept-charset="UTF-8,US-ASCII, ISO-8859-1"。
<postfield name="name" value="value"/>可以看作是HTML表单FORM中的<INPUT TYPE="HIDDEN" NAME="变量名" VALUE="值">,通过它可以向指定的URL传递以“变量名/值”形式的数据。name和value属性都是必选的。注意只有这里的变量是用来递交给CGI程序的。
除了<postfield>,还可以在<go>和</go>之间加入一句或者多句<setvar name="name" value="value"/>。该语句的意思是,当触发某一事件时,给变量赋值。
要注意的是:当<go>和</go>之间没有任何语句时,要用<go/>的形式,这点比较特别。比如:<anchor title="Link1"><go href="test.wml"/>News</anchor>。
· <prev>
用来将当前页面的URL压入URL历史堆栈,并打开此前的URL。若该URL不存在,则<prev>无效。语法类似<go>:
<prev><setvar name="name" value="value"/></prev>
<prev>和</prev>之间可加入一句或多句<setvar name="name" value="value"/>。若不加,则必须变成<prev/>的形式。
· <refresh>
用来刷新当前的页面,从而使得页面内的变量刷新,语法为:
<refresh><setvar name="name" value="value"/></refresh>
· <noop>
表示什么也不做。该标签不能用在<anchor>中,一般用在覆盖页面级的事件模板。
显示表单
类似于HTML的<FORM>。<fieldset>可用来包括一组表单选项,但不是必须的。前面说过,当<card>的ordered设置为false时,手机可以显示一个概要卡片来总结有效的选项,方便用户从中选取表单选项来填写。概要卡片就是根据<fieldset>和独立的输入框<input>以及选单<select>来总结的。语法为:
<fieldset title="label">表单内容</fieldset>
可选的title属性除了可以用来表示表单的名字外,还在概要卡片里作为选择项的标题。表单内容可以是嵌套的<fieldset>,输入框<input>,选单<select>和必要的提示文本。
<input name="variable" title="label" type="type" value="value" default="default" format="specifier" emptyok="false|true" size="n" maxlength="n" tabindex="n"/>
用来输入文本,除了name属性是必要的,其他可选。
- name属性,指定了用来存储该输入文本的变量名字。
- title属性,该输入框的名字,同样可被用来作为概要card页中的选项名。
- type属性,默认值为text,如选择password,则输入的数据显示为*。
- value属性,在语法和行为上等同于下面的default属性。
- default属性,指定输入框的默认值,即name属性指定变量的默认值,当用户输入新值时,该值无效,如果该值不符合以下format属性的规定,则手机忽略该默认值。
- format属性,用来格式化输入的数据,可用的标记如下,使用时可用“一位数字标记”和“*标记”的形式,前者代表N个标记型字符,如3X,后者代表任意个(小于maxlength属性的值)标记型字符。表3-4中包括了在format中常用的枚举数值及其意义。
表 3-4 格式化标记
标记 |
描述 |
A |
任何符号或者大写字母(不包括数字) |
A |
任何符号或者小写字母(不包括数字) |
N |
任何数字(不包括符号或者字母) |
X |
任何符号、数字或者大写字母(不可改变为小写字母) |
X |
任何符号、数字或者小写字母(不可改变为大写字母) |
M |
任何符号、数字或者大写字母(可改变为小写字母)或者多个字符,默认为首字大写 |
M |
任何符号、数字或者小写字母(可改变为大写字母)或者多个字符,默认为首字小写 |
- maxlength属性,指定了用户可输入的最大字符长度,最大限制为256个字符。
- emptyok属性,表示用户可否不填输入框,默认为false,即要填。
- size属性,输入框显示长度,目前未被支持。
- tabindex属性,类似于在HTML表单中按TAB键后,焦点落在哪个选项上,该值决定了选择顺序,数字大的排在后面。目前未被支持。
为了说明输入格式对用户的影响,请看下面的例子程序:
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
<card id="card1" ordered="false">
<p>
USERNAME:<input name="userName" title="User Name" type="text" value="YourNameHere" format="*M" emptyok="false" maxlength="12" tabindex="1"/>
PASSWORD:<input name="password" title="Password" type="password" format="8x" emptyok="false" maxlength="8" tabindex="2"/>
COMMENTS:<input name="comments" title="comment" type="text" value="YourCommentsHere" format="*M" emptyok="true" maxlength="30" tabindex="3"/>
</p>
</card>
</wml>
启动Nokia WAP Toolkit,并选择“Go”下的“Open Location”,在输入URL地址后,可以看到模拟器上出现图3-7所示的内容。注意光标默认地指在PASSWORD的编辑框内。
图 3-7 用户输入界面
选择“Options”进行编辑,多按几次按钮。在输入没有满8个之前选择“OK”,模拟器没有任何反应;当超过8个以后就无法再输入。这就是8x的限制在起作用。并且由于PASSWORD输入属性type为“password”因此显示出来的都是“********”(图3-8)。要注意的是:在输入的时候不要太快,否则总在一个字符上切换。如果读者用过手机,应该知道这点。
图 3-8 Password输入界面
在删除所有的字符时候,“Clear”变成了“Back”(图3-9)。模拟器返回以前的页面。
图 3-9 删除所有的字符
当编辑“User Name”的时候,发现输入的自动都变成大写(图3-10)。这是因为M起作用。如果输入超过12个字符,那么将无法再输入字符。这是maxlength在起作用。
图 3-10 编辑User Name
当然可以使用这个按钮,将输入方式切换到小写(图3-11)。
图 3-11 切换大小写的按钮
现在可以输入小写字符了!(图3-12)
图 3-12 输入小写字符
如果这个时候按“OK”,那么USERNAME就变成了“GJTMW.g”(图3-13)。这是由于M前面是“*”的缘故。它不限制输入字符的数目。但是如果将“User Name”中所有的字符清除,再选择“OK”就不行。这是emptyok在起作用。它要求至少输入一个字符。读者自己试试吧!
图 3-13 User Name已经改变
将上例<card>中的ordered的值改为“true”试试看,然后再在<p>和</p>内加入<fieldset title="field1">和</fieldset>试试看。(Nokia WAP Toolkit好像对这些变化视而不见……)
<select>选单类似于HTML表单中的<SELECT>。<select>和</select>间可包含<optgroup>和<option>标签,语法如下,所有属性都为可选:
<select title="label" multiple="false|true" name="variable" default="default" iname="index_var" ivalue="default" tabindex="n">
<optgroup title="label">选单内容</optgroup>
<option title="label" value="value" onpick="url">
事件或者文本
</option>
</select>
- title属性,如以上<input>的title属性。
- multiple属性,指定用户可否进行多项选择,默认值为false。
- name属性,用来存储用户选择项的变量名,其值为<option>标签的value属性。若用户没有选择又没有用default属性指定默认值,则手机将改变量赋值为空字符串(""),对于多项选择,每个值用“;”分开。
- default属性,可为name属性指定的变量赋成默认值。
- iname属性,用来记录用户选择项的位置,相应的值从1开始。若没选,则该值为0。
- ivalue属性,用来记录默认值所在的位置。
<optgroup>可用来将多个<option>分组,<optgroup>和</optgroup>间还可包括<optgroup>和<option>,该标签目前尚未被支持。
<option>,类似于HTML中选单的<option>,用来表示选单的可选项。<option>和</option>间可包括事件和选单的显示文本。<option>的属性为可选,其中value属性用来提供值。当选到该项后,将该值赋给<select>的name属性所指定的变量。onpick属性,用来指定用户选到该项并按ACCEPT键后所打开页面的URL。
为了说明选择项的工作方式,请看下面的例子:
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
<card id="card0" ordered="false">
<p>
Please select a city...
<select title="Cities List" name="city">
<option title="Beijing" value="c1">Beijing</option>
<option title="Shanghai" value="c2">Shanghai</option>
<option title="Hongkong" value="c3">Hongkong</option>
</select>
Please select columns...
<select title="Column List" multiple="true" name="col">
<option title="Hot News" value="l1">News</option>
<option title="Cool Sports" value="l2">Sports</option>
<option title="Pop Enter,,," value="l3">Entertainment</option>
</select>
</p>
</card>
</wml>
使用Nokia WAP Toolkit对该程序进行测试。启动Nokia WAP Toolkit,并选择“Go”下的“Open Location”。在输入URL地址后,可以看到模拟器上出现如图3-14所示。
图 3-14 首页
图3-15所示是单选框的样子:
图 3-15 单项选择
图3-16所示的是多项选择框的样子:
图 3-16 多项选择
图3-17所示的是在完成多项选择后的样子:
图 3-17 完成选择后
事件
WML的事件基本上分为两大类,一类是键盘(包括软硬按钮)输入事件,用<do>标签来处理。另一类是相关页面内部的事件,用<onevent>标签来处理。
<do>的语法如下:
<do type="type" label="label" name="name" optional="false|true">
任务</do>,任务就是以前提到的四种任务。<do>的属性中,type是必选的,其他为可选。
- label属性,指定了软按钮在屏幕上的显示文本。目前type属性为delete、help、prev时该属性无效。
- name属性,为<do>取个名字。同一的卡片里的<do>不能重名。如果卡片级的<do>和页面级的<do>同名,则覆盖页面级的<do>。
- optional属性,指定手机是不是可以忽略这个事件,默认值是false。
- type属性,指定触发的事件,具体如表3-5所示:
表 3-5 type的枚举值
枚举值 |
触发原因 |
accept |
调用ACCEPT按钮机制 |
delete |
调用DELETE按钮机制 |
help |
调用HELP按钮机制 |
options |
调用选择按钮机制 |
prev |
调用PREV按钮机制 |
reset |
调用清除和重新设定手机状态时的RESET机制(目前不支持) |
unknown |
调用unknown机制。等价于type=""(目前不支持) |
Vnd. co-type |
调用厂商特定的机制(目前不支持) |
X-*, x-* |
供以后使用(不保留)(目前不支持) |
为了演示事件的触发过程,请看下面的例子:
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
<head>
<meta http-equiv="Cache-Control" content="max-age=0"/>
</head>
<card id="card0" ordered="false">
<do type="accept" label="InputName" name="do1">
<go href="#card01"/>
</do>
<p>
NAME:<input name="userName" title="User Name" type="text" format="*M" emptyok="false" maxlength="12"/>
</p>
</card>
<card id="card01">
<p>
You name is $(userName:noesc).
</p>
</card>
</wml>
使用Nokia WAP Toolkit对该程序进行测试。启动Nokia WAP Toolkit,并选择“Go”下的“Open Location”。在输入URL地址后,可以看到模拟器上出现图3-18所示的界面。
图 3-18 主界面
在选择“Optionos”后出现了事件选择项(图3-19)。注意到“InputName”是do标签名字。
图 3-19 事件选项
在选择了“InputName”事件后,模拟器上将出现图3-20所示的界面:
图 3-20 输出姓名
<onevent>的语法如下:
<onevent type="type">任务</onevent>
必选属性type的取值如表3-6所示:
表 3-6 type属性的取值
枚举值 |
如果用户执行了以下操作就执行任务 |
onpick |
用户选择或不选一个<option>项时 |
onenterforward |
用户使用<go>任务到达一个卡片时 |
onenterbackward |
用户使用<prev>任务返回到前面的卡片时,或者按BACK按钮时 |
ontimer |
当<timer>过期时 |
请研究下面的例子程序:
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
<head>
<meta http-equiv="Cache-Control" content="max-age=0"/>
</head>
<card id="card0" ordered="false">
<p>
Please select a city...
<select title="Cities List" name="city">
<option title="Beijing" value="Beijing">
<onevent type="onpick">
<go href="#card01"/>
</onevent>Beijing</option>
<option title="Shanghai" value="Shanghai" onpick="#card01">Shanghai</option>
<option title="Hongkong" value="Hongkong" onpick="#card01">Hongkong</option>
</select>
</p>
</card>
<card id="card01">
<p>
You are Living in $(city:noesc)
</p>
</card>
</wml>
<timer/>可以用作在用户不进行任何操作的一段时间后,自动执行一个任务,任何激活卡片页面的任务和用户操作都会启动<timer/>,而任务进行时,<timer/>就停止。每个卡片只能有一个<timer/>,一个<timer/>只能触发一个任务。语法如下:
<timer name="variable" value="value"/>
其中name为可选属性,指定为一个变量名。当退出该卡片时,该变量存储此时定时器的值。当定时器超时时,手机将该变量设为0;value为必选属性,用来设置定时器的定时值,最小单位为0.1秒。
请研究下面的例子程序:
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
<head>
<meta http-equiv="Cache-Control" content="max-age=0"/>
</head>
<card id="card1" ontimer="#card2">
<timer name="time1" value="50"/>
<p align="center">
After 5s, goto card2
</p>
</card>
<card id="card2">
<onevent type="ontimer">
<go href="#card1"/>
</onevent>
<timer name="time2" value="50"/>
<p align="center">
Here is card2!
</p>
</card>
</wml>
再提一下:<onevent>、<timer>、<do>三者必须按以上顺序写。
此外在页面级还可以加入<template>,用来将事件捆绑在页面级上,语法如下:
<template onenterforward="url" onenterbackward="url" ontimer="url">
<do>或者<onevent>
</template>
请研究下面的例子程序:
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
<head>
<meta http-equiv="Cache-Control" content="max-age=0"/>
</head>
<template>
<do type="accept" label="deckPress" name="do1">
<go href="#card01"/>
</do>
</template>
<card id="card0" ordered="false">
<do type="accept" label="cardPress" name="do1">
<go href="#card02"/>
</do>
<p>
Press ACCEPT...
</p>
</card>
<card id="card01">
<p>
Here is card01
</p>
</card>
<card id="card02">
<p>
Here is card02
</p>
</card>
</wml>
四、编程指导
以下将要简明扼要地讲述WML标记的特点以及使用方法。并指导初学者学习和熟悉WML语言。在对WML有初步了解的基础上,下面将要讲述的是WML语法中的重点部分。了解这些部分就等于对WML有了一个比较全面的了解。
1. WAP构架
- WML是一种适用于无线互连网的标记语言。
- WAP(Wireless Application Protocol)是适用于无线互连网的网络协议。
- 客户是各种基于WAP协议的手持设备或者是各种模拟器。
- WAP网关有两个功能:对WML网页进行编码和解码;实现HTTP协议和WAP协议之间的转换,如图3-21所示。
- WAP服务器是指在MIME配置中设置了WML数据类型的Web服务器。
- 为什么采用WAP:方便、安全。
图 3-21 WAP构架
2. URL
- WML使用和HTML相同的引用方式。
例如:http://wap.yestock.com/index.wml
- 在URL后使用片段。
例如:http://wap.yestock.com/index.wml#login
- 相对的URL——基础URL是当前的卡片。
例如:<go href="/next" />
3. Content-type
- 在互联网上使用WML数据类型。
- 要想使用Web服务器传输WML数据类型,就需要对Web服务器的MIME设置进行配置。
- 需要增加以下数据类型:
wml:text/vnd.wap.wml
wmlc:application/vnd.wap.wmlc
wmls:text/vnd.wap.wmlscript
wbmp:image/vnd.wap.wbmp
其他可选的数据类型:
wmlsc:application/vnd.wap.wmlscriptc
wmlscript:text/vnd.wap.wmlscript
ws:text/vnd.wap.wmlscript
wsc:application/vnd.wap.wmlscriptc
4. WML字符集
- WML是XML的子集,继承了XML的字符集设置。
- WML文档默认的字符集是UTF–8。
5. 标签和属性
- 标签:
一个完整的WML标记有以下两种格式:
(1)<tag> content </tag>
(2)<tag/>
- 属性:
- 可以随意地指定或添加标签的属性。
- 属性的格式:<tag attr="abcd"/>。
- 所有的XML名字都是大小写敏感的。
- 所有的属性值都必须用双引号或单引号括起来。
6. 变量
- WML卡片中可以使用变量。
- 描述变量的语法在WML中有最高的解释优先级。
- 当空格无法表示一个变量名结束的时候,就必须使用括号将参数名括起来。
- $$在WML中代表一个‘$’符号。
- 变量语法格式有以下三种:
- $identifier
- $(identifier)
- $(identifier:conversion)
- 变量使用说明:
- 可以在字符串中使用。
- 可以在运行中更新变量的值。
- 如果变量不等同于空字符串,变量处于设置状态(NOT NULL)。
- 如果变量等同于空字符串,变量处于未设置状态(NULL)。
- 变量替代:
- 变量的数值可以代入卡片中的文本。
- 只有文本部分可以实现替代。
- 任何标签和属性都不能使用变量来替代。
- 替代将在运行期发生。
- 替代将不影响变量现在的值。
- 替代是按照字符串替代的方式工作。
- 如果一个没有定义的变量要实现替代,那么该变量将被看作空字符串。
- 变量名是由US-ASCII码、下划线和数字组成,并且只能以US-ASCII码开头。
- 变量名是大小写敏感的。
7. 美元符号
- 美元符号:
- 要想在文本中显示美元符号,必须成对使用。
- 一个美元符号表示变量替代。
- 一个简单的显示美元符号的例子:This is a $$ character。
- 有效性:
- 在美元符号后面接字符串都将被认为是变量替代或者是生效。
- 几个无效的例子:
<!--错误的变量语法-->
Balance left is $10.00.
<!--错误的位置(变量type在属性内)-->
<do type="x-$(type)" label="$type">
8. newcontext属性
newcontext等于true或false,将决定浏览是否做以下事情:
- 删除所有在当前上下文中定义的变量。
- 清除历史信息。
- 重新设置所有的状态为一个默认的状态。
例如:<card id="card1" title="Mortgage Calc" newcontext="true">
9. 大小写敏感
- WML和XML都是大小写敏感的语言。
- 所有的WML标记和属性都是小写敏感的。
- 任何枚举的属性值也是大小写敏感的。
10. 页面与卡片
- WML是XML语言的子集。
- 一个WML应用是由许多页面(deck)所组成的。一个WML的页面就相当于HTML的一页。
- 一个WML页面是由文件声明和WML标记对组成。
- WML标记对中间有一个或多个卡片组成。
- WML就是在各个卡片之间传递信息和切换。
11. WML标记对
WML标记对是指<wml>和</wml>组成的标记对。
- WML标记对是任何一个WML页面的根标签。
- WML标记对中可以包含一个或多个卡片。
- WML标记对中可以使用可选的“模板”来生成所包含的所有卡片的相关动作。
12. WML例子
先阅读下面的例子,在后面对例子中的各个部分将做详细的解释。
<?xml version="1.0"?>
<!DOCTYPE WML PUBLIC "-//WAPFORUM//DTD WML1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
<card>
<p>
Hello world !
This is the first card…
</p>
<do type="accept">
<go href="#card2"/>
</do>
</card>
<card id="card2">
<p>
This is the second card.
Goodbye
</p>
</card>
</wml>
13. 文件声明
- XML声明总是在文件的第一行。前面最好不要有空格或者换行。
<?xml version="1.0"?>
- DOCTYPE声明。
<!DOCTYPE WML PUBLIC "-//WAPFORUM//DTD WML1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">
14. 事件与导航
- WML包括导航和事件处理模块。
- WML允许作者指定需要处理的事件。
- 事件可以和所需要完成的任务捆绑在一起。
- URL导航就是这样的一个例子。
- 事件捆绑是通过几种标签声明来完成的,包括:go、do和onevent。
- do标签比go标签需要用户更多的参与。
15. do标签
- do标签提供了一个通用的事件处理机制,使得用户可以参与当前卡片的事件处理。
- WML提供一些预先定义的do模块。
- accept:确定(或接受)。
- prev:返回到上次的位置。
- help:请求帮助。
- options:上下文敏感的选项请求。
<do type="options" name="do1" label="options">
<go href="/options"/>
</do>
16. 任务
- go标签——当用户选中该标签时,就引导用户去WML中指定URL。
<go href="http://www.simpleteam.com/wireless.wml">Simple Team</go>
- prev标签——当用户选中该标签时,就引导用户去上次用户访问过的URL。
<do type="options" name="do1" label="default">
</prev>
</do>
- refresh标签——当用户选中该标签时,变量值将被重新设置。
<do type="refresh">
<refresh>
<setvar name="firstname" value="forest">
<setvar name="lastname" value="luo">
<setvar name="age" value="25">
</refresh>
</do>
17. setvar标签
- 指定在当前上下文中的变量值,从侧面影响正在运行的任务。
- 必须使用name属性指定变量的名字。
- 必须使用value属性指定所要赋给变量的值。
18. select与option标签
- select标签和option标签是用来在WML中形成选择任务。
- option标签可以指定在用户做出选择后的目标地址。
<select name="type">
<option value="boxed" onpick="#selectBoxed">boxed</option>
<option value="arranged" onpick="selectArranged">arranged</option>
</select>
19. input标签
- input标签是用来收集用户的输入。
1. name属性是用来指定变量的名字。
2. value属性可以指定变量默认的值。
<input name="firstname" type="text" value="Robert" format="*A" maxlength="32"/>
<input type="text" name="age" format="*N"/>
<input type="text" name="address" format="*M"/>
<input type="password" name="password"/>
64. type属性可以用来指定按密码输入模式进行输入,否则就是普通的文本输入模式。
65. format属性用来指定输入的内容是数字(N)、字母、字母和数字,输入长度,大写或者小写等等。
20. 文本类标签
66. 段落:<p></p>(自动换行模式切换)
67. 空白:空格、制表符和换行都将被显示为空白。
68. 重点:em(强调)、strong(特别强调)、i(斜体)、u(下划线)、big(预定义的大字体),small(预定义的小字体)。
69. br标签:建立新的一行。
<p>
<b>
Welcome to…
</b>
<strong><i>
Simple Team
</i></strong>
<u>
WAP site
</u>
</p>
21. 超链接标签
70. a标签和anchor标签被用来创建一个超级链接。选中该标签的时候,用户将被带入到链接的地址(可以是另外的页面或者是同一页面下的不同卡片)。
71. 也可以不使用a标签和anchor标签,而采用go标签中的href属性来创建一个超级链接。
<anchor>
fullow me<go href="destination"/>
</anchor>
<a href="destination">fullow me</a>
<do type="accept" label="ACCEPT">
<go href="http://www.simpleteam.com/yourcode" method="post">
<postfield name="w" value="12"/>
<postfield name="password" value="your password"/>
</go>
</do>
22. timer标签
72. timer可以用来延时显示页面或卡片,或在页面和卡片间实现切换以取得动画效果。
73. 下面的例子就是在显示“Hello World”5秒钟后,用户将被自动引导至"/next"所指定的位置:
<wml>
<card ontimer="/next">
<timer value="50"/>
<p>
Hello World !
</p>
</card>
</wml>
23. 注释
74. 简单的注释(单行或多行,注释中没有WML标记)。
<!—将注释写在这里-->
75. 使用CDATA标记来实现带有WML标记的注释。
<![CDATA[很多内容
<b>buld text</b>
……
<table culumn="2">
…
</table>
还有很多…
]]>
24. template标签
template标签声明一个在页面中所有卡片都可以使用的事件处理模块。
76. 模块中的事件处理将自动应用于同一页面中的所有卡片。
77. 某个卡片可以通过定义同名的事件处理来替代模块中的事件处理。
<wml>
<template>
<do type="options" name="do1" label="default">
<prev/>
</do>
</template>
<card id="first">
<!—该卡片将自动套用模块中定义的事件处理过程-->
…
</card>
<card id="second">
<!—该卡片将使用空操作(noop)来替代模块中定义的事件处理过程,那么就等价于该卡片中没有该事件处理过程—>
<do type="options" name="do1">
<noop/>
</do>
…
</card>
<card id="third">
<!—该卡片使用同名的事件处理替代模块中提供的事件处理—>
<do type="options" name="do1" label="options>
<go href="/options"/>
</do>
</card>
</wml>
25. table标签
78. table标签是用来创建能容纳文本和图片的表格。
align属性是用来指定对齐的方式(“L”是左对齐,“C”是对中,“R”是右对齐。默认的对齐方式是从左到右的左对齐方式)。
79. tr标签用来指定表格的行。
80. td标签用来指定表格的列。
<table culumns="2">
<tr><td>One</td><td>Two</td></tr>
<tr><td>1</td><td>2</td></tr>
<tr><td>BA</td><td>B</td></tr>
</table>
26. img标签
81. 当设备不能显示图像的时候,alt属性指定可选的文本。有时候这个属性是必须的。
82. src属性指定图像的来源。
83. align属性指定图像与相邻的文本对齐方式。
<p>
<img alt=":)" src="http://www.simpleteam.com/logo.gif"/><br/>
Welcome to…
</p>
27. postfield标签
指定向服务器指定提交时候的参数名字和参数数值。
84. Login和Password校验是最常用提交。
85. 一个使用go标签的提交例子。
<go href="http://193.120.145.194:80/wap" methos="post">
<postfield name="LI" value="$LI"/>
<postfiels name="PV" value="$PV"/>
</go>
28. 事件
86. ontimer事件:该事件发生在定时器过期的时候。
87. onenterforward事件:该事件发生在用户选中一个有效的URL之后,在正式引导用户去该URL地址之前。
88. onenterbackward事件:该时间发生在用户选中一个有效的prev操作之后,在正式引导用户之前。
89. onpick事件:该事件发生在用户选中某个选项。
<card>
<onevent type="onenterforward">
<go href="/url_to_check_security"/>
</onevent>
<p>
Help
</p>
</card>
<card onenterforward="/url_to_check_security"/>
<p>
Hello
</p>
</card>
29. WML核心数据
90. 长度:
§ 可以用整数指定画布(屏幕、纸张)的像素大小,或者用百分数表示占用的长度或宽度。
§ “50”表示50个像素。
§ “50%”表示占用一半的位置。
§ 只能用在属性值中。
30. id和class属性
91. 所有的WML标签有两个核心属性:id和class。
92. 这两个属性被用于服务器方的信息传输。
93. id提供某个标签在页面中唯一的名字。
94. class接收标签一个更多的class定义。
95. 多个标签可以使用同一个class定义。
96. class的名字是大小写敏感的。
97. 标签也可以作为class中的一个部分。
31. 编程指导
尽量使用户的操作简单、友好。
98. 建立一个操作流程图。
99. 定义每个卡片的操作。
100. 保持每个卡片小而且简单。
101. 尽量减少按键的次数。
102. 不要使用WML所有的属性(各个厂家对WML兼容情况是不同的)。
32. 创建一个新的WML文件
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
"http://www.wapforum.org/DTD/WML_1.1.xml">
<wml>
<card id="card_name" title="title_name">
<!—write your code here-->
</card>
</wml>
由于WML的格式基本上都是一样的,可以自己做一个模板。这样省去了反复录入页面开头和结尾的时间。如果使用的是MADK或者Nokia WAP Toolkit,那么在每次新生成WML文件的时候,它会自动地将模板准备好。在以后的程序中,为了说明的简洁,WML的标准开头和结尾将被省略。只要主要的卡片。
33. 增加卡片
103. 根据自己的需要改变卡片的id和title。
104. 增加卡片的内容。
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
<card id="welcome" title="welcome">
<p>
MADK WML DEMO.
</p>
</card>
</wml>
34. 增加动作
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1 //EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
<card id="welcome" title="welcome">
<do type="accept">
<go href="#greeting"/>
</do>
<p>
MADK WML DEMO.
</p>
</card>
<card id="greeting">
<p>
Welcome to the wireless bookshop.
</p>
</card>
</wml>
下面将程序在Nokia WAP Toolkit上进行测试。启动Nokia WAP Toolkit,在“Go”下选择“Open Location”。在输入URL地址后,模拟器上出现图3-22所示的界面:
3-22 欢迎界面
这个时候显示的是页面中的第一张卡片。也就是id为“welcome”的card。它的标题是“welcome”。在选择“Options”后(这是Nokia的选择习惯,不同的模拟器的操作有所不同),模拟器上出现图3-23所示的界面:
图 3-23 选择菜单
在选择“Select”之后,模拟器上出现图3-24所示的界面。这是同一个页面中的第二张卡片。该卡片的id为“greeting”。由于没有设置title参数,因此模拟器没有显示标题。
图 3-24 第二张卡片
35. 建立一个动画消息
<card id="greeting" ontimer="#card2" title="Toulkit Demo">
<timer value="30"/>
<p>
<big>
Welcome to…
</big>
</p>
</card>
<card id="card2" ontimer="#card3" title="Toulkit Demo">
<timer value="30"/>
<p>
<b>
the Wonderful
</b>
<u>
Wireless
</u>
</p>
</card>
<card id="card3" title="Toulkit Demo">
<p>
<big><i>
Bookstore.
</i></big>
</p>
</card>
在Nokia WAP Toolkit对该程序进行测试。启动Nokia WAP Toolkit,在“Go”下选择“Open Location”。在输入URL地址后,模拟器上出现图3-25所示的界面。等待3秒,将跳到下一张卡片如图3-26所示。注意value为30,其实要除上10才是以秒为单位。
图 3-25 欢迎界面
Nokia WAP Toolkit对<big>、<u>支持得还挺好!等待3秒,将跳到下一张卡片。
图 3-26 第二张卡片
对<i>的支持也不错!已经到了最后一个页面(图3-27),不会再跳动了。如果想实现反复地跳动,可以试试自己修改一下程序。如果在程序中加入了另外的事件处理,那么当用户触发这些事件的时候,动画就会停止。
图 3-27 最后一张卡片
36. 建立选项列表
<card id="card3" title="Toulkit Demo">
<do type="accept">
<go href="#cullectBookType"/>
</do>
<p>
<b><i>
BookStore.
</i></b>
</p>
</card>
<card id="cullectBookType">
<p>
Science or novel:
<select name="type">
<option value="science" onpick="#science">Science</option>
<option value="novel" onpick="#novel">novel</option>
</select>
</p>
</card>
在Nokia WAP Toolkit对该程序进行测试。启动Nokia WAP Toolkit,在“Go”下选择“Open Location”。在输入URL地址后,模拟器上出现图3-28所示的界面。
图 3-28 欢迎页面
在进入到“Options”后,模拟器上出现图3-29所示的界面:
图 3-29 选择菜单
在选择“OK”以后,模拟器上显示的就是Nokia WAP Toolkit的选择方式(图3-30)。必须选择“Options”才能进入选择状态。目前默认的是“Science”。
3-30 可编辑的选择项目
在选择“Options”之后出现了浏览选项菜单(图3-31)。当然只有“Edit Selection”这一个选项。
图 3-31 选择编辑选项
在出现了所有的可选择项目(图3-32)。默认的状态是“Science”。注意,选择“Select”和”OK”两个操作所产生的结果是不一样的。
图 3-32 所有的可选择项目
选择“Select”之后,就立即触发了“onpick”事件。显然没有找到novel这张卡片。Nokia WAP Toolkit抛出了一个错误警告!(图3-33)
图 3-33 错误警告
果选择了“OK”,那么就回到了开始的选择页面。但是默认的选择变成了“novel”,说明修改成功(图3-34)。这两个操作方式的区别在于:前者主要是用来导航,而后者将修改选择值,type这个时候应该等于“novel”。
图 3-34 修改成功
37. 建立更多的选项
<card id="science">
<p>
select science title:
<select name="productID">
<option value="universe" onpick="#price">The Universe</option>
<option value="space" onpick="#price">Facts About Space
<option value="time" onpick="#price">Time Machine
</select>
</p>
</card>
<card id="novel">
<p>
select novel title:
<select name="title">
<option value="speed" onpick="#price">Speed</option>
<option value="terminator" onpick="#price">Terminator</option>
<option value="ghost" onpick="#price">Ghost</option>
</select>
</p>
</card>
如果把上面的程序加入到3.4.36的程序中,那么在选择“Select”的时候,就不会抛出错误警告了。读者可以自己再试试。
38. 滚动和setvar
<card id="price">
<do type="accept">
<go href="#copies>
<setvar name="price" value="30.0"/>
<setvar name="discount" value="0.00"/>
</go>
</do>
<p>
Click accept to find the
Price and enter number of copies you need:
</p>
</card>
39. 使用input
105. 使用正确的格式。
106. 选择一个合适的标题。
107. 限制所输入内容的最大长度。
108. 收集名字
<card id="collectName">
<do type="accept">
<go href="#collectAddress"/>
</do>
<p>
name:
<input name="fullName" title="Full Name" format="*A" maxlength="9"/>
</p>
</card>
109. 收集地址
<card id="collectAddress>
<do type="accept">
<go href="#cardType">
<setvar name="ship" value="4.0"/>
</go>
</do>
<p>
address:
<input name="address" title="Address" format="*M" maxlength="9"/>
</p>
</card>
40. 选择信用卡类型
<card id="cardType">
<p>
what kind of credit card?
<select name="creditCardType">
<option value="visa" onpick="#cardNo">visa
<option value="mastercard" onpick="#cardNo">mastercard</option>
<option value="discover" onpick="#cardNo">dicover</option>
</select>
</p>
</card>
41. 输入信用卡号码
<card id="cardNo">
<do type="accept">
<go href="#cardDate"/>
</do>
<p>
card number
<input name="cardNumber" title="Card Number" format="*N" maxlength="16"/>
</p>
</card>
42. 输入信用卡过期日期
<card id="cardDate">
<do type="accept">
<go href="#confirmation"/>
</do>
<p>
expiration date
<input name="creditCardExp" title="Expiration Date" format="*N" maxlength="8"/>
</p>
</card>
43. 确认
<card id="confirmation">
<p>
Each is $$ $(price), you ordered $(unint) copies,
Shipping is $$ $(ship), and total is $$64,
Thank you ! Bye Bye !
</p>
</card>
44. 卡片调用
<card id="collectAddress">
<do tyoe="accept">
<go href="card.wml#cardType">
<setvar name="ship" value="4.0"/>
</go>
</do>
<p>
address:
<input name="address" title="Address" format="*M"/>
</p>
</card>
45. 复合调用
<card id="collectAddress">
<do type="accept">
<go href="http://www.abc.com/wml/card.wml#cardType">
<setvar name="ship" value="4.0"/>
</go>
</do>
<p>
address:
<input name="address" title="Address" format="*M"/>
</p>
</card>
46. 调用WMLScript
<card id="confirmation">
<do type="accept" label="Calculate">
<go href="calculateTotal.wmls#calculateTotal($(price),$(unit),$(ship))"/>
</do>
<p>
Each is $$ $(price),
You ordered $(unit) copies,
Shipping is $$ $(ship), and
Total is $$ $(total)
</p>
</card>
47. WMLScript例子
//wml script used by book store application
extern function calculateTotal(a,b,c)
{
//a: unit price
//b: number of units
//c: shipping charges
var total=a*b+c;
WMLBrowser.setVar("total",total);
WMLBrowser.refresh();
}
五、WML标记
这个部分详细地说明了WML语言中各个标记的语法和使用方法。每个标记都有一个简单的例子供参考。
1. <a>
这是短格式的锚语法。使用<a>代替<anchor>,并且只用来定义隐含的、指定了URL的<go>任务。
语法
<a href="url" <!-- required --> title="label">
...any valid combination of <text>, <br/> and <img> elements
</a>
2. <anchor>
<anchor>标签将一个格式化的文本和一个任务捆绑在一起。经常被称作超级链接,可以使用任何的文本或图标指定超级链接。当用户选择了超级链接,并且按下ACCEPT,设备就会执行该任务。
语法
<anchor title="label">task text</anchor>
task表示当用户激活超级链接以后所要执行的动作。text是设备显示在屏幕上,用来代表超级链接的文本。
task 必须指定下列任务中的一个:<go>、<prev>或<refresh>。
text设备通常将这段文字与其他的文字区别开。例如使用方括号,或者使用下划线。
title用来标识link的标签。如果不指定title属性,设备将使用“link”作为默认的属性。设备可以以不同的方式使用这个标签。例如,在用户选择的时候可以用来显示一个帮助工具条,或者一个语音提示。为了兼容所有的设备,label最好不要超过5个字符。
例子:
<wml>
<card>
<p>
Some links:<br/>
<a title="Link1"><go href="d1.wml"/>News</a><br/>
<a title="Link2"><go href="d2.wml"/>Sports</a>
</p>
</card>
</wml>
3. <access>
<access>标签用来指定WML页面的操作权限。必须在head内和其他的meta信息一起声明。每个页面只有一个<access>标签。所有WML默认的权限是public。
语法
<head>
<access domain="domain" path="path"/>
...
</head>
access的属性包括:
- domain可对WML页面进行操作的URL域。默认的是当前页面所在的域。
- path可对WML页面进行操作的其他页面所在的根目录。默认的是“/”(当前页面所在的根目录)这就使得所有的在domain域下的页面都可以操作该页面。
4. <b>
<b>指定黑色字体文本。
语法
<b>text</b>
text是需要使用黑体显示的文本。
例子:
<wml>
<card>
<p>
Press <b>OK</b> to go to the next screen.
</p>
</card>
</wml>
5. <big>
<big>指定大字体的文本
语法
<big>text</big>
text是所需要以大字体显示的文本。
6. <br/>
<br/>标签用来指定换行。它将使得设备在新行上显示文本的图标。
语法
<br/>
注意:不像HTML所有的WML标签需要一个结尾标志“/”,因此在WML中插入一个新行是<br/>,而不是<br>。
7. <card>
一个WML页面是由一个或多个卡片(card)组成。每个卡片都包含了一套用户和设备交互的操作。设备每次只能显示一个卡片——有些情况下会显示一系列的卡片。
语法
<wml>
<card id="name" title="label" newcontext="boolean"
ordered="true" onenterforward="url" onenterbackward="url"
ontimer="url">
content
</card>
</wml>
content代表了所有WML卡片的定义和操作的一系列内容:一个timer元素(或者没有)、一个或多个onevent元素、一个或多个do元素、pre元素等一系列的导航信息,此外一个card元素还可以包含一个或多个p元素。
重点:<card>必须遵循以下顺序:<onevent>、<timer> 、<do>。
除了以上列出的,设备将按照所指定的顺序显示元素。
card的属性包括:
- id指定card的名字。
名字是导航时候的依据,例如,可以指定<go href="#cardname"/>来导航(参考<go>)。
- title为卡片指定一个简短的标题。
各种设备对此有不同的用途。
注意: 生产厂家将会显示title,如果那儿有比较充分的屏幕空间。title属性应该看作是对用户的一种提示,而不是卡片所显示的内容。
- newcontext(Boolean类型)
取值为true或者false,默认为false。当用户重新进入的时候 指定设备是否需要初始化卡片中所有的内容。当指定newcontext="true"那么所有的内容重新初始化,并清除历史记录。
- ordered(Boolean类型)
取值为true或者false,默认为true。它指定卡片内容的组织形式。ordered="true"将使得设备按固定的顺序显示内容。否则根据用户选择的顺序来显示内容。
ordered属性可以指定设备在一个卡片中显示多个内容时候的顺序。true 将按线型方式显示(默认的值)。使用这个设置时,将只显示必须的属性。如果设备无法在一屏上显示所有的内容,那么它将分屏显示:
- 指定了field组,有一个或多个<fieldset>(参见<fieldset>)。
- 无效的fields(使用了文本前缀作为每个部分的提示)。
false允许用户在各个部分之间进行任意的导航。使用这个设置,可以不必考虑他们之间的顺序。如果设备不能将所有的部分显示在屏幕上,那么它将会出现一个可供选择的卡片,用户可以导航到每一个部分(根据自己的意愿进行选择或者输入一个选择值)。
- onenterforword(href类型)
如果用户执行<go>,那么就打开指定的URL地址。这个属性是<onevent>的一个简短格式。
- onenterbackword(href类型)
如果用户执行<prev>,那么就打开指定的URL地址。这个属性是<onevent>的一个简短格式。
- ontimer(href类型)
当timer过期的时候,就打开指定的URL。这个属性是<onevent>的一个简短格式。
例子:
<wml>
<card>
<do type="accept">
<go href="#card2"/>
</do>
<p>
Press OK to display the next screen.
</p>
</card>
<card id="card2">
<p>
This screen displays the content of Card 2.
</p>
</card>
</wml>
8. <do>
<do>将用户的交互(例如功能键、声音提示等)和一个任务联系在一起。当用户激活这些功能的时候,设备就执行和<do>相联系的任务。
重点:<do>已经扩展了功能:可以使用图标来作为label。这个功能可以通过嵌入<img>来指定。
例如:
<do type="accept">
<go href="/foo"/>
<img src="img" localsrc="OK" alt="OK"/>
</do>
如果手机支持img、localsrc、src和alt,就应该保持这种顺序。如果不支持,就由alt指定label。如果指定了<img>,那么<do>中的label就被忽略。如果没有指定<img>,那么<do>中的<label>就被使用。
语法
<do type="type" label="label" name="name" optional="boolean">
task
</do>
task代表将要执行的动作:
do元素必须绑定go、prev、noop、refresh任务中的一个任务。
do的属性包括:
- type
绑定特殊的用户交互事件
可以指定以下的type属性:
- accept激活ACCEPT(功能键,按钮等等)。
- delete激活DELETE(功能键,按钮等等)。
- help激活HELP(功能键,按钮等等)。
- options激活OPTIONS(功能键,按钮等等)。
- prev通过激活PREV导航到另外一个卡片。
- reset激活RESET(清除和重设当前的状态)。
- unknown激活未知道的机制(相当于TYPE="")。
- X-*, x-* 将来用(没有保留)。
- vnd.co-type 激活供应商的一个特定的功能。
如果type 隐含了特殊的用户交互机制。有些设备将功能映射成按键,有些则映射成上下文独立的操作。因此当设计用户交互的时候,要记住不能指定设备将要使用的特别操作机制。
注意: 如果在一个<card>中定义了多个<do>拥有同样的type,那么必须为每个<do>指定不同的name。
- label
label可以标识用户的交互事件。例如,如果将一个任务绑定在ACCEPT键上,那么设备就会将label的值显示在屏幕上,如果不指定,那么默认显示"OK"。为了保证屏幕有足够的宽度,label最多不超过5个字符。如果不支持动态的标签,设备将忽略label属性。
- name
指定<do>的名字。如果卡片级别<do>(定义在<card>中)和页面级别<do>(定义在<template>中)具有同样的名字,卡片级别将将覆盖页面级别。
- optional
取值为true或者false,缺省为false。指定设备是否忽略这个标签。
9. <em>
<em>指定强调文本。
语法
<em>text</em>
text是需要强调的文本。
10. <fieldset>
<fieldset>允许在一个card中,定义一组text或者输入。指定一个或多个<fieldset>可以控制设备如何显示卡片的内容,用来简化用户的输入。
语法
<fieldset title="label">content</fieldset>
content表示以下内容中的一个或者多个的组合:control在一个<fieldset>组中,可以指定fieldset、input、select的内容;text也可以在<fieldset> 组中指定格式化的文本。设备对这些文本的使用是大不一样的。例如:作为用户输入的提示,或者描述选项。
<fieldset>的属性:title指定<fieldset>组的标签。一些设备当显示<fieldset>组的时候将作为显示用的标签。其他的也许用作用户交互的提示。
11. <go>
<go>是一个任务标签,它将指导用户去打开一个指定的URL。如果URL是一个指定的卡片,那么设备将显示那个卡片。如果URL是一个指定的页面,那么设备就显示那个页面的第一个卡片。
语法
<go href="url" sendreferer="boolean" method="method"
accept-charset="charset"
<postfield name="data" value="value"/>
content
</go>
content代表了打开的时候用来设置变量,可以指定一个或更多的变量。
重点:不象其他的WML标签,指定content是可选的。如果不指定content,那么必须使用<go attributes/>代替<go attributes>content</go>。
<go>的属性包括:
- href
将要打开的URL;
- sendreferer
取值为true或者false,缺省为false。指定设备是否要将所发送请求的页面的URL包含在内。如果sendreferer="true" 那么设备就要发送 HTTP_REFERER 头参照请求页面的相对URL。如果将操作权限限制在可信任的设备,那么就可以指定这项为true。
- method
取值为get或者post,缺省为get。指定HTTP的提交方式。指定method="post" 将使得服务器将通过HTTP的头来传递变量。当变量值中有非ASCII字符,可以使用这种方式。如果不指定,那么默认地使用post方式。
- accept-charset
指定字符的编码方式。设备将使用这个属性来确定postfield元素传输的编码。一般来说服务器采用UTF-8作为默认的编码。
注意:accept-charset属性将覆盖HTTP头中的任何的字符编码设置。语法格式为, accept-charset="UTF-8, US-ASCII, ISO-8859-1"。
以下的例子解释了<go>的使用方法:
<wml>
<card title="Employee" ordered="true">
<do type="ACCEPT" label="Find">
<go method="post" href="?next=list"
<postfield name="next" value="list&"/>
<postfield name="L" value="$last&"/>
<postfield name="F" value="$first"/>
</go>
</do>
Partial First Name:
<input title="First Name" name="first"/>
Partial Last Name:
<input title="Last Name" name="last"/>
</card>
</wml>
12. <head>
<head>指定整个页面的头,包括metadata和access控制信息。
语法
<head>
content
</head>
content代表的是deck-level的头信息,content可以指定仅有一个access或一个或多个meta的内容。下面的例子指定页面的最大过期时间。WML通过<meta>中定义来决定缓冲控制。
<wml>
<head>
<meta http-equiv="Cache-Control" content="max-age=3600" forua="true"/>
</head>
<card>
...
...
</card>
<card>
...
...
</card>
</wml>
13. <i>
<i>指定斜体字的文本。
语法
<i>text</i>
text是需要按斜体显示的文本。
例子:
<wml>
<card>
<p>
<i>Red</i>, <i>blue</i>, and <i>yellow</i> are primary colors.
</p>
</card>
</wml>
14. <img>
<img>指导设备在格式化的文本中如何去显示一个图片。注意:不是所有的设备都可以显示图片。
注意:不能在<do>或者<option>内指定图片。也不能将图片作为一个功能键的标题或者选项。
语法
<img alt="text" src="url" localsrc="icon" align="alignment" height="n" width="n" vspace="n" hspace="n"/>
<img>包括以下属性:
- alt
指定可选的文本,假如设备无法显示执行的图片。
- src
图片的URL地址。如果指定了一个有效图标的localsrc,那么设备就会忽略这个属性。
- localsrc
已经知道的图标名字。如果设备在ROM中找不到,那么它将从服务器上寻找。如果指定了一个有效的图标,那么将忽略src属性。
- align
取值为top、middle和bottom,缺省为bottom。指定图片的垂直对齐方式。
- height
指定图片的高度。
- width
指定图片的宽度。
- vspace
- hspace
例子:
<wml>
<card>
<p>
Here's a smiley:
</p>
<br/><img alt=":-)" localsrc="smileyface" src=""/>
</card>
</wml>
注意 :一些localsrc在不同的矢量字体下有不同的显示。既然控制不了显示的大小,应该记住在不同的设备上图标的显示差别很小。
15. <input>
<input>可以让用户输入文本或者变量。
语法
text
<input name="variable" title="label" type="type"
value="value" format="specifier"
emptyok="boolean" size="n" maxlength="n" tabindex="n"/>
text代表了用来提示用户输入的文本或者图片。
input包括以下属性:
- name
变量的名字,设备将用它来保存用户输入的数值。如果变量没有数值,那么设备就将它设为默认的初始状态,也就是空字符串("")。当设备显示<input> 时,变量的数值会出现在输入栏内。
- title
指定一个简短的输入标题。有些设备将其作为一个帮助提示,当显示输入栏的时候。其他的也许将其作为一个交互时使用的标签。
- type
取值为text或者password,缺省为text。指定设备如何显示用户输入的文本。指定 type="text" 使得文本可见;指定 type="password" 使得文本不可见(例如,使用*代替原文本)。注意password方式,不是指加密方式。不能指望它带来安全保障。
- value
该属性是确定默认的数值。
- format
指定用户输入的匹配模式。如果省略这个属性,那么默认的就是*M。
下面是指定格式化掩码的标签:
- A表示任何大写的字符(不包括数字)。
- a任何大写的字符(不包括数字)。
- N任何数字(不包含字符)。
- X任何数字和大写的字符(不能变为小写)。
- x任何数字和小写的字符(不能变为大写)。
- M任何数字和大写的字符,可以大小写切换。
- m任何数字和小写的字符,可以大小写切换。
为了限制用户输入的字符个数,可以指定输入字符的限制,只需要在格式前面加上数字。例如 format="3X" 让用户最多输入3个符号、数字和大写的字符。为了不限制用户的输入,可以通过在格式前面指定“*”。例如:format="*a"可以让用户输入任意多的内容。
- emptyok
取值为true或者false,默认为false。指定用户是否可以空着离开哪个项。指定 emptyok="true" 表明那个项目是可选的。
- size
- maxlength
指定输入框的最大输入长度。默认的是256。
- tabindex
例子:
<wml>
<card>
<p>
First Name:
<input name="fname" maxlength="15" /> <br/>
Last Name:
<input name="lname" maxlength="15" /> <br/>
State:
<input name="state" maxlength="2" emptyok="true" value="CA" /> <br/>
Zipcode:
<input name="zipcode" maxlength="9" /> <br/>
Password:
<input name="password" maxlength="8" type="password" />
</p>
</card>
</wml>
16. <meta>
<meta>元素为WML页面提供各种信息。这个元素是在页面的头部指定有关页面操作控制的信息。
注意:不是所有的设备都支持附加信息。
语法
<head>
<meta http-equiv="Cache-Control" content="max-age=time"
forua= true />
...
</head>
meta的属性包括:
- name
必须指定name的属性:name="name" http-equiv="name"
- content
指定一个和property相关的数据值。
- scheme
- forua
取值为true或者false,默认为true。指定信息是否要发往用户代理。如果为“false”,那么相关的meta信息必须清除然后再发往客户代理。如果为“true”,那么相关的meta信息就直接分发给客户代理。
17. <noop>
<noop>是一个任务元素。它指导设备不做任何事情。这个元素在覆盖页面级别时十分有用。
语法
<noop/>
18. <onevent>
<onevent>和状态转移与内建事件相关。当内建的事件发生,设备将指定一个与<onevent>相关的任务。
语法
<onevent type="type">task</onevent>
这里task代表当内部事件发生的时候要执行的动作,可以指定go、prev、refresh、noop中的任何一个元素。
type属性标识内建事件,激活指定的任务。如果一个卡片级别的事件和一个页面级别的时间具有同样的类型,那么卡片级别的绑定将覆盖页面级别的绑定。
可以指定以下的类型值:
- onpick 用户选择或者放弃选择一个选项。
- onenterforward 用户执行<go>任务。
- onenterbackward 用户执行<prev>任务,或者激活PREV机制。
- ontimer 一个指定的<timer>过期。
19. <optgroup>
<optgroup>允许在一个卡片中组织多个<option>(或者嵌套的<optgroup>)。创建选择组可以指定设备如何显示一个卡片的内容。
语法
<optgroup title="label">content</optgroup>
这里content代表一个或多个以下的内容,可以指定以下的元素:
- <optgroup> (嵌套的<optgroup>)
- <option> 设备将按顺序显示所指定的内容。
title属性指定一个简单的标签。有些设备要将这个标签做为标题来使用。有些设备可能作为导航来使用。
20. <option>
<option>在<select>中指定一个特殊的选择项目。
重点:<option>元素已经扩展了功能,允许在<option>文本中加入图片。
例如:
<option value="1">
<img src="/img1" alt="Choice 1"/>
</option>
语法
<option title="label" value="value" onpick="url">
content
</option>
这里content代表设备将要显示的文本内容以及当用户选中之后所要执行的动作,event可以指定onevent元素, text显示代表选择的文本。
<option>的属性包括:
- title
标识选择项的标记。为了保证和大多数的设备兼容,label应该最大不要超过5个字符。
- value
指定将要赋给<select>中指定变量的值。如果指定了一个参考变量,那么设备将先测试变量有效性,然后再设置变量。
- onpick
指定在用户选择或者放弃选择(如果使用了多选)的时候,将要打开的URL地址。这个是一个<onevent>的缩写。
例子:
<wml>
<card>
<p>
Please select your favorite color:
<select name="color">
<option value="1">red</option>
<option value="2">blue</option>
<option value="3">green</option>
<option value="4">yellow</option>
</select>
</p>
</card>
</wml>
21. <p>
指定一个具有特定对齐方式和换行方式的新段落。
语法
<p align="alignment" mode="wrapmode">
content
</p>
<p>的属性包括:
- align
取值为left、right或者center。指定显示行的对齐方式。如果没有,那么将采用左对齐方式。
- mode
取值为wrap或者nowrap,缺省为wrap。指定文本的换行方式。如果指定为nowrap,设备将使用另外的机制来显示过长的行,例如:水平滚动。设备将会使用指定的换行模式直到下一个新的指定。换句话来说:如果指定了模式属性,那么设备将应用这种模式。如果没有指定模式,那么设备将使用最后一次所指定的模式。如果以前没有指定过,那么默认采用wrap模式。
22. <postfield>
<postfield>定义了一个将要传送给HTTP 服务器的名字数值对。
语法
<postfield name="name" value="value"/>
<postfield>的属性包括:
- name
表明域的名字标签。
- value
指定的数值
23. <prev>
<prev/>是一个任务元素。它指导设备从当前的堆栈中移走URL,并打开前一个URL。如果堆栈中没有内容,那么<prev>将没有任何效果。
语法
<prev>content</prev>
这里content代表在打开前一个URL时,所需要设置的变量值。可以在其中指定一个或多个变量:<setvar>。
注意:不像其他的WML元素,<prev>的内容是可选的。如果没有指定任何内容,那么就必须使用<prev/>。
24. <refresh>
<refresh>元素是一个任务元素。它指导设备刷新卡片中的变量。设备当然也将更新屏幕上的变量。
语法
<refresh>content</refresh>
这里content代表需要刷新的元素变量,必须指定至少一个变量:<setvar>。
注意:可以使用<refresh>标签来设置变量的值,但是不可能将它们设置为NULL。
例子:
<wml>
<card title="Employee" ordered="true">
<do type="ACCEPT" label="Find">
<go method="post" url="?next=list">
<postfield name="NEXT" value="list&"/>
<postfield name="L" value="$last&"/>
<postfield name="F" value="$first&"/>
</go>
</do>
<do type="OPTIONS" label="Clear">
<refresh>
<setvar name="first" value=""/>
<setvar name="last" value=""/>
</refresh>
</do>
Partial First Name:
<input title="First Name" name="first"/>
Partial Last Name:
<input title="Last Name" key="last"/>
</card>
</wml>
25. <select>
<select>元素指定用户选择项列表。可以指定单选或者多选。
语法
text
<select title="label" multiple="boolean" name="variable"
default="default" iname="index_var" ivalue="default"
tabindex="n">
content
</select>
这里text代表用来提醒用户输入的文本或者图像。content代表可供选择的列表。可以使用<optgroup>或<option>来定义content。
26. <setvar>
当设备执行<go>、<prev>或者<refresh>任务时,<setvar>指定变量的值。
语法
<setvar name="name" value="value"/>
setvar的属性:
- name
需要设置的变量名。如果找不到这个变量,设备将忽略这个<setvar>。
- value
指定变量的值
27. <small>
指定小尺寸的矢量字体的文本。
语法
<small>text</small>
这里text表示需要显示的小字体内容。
28. <strong>
指定所需要特别强调的文本。
语法
<strong>text</strong>
这里text代表需要特别强调的文本。
29. <table>
<table>允许指定一个行格式化的输出,可以控制整个表格的对齐方式,但不是每个单元格的对齐方式。WML表格和HTML表格很像,但是只有少量的功能。在定义表格的时候,必须声明行数,以及后面的内容。这些内容可以是空行或者列。
语法
<table title="name" align="left|right|center" columns="number of columns">
...row and data declarations
</table>
table的属性包括:
- align
取值为left、right或center,默认为left。指定文本的对齐方式。如果没有指定,那么默认将采用左对齐方式。
- title
指定表格的标签。
- columns
指定每行的列数。指定为0是不允许的。
30. <td>
<td>元素是一个用来装入格子内容的容器。表单的格子可以为空。用户代理必须处理由于使用图像或者链接所带来的多行数据单元格。
语法
<td>content</td>
这里content代表了在表单格中的文本,或者是<img>和<anchor>元素。可以指定<img>、<anchor>任何一种元素。
31. <tr>
<tr>是一个用来装入表单行的容器。这个表单行可以为空,换句话说,所有的格子都是空的。
语法
<tr>
<td>content</td>
</tr>
这里content代表表单格子中的内容,可以是文本,或者是<img>和<anchor>。
32. <template>
一个WML页面可能包含一个<template>元素来定义页面级别的事件捆绑。这些事件特点将对页面内的所有卡片起作用,可以通过指定卡片的同名事件捆绑来覆盖某个事件捆绑。
语法
<wml>
<template onenterforward="url" onenterbackward="url"
ontimer="url">
content
</template>
</wml>
这里content代表了当事件发生时的一般动作,可以指定<do> 、<onevent>的任何一种元素来定义。
template元素包括以下属性:
- onenterforward
如果用户通过<go>任务来浏览一个卡片,那么打开指定的URL。这个属性是<onevent>的一个缩写。
- onenterbackward
如果用户通过<prev>任务来浏览一个卡片,那么打开指定的URL。这个属性是<onevent>的一个缩写。
- ontimer
如果用户通过<timer>过期,那么打开指定的URL。这个属性是<onevent>的一个缩写。
33. <timer>
<timer>提供了在一段时间的交互之后,自动激发任务的功能。任何一种用户的动作都将激活定时器,执行任何任务都将停止定时器。只能在一个卡片中定义一个定时器。
语法
<timer name="variable" value="value"/>
<timer>的属性包括:
- name
name变量用来保存定时器的值。如果变量没有指定初始值,设备将自动使用默认的指定值。如果用户退出卡片,那么这个变量将被设置为当前时间。如果在定时器过期以后,设备将这个变量设置为0。
- value
指定变量的关键属性。必须以1/10秒为单位指定<timer>的值,例如,100等于10秒。将值设置为0将停止timer。如果name在定时器之前已经有了一个值,那么设备将忽略默认的属性。如果变量名还没有值,那么设备将使用指定的数值设置该值。
以下的例子解释了怎么初始化和重新使用一个计数器。当用户访问该卡片的时候,设备都将重新设置定时器的数值。如果定时器没有数值,设备将设置定时器为5秒。当定时器过期以后,设备将自动设置时间。
<wml>
<card ontimer="#card2">
<timer name="time" value="50"/>
<p>
Hello, Unwired World!
</p>
</card>
<card id="card2">
...
...
</card>
</wml>
34. <u>
<u>指定带下划线的文本。
语法
<u>text</u>
这里text是将要显示下划线的内容。
35. <wml>
<wml>指定一个WML页面。
语法
<wml xml:lang="lang">
<card>
content
</card>
</wml>
这里content代表定义页面动作的WML元素。
wml的属性“Xml:lang”指定WML文档的语言。所指定的语言属性将覆盖其他任何语言指定语句的功能。
例如:
<wml xml:lang="en-us">
<card>
...
...
</card>
六、WML速查
其中包括了所有的WML标签的语法速查
表3-7中包括了所有的WML标签的语法速查。
表 3-7 WML速查
标记 |
语法 |
<wml> |
<wml xml:lang="lang" > |
<card> |
<card id="name" |
<template> |
<template onenterforward="url" |
<head> |
<head> |
<access> |
<access domain="domain" |
<meta> |
<meta name="name"|http-equiv="name" |
<timer> |
<timer name="variable" |
<setvar> |
<setvar name="name" |
<anchor> |
|
<a> |
<a title="label" > |
<do> |
<do type="type" |
<onevent> |
<onevent type="type" > |
<go> |
<go href="url" |
<prev> |
<prev> |
<noop> |
<noop/> |
<refresh> |
<refresh> |
<img> |
<img alt="text" |
<input> |
<input name="variable" |
<select> |
<select title="label" |
<option> |
<option title="label" |
<optgroup> |
<optgroup title="label" > |
<fieldset> |
<fieldset title="label"> |
<b> |
<b> |
<big> |
<big> |
<br> |
<br/> |
<em> |
<em> |
<i> |
<i> |
<p> |
<p align="alignment" |
<small> |
<small> |
<strong> |
<strong> |
<table> |
<table align="alignment" |
<td> |
<td>content</td> |
<tr> |
<tr> |
<u> |
<u> |
七、字符实体
其中包括了WML中字符实体与其对应字符。
表3-8中包括了WML中字符实体与其对应字符。
表 3-8 字符实体
字符实体 |
字符 |
< |
< |
> |
> |
' |
‘ |
" |
“ |
& |
& |
|
空格 |
­ |
- |
八、WMLScript
WMLScript语言也是WAP应用层的组成部分之一。这种语言是基于ECMAScript语言的,但是它更适合于窄道通信。在应用时,WMLScript可以和WML文档一起,问客户端增加动态功能,此外WMLScript也可以作为一种独立的工具使用。
WMLScript是一种程序语言,它可以调用在本地安装的标准库函数。为了在传输时节省带宽,WMLScript程序先被编译成字节码(bytecode),传到客户端后,再通过解释器执行。这也是WMLScript和ECMAScript的重要区别之一。
基本原则
总的来说,由于WMLScript是以C语言为蓝本制定的,因此其语法特征和C语言很相象。在学习的过程当中,可以参考C语言。
1. 大小写敏感
WMLScript 1.1是一个大小写敏感的语言。所有的关键字、变量和函数名都必须合理地使用大小写。
2. 空格与换行
WMLScript 1.1忽略所有程序间的空格、制表符、换行,字符串常量里面的空格、制表符、换行不被忽略。例如WMLScript能够识别以下几种字符串:
- "June 29, 1908"
- "June29,1908"
- "6/29/08"
3. 注释
WMLScript 1.1有两种注释结构:
- 行注释:从使用“//”开始到这行结束都算做注释。
- 块注释:以“/*”开始到“*/”结束。
编译器不支持注释嵌套。
4. 直接编码
有一些数值将直接编码并嵌入在程序之中。直接编码的内容如下:
· 整数
按以下方式使用数字,就使用直接编码:
- 十进制
十进制的数字是不以0开头,只包含0~9的字符串。
例如:-41。
- 十六进制
十六进制是以0X或者0x开头,只包含0~9、a-f或者A-F的字符串。
例如:0xF3
- 八进制
八进制是以0开头,只包含0-7的字符串。
例如:032
· 浮点数
定义成含有小数点的数字。浮点数可以包含小数和指数部分。
例如浮点数3.14可以表示成以下WMLScript 1.1编译器能够识别的几种形式:
- 3.14
- 3.14e0
- 3.14E0
- .314E1
- 314e-2
下面的形式都表示一个浮点数:
- 十进制整数
例如:3
- 十进制浮点数
例如:.14
- 分数
例如:1/2
- 指数
例如:e0
一个浮点数必须至少有一个数,是十进制的小数点或者指数。
指数是以e或E开头,后面跟着一个整数。指数是以10为底的幂。例如:e0是10的零次幂,e-2等于0.01。指数可以带符号(+或者-,代表是正指数还是负指数)。
一个超出定义范围内的浮点数将导致编译错误。一个下溢出将导致这个浮点数为0。
o 字符串
定义为在成对的双引号("")或者成对的单引号('')之间的内容。
下面都是字符类型:
- 'Goldwater Wins Nomination!'
- "Tuesday, June 29, 1999"
- "15% off retail"
字符串是一个指向字符串所在位置的内存指针。在运行的时候可以修改字符串的值。WMLScript 1.1只允许成对的双引号或单引号。这意味着当使用一个单引号和一个双引号的时候将出现编译错误。
有一些字符不能在字符串中直接体现出来。WMLScript 1.1支持特殊的转义来支持这些字符。全部的转义字符请见表3-9。
表 3-9 转义字符
所代表的字符 |
符号 |
转义序列 |
单引号 |
` |
"' |
双引号 |
" |
"" |
反斜杠 |
" |
"" |
斜杠 |
/ |
"/ |
后退一格 |
|
"b |
送纸 |
|
"f |
换行 |
|
"n |
回车 |
|
"r |
水平制表符 |
|
"t |
使用十六进制引用字符(Latin-1 ISO8859-1) |
|
"xhh |
使用八进制引用字符(Latin-1 ISO8859-1) |
|
"ooo |
显示Unicode字符 |
|
"uhhhh |
o 布尔型
定义为只有true和false两个值的数。
o 无效(空)
一个表示无效值的量(像C语言中的NULL)。
5. 保留字
保留字在WMLScript 1.1中表示了特殊的意义,因此不能另外定义。在WMLScript 1.1中,保留字如下:
access |
agent |
http |
if |
break |
continue |
isvalid |
meta |
div |
div= |
name |
path |
domain |
else |
return |
typeof |
equiv |
extern |
url |
use |
For |
function |
user |
var |
header |
while |
|
|
有一些保留字已经预先为将来的WMLScript版本保留:
case |
finally |
import |
public |
catch |
private |
switch |
struct |
class |
sizeof |
try |
throw |
const |
super |
do |
export |
debugger |
default |
enum |
extends |
WMLScript没有使用的保留字:
delete |
null |
in |
this |
lib |
void |
new |
With |
变量与数据类型
本节介绍WMLScript 中的两个重要概念:变量和数据类型。
1. 变量
变量是在脚本程序中具有值的符号名。使用变量来存储和改变程序的数据。
注意:WMLScript 1.1仅仅支持函数内定义的变量或者是用来传送数值的参量。
- 声明
就是指定变量的名字。
例如:
var x;
var x,y;
var size=3;
使用var关键字来定义一个变量。如果想在一条语句中声明多个变量,那么这些变量之间使用逗号“,”分开,定义使用分号“;”结束。
WMLScript 1.1要求在使用变量之前定义变量。如果不是十分需要,没必要去初始化每一个声明的变量。如果不做初始化,它将自动初始化成为空字符串("")。
- 作用域与生命期
一个变量的作用域是指在程序中能够引用这个变量的一段代码。变量的生命期是指从变量声明开始到失效为止。生命期也被称为持久性。
- 使用
一个变量只能在其所定义的函数内使用。
例如:
var myAge=25;
var yourAge=25;
var ourAge=myAge+yourAge;
可以通过调用变量的名字来使用变量。在上面的例子中,变量ourAge对变量myAge和变量yourAge实行了求和的操作。
2. 数据类型
数据类型是确定变量该是哪种类型的变量。
例如:
var flag=true;
var number=12;
var temperature=27.7;
var number="XII";
var except=invalid;
WMLScript 1.1只支持内部定义的数据。没必要去指定变量的类型,变量在任何时候可以是以上五种数据类型中的一种。当需要同其他内部定义的数据相区别的时候,可以使用第五种数据类型。
- 整数范围
指WMLScript 1.1所支持的整数范围。
支持的范围是从-2147483648到2147483647。可以在运行期使用Lang库函数来取得这些值。
Lang.maxInt()返回所能支持的最大整数值。
Lang.minInt()返回所能支持的最小整数值。
- 浮点数范围
指以浮点数的精度所能表示的最小和最大数值。
最大数值:3.40282347E+38。
最小的非零的数值(按照正常的精度):1.17549435E-38或更小。
可以使用的Float库函数在运行期取得这些数值:
Float.maxFloat()返回所能支持的最大浮点数值。
Float.minFloat()返回所能支持的最小浮点数值。
如果操作结果是一个不能被单精度浮点数所能表示的数值,那么结果将是invalid。如果操作结果发生下溢出,那么结果将是0.0。负零和正零是完全相等的。
- 字符串
由字母、数字或特殊字符组成。
可以使用字符串来初始化字符串变量。可以使用WMLScript 1.1中定义的关于字符串的操作或String库中的函数来控制字符串。
例如:
var msg="Hello"
var len=String.length(msg)
var msg=msg+"World !"
- 布尔型
可以使用布尔类型去初始化或指定变量的数值。或者使用一个需要布尔值做为参数的语句。布尔值可以是数值或者是逻辑运算的结果。
例如:
var truth=true;
var lie=!truth;
预编译头
预编译就是在编译阶段控制编译器的行为。预编译头一般在文件开头和函数声明之前指定。所有的预编译头都是以“use”加上指定的预编译属性。
1. 外部文件
可以使用URL(Uniform Resource Locator)去调用一个WMLScript 1.1的文件。使用 “use url”标签去调用一个在外部文件里的函数。
例如:
use url OtherScript "http://www.host.com/app/script";
为了调用一个外部文件,必须按下面的方式指定:
- WMLScript 1.1 资源所在的URL(http://www.host.com/app/script)
- 资源的名字(OtherScript)
然后才可以在函数的声明内使用该资源。
例如:
function test (par1, par2)
{
return OtherScript#check (par1-par2);
};
调用的过程如下:
- 找到WMLScript 1.1文件的URL。
- 函数从指定的URL位置装载文件。
- 检测文件的内容,并执行check函数。
“use url”预编译头有自己局部命名空间。局部名字在整个文件中必须是唯一的。WMLScritp 1.1支持绝对URL和不带井号“#”和标识片段的相对URL。想了解更多的内容请查看http://info.internet.isi.edu/in-notes/rfc/files/rfc2396.txt。
对于相对URL,URL的起始位置是当前文件所在的位置。
被指定的URL中的内容要根据转义要求转义。在编译的时候编译器不会自动转义、检查URL的格式和校验其有效性。
2. 控制权限
可以使用权限控制预编译头来保护文件的内容。必须在调用外部函数之前使用权限控制预编译头。当然多于一个以上的权限控制预编译头将导致编译错误。
每当外部函数被调用的时候,编译器就会检查外部文件的控制权限,以决定调用者是否有该文件的使用权。权限控制预编译头通过指定domain和path属性来决定将要进行什么样的检查工作。如果文件有domain 或者path属性,那么文件所在的URL就必须和属性中的值一致。比较是按下面的步骤进行的:
- 操作域与URL中的域后缀相匹配。
- 操作路径和URL中的路径前缀相匹配。
域和路径都依据URL大写规则。
域后缀匹配是所有的子域从后向前都必须一致。
例如:
www.wapforum.org和wapforum.org相匹配,而不是forum.org。
路径前缀匹配指从前向后都必须一致。
例如:
/X/Y匹配/X,而不是/XZ。
默认的domain属性为当前的文件域,也就是“/”。
为了使开发简单化,有时候不需要知道文件的绝对路径,而使用相对的URL。用户代理就将相对路径转换成为绝对路径,然后根据路径属性进行匹配。
例如如果权限控制的属性为:
use access domain "wapforum.org" path "/finance";
可以使用以下的路径来调用指定文件中的外部函数:
http://wapforum.org/finance/money.cgi
https://www.wapforum.org/finance/markets.cgi
http://www.wapforum.org/finance/demos/packages.cgi?x+123&y+456
而以下的路径是被禁止的:
http://www.test.net/finance
http://www.wapforum.org/internal/foo.wml
控制权限检查的默认值是不进行检查(disabled)。
meta能够指定文件的属性名(property name)和属性值(content)。meta同样能指定文件的配置(scheme)。也许是一个表单或者是一个结构用来进行文件的内部解释。属性值都是字符串类型。
meta从不定义任何属性值,也不知道用户如何解释meta。用户代理也不会理会meta中的内容。
meta可以有以下属性:
- name
name指定供服务器使用的meta信息。
例如:
use meta name "Created" "18-June-1999";
用户代理应当忽略这些属性。而服务器应该不能将这些信息透露给用户代理。
- http equiv
指定Meta信息应当被解释为HTTP的头。
例如:
use meta http equiv "Keywords" "Script, Language";
按照这样命名的数据将按照无线对话层协议(Wireless Session Protocol)来解释或者将在达到用户代理之前进行解释。
- user agent
定义用户代理使用的数据。
例如:
use meta user agent "Type" "Test";
这些数据必须立即发送给用户代理,并马上清除掉。
操作符与表达式
本节介绍WMLScript 支持的操作符,以及如何用这些操作符构造完整的表达式。
1. 赋值操作符
指定一个变量的数值。
例如:
var a="abc";
var b=a;
var b="def"; //value of a is "abc"
赋值运算符不需要指定使用对象,也不会改变赋值操作符右边变量的数值。最简单的赋值运算符就是等号“=”;其他赋值运算符见表3-10。
表 3-10 赋值运算符
操作符 |
操作 |
= |
赋值 |
+= |
加上一个数或字符串,在赋值给右边 |
-= |
求差并赋值 |
*= |
求积并赋值 |
/= |
求商并赋值 |
Div= |
整除并赋值 |
%= |
求余数并赋值 |
<<= |
带符号左位移并赋值 |
>>= |
右位移并赋值 |
>>>= |
补零右位移并赋值 |
&= |
位与并赋值 |
^= |
位异或并赋值 |
|= |
位或并赋值 |
2. 数学运算符
一些基础的数学运算符。
例如:
var y=1/3; //y=0.3333……
var x=y*3+(++b);
WMLScript 1.1 以下所有的基础数学运算符如表3-11所示。
表 3-11 基础数学运算符
运算符 |
操作 |
+ |
数字相加,字符串相连 |
- |
相减 |
* |
相乘 |
/ |
相除 |
div |
整除 |
WMLScript 1.1所能支持的复杂运算符如表3-12所示。
表 3-12 复杂数学运算符
运算符 |
操作 |
% |
求余数 |
<< |
按位左移 |
>> |
带符号右位移 |
>>> |
补零右位移 |
& |
位与运算 |
| |
位或运算 |
^ |
位异或运算 |
WMLScript 1.1的基本一元运算符如表3-13所示。
表 3-13 一元运算符
运算符 |
操作 |
+ |
加 |
- |
减 |
-- |
前缀或后缀的自减 |
++ |
前缀或后缀的自加 |
~ |
按位求反 |
运算过程当中,将按照表3-14进行以下隐含的转换。
表 3-14 转换规则
操作类型 |
转换规则 |
例子 |
布尔型 |
如果操作数是布尔型或者能够被转换为布尔型,那么将进行布尔运算并返回值 |
true && 3.4 => boolean |
返回invalid |
!invalid => invalid |
|
整数 |
如果操作数是整型或者能够被转换为整型,那么进行整数运算并返回整数值 |
"7" << 2 => integer |
返回invalid |
7.2 >> 3 => invalid |
|
浮点数 |
如果操作数是浮点数或者能被转换为浮点数,那么将进行浮点运算并返回浮点值 |
|
返回invalid |
||
字符串 |
如果操作数是字符串类型或者能够被转换为字符串类型,那么进行字符串运算并返回字符串 |
|
返回invalid |
||
整数或浮点(一元) |
如果操作数可以被转换成整数值,那么进行整数转换并返回整数值 |
+10 => integer |
如果操作数是浮点数或者能被转换为浮点数,那么将进行浮点运算并返回浮点值 |
-10.3 => float |
|
返回invalid |
-"ABC" => invalid |
|
整数或浮点 |
如果有一个操作数是浮点数,就将另外一个数转换为浮点数,进行浮点运算并返回浮点值 |
100/10.3 => float |
如果操作数是整数或者能够被转换为整数,那么进行整数运算并返回整数 |
33*44 => integer |
|
如果操作数能被转换为浮点数,那么将进行浮点运算并返回浮点值 |
||
返回invalid |
3.2*"A" => invalid |
|
整数、浮点或字符串 |
如果操作数是整数或者能够被转换为整数,那么进行整数运算并返回整数 |
12+3 => integer |
如果有一个操作数是浮点数,就将另外的操作数转换为浮点数,进行浮点运算并返回浮点值 |
32.4+65 => float |
|
如果有一个操作数是字符串,就将另外的操作数转换为字符串,进行字符串运算并返回字符串 |
"12"+5.4 => string |
|
返回Invalid |
"A"+invalid => invalid |
|
任何类型 |
任何类型都接受 |
a = 37.3 => float |
3. 逻辑运算符
逻辑操作或和逻辑相关的运算。
基础的逻辑运算如表3-15.
表 3-15 比较操作符
操作符 |
操作 |
&& |
逻辑与 |
|| |
逻辑或 |
! |
逻辑反(一元) |
逻辑与只计算第一个操作数的值,结果为false或者invalid,那么整个结果就是false或者invalid。并且不计算第二个操作数的值。如果第一个操作数的值为true,那么整个结果就取决于第二个操作数的值。
类似的,逻辑或也只计算第一个操作数的值,如果结果为true或者invalid,那么整个结果就是true或者invalid,并且不计算第二个操作数。如果第一个操作数为false,那么整个结果就取决于第二个操作数的值。
例如:
weAgree = (iAmRight && youAreRight) || (!iAmRight && !youAreRight);
WMLScript 1.1只能使用布尔值来进行逻辑运算,因此就需要将其他类型自动转换为布尔型。
注意:如果与、或操作符的第一个操作数是invalid,那么将不计算第二个操作数的值。并且整个结果就是invalid。
例如:
var a = (1/0)|| foo (); // result: invalid, no call to foo ()
var b = true || (1/0); // true
var c = false || (1/0); // invalid
4. 字符串运算符
和字符和字符串相关的运算。
例如:
var str = "Beginning" + "End";
var chr = String.charAt (str,10) // chr = "E"
“+”和“+=”运算符用来连接字符串。其他有关字符串的操作全部在String库中。
5. 比较运算符
比较两个变量的值,也常被称为关系运算符。
例如:
var res = (myAmount > yourAmount);
var val = (( 1/0) == invalid); // val = invalid
WMLScript 1.1支持表3-16中的比较操作符。
表 3-16 比较操作符
操作符 |
操作 |
< |
小于 |
<= |
不大于 |
== |
相等 |
>= |
不小于 |
> |
大于 |
!= |
不等于 |
比较运算的规则如下:
- Boolean:true比false大。
- Integer:按照整数规则比较。
- Floating-point:按浮点数规则比较。
- String:按顺序比较字符串中的字符(字符的数值是在WMLScript 1.1中定义的)。
- Invalid:如果只要有一个操作数是invalid,那么整个比较就是invalid。
在比较的过程中,将隐含地发生数据类型转换。请参见表3-14。
6. 数组运算符
String库内的函数将字符串看作为一个数组。并按照模仿数组的行为对其进行操作。
例如:
function dummy()
{
var str = "Mary had a little lamb";
var word = String.elementAt (str,4,"");
};
WMLScript 1.1不支持普通的数组。但是String库支持对字符串的类数组操作。
一个字符串可以包含程序员所指定的多个分隔符。String库中有创建和管理字符和字符串的函数。
7. 逗号运算符
将多个表达式连接在一起。
例如:
for (a=1, b=100; a < 10; a++,b++)
{
//... do something ...
};
逗号运算符的结果是第二个操作数的结果。
在为声明的变量赋值的逗号,不是逗号运算符。一般来说逗号运算符都要使用括号保护起来。
例如:
var a = 2;
var b = 3, c = 3;
myFunction("Name", 3*(b* a, c)); // Two parameters: "Name", 9
8. 条件运算符
根据布尔运算的结果给一个变量赋值。
例如:
myResult = flag ? "Off" : "On (value=" + level + ")";
条件运算符其实是个if-then语句,它们的组织方式如下:
d = operand1 ? operand2 : operand3
operand1 是计算出的条件。如果条件是true,表达式的值就是operand2。如果条件是false或者invalid,那么结果就是operand3。
9. typeof运算符
通过返回整数来表示给定的表达式的类型。
例如:
var str = "123";
var mytype = typeof str; // myType = 2
WMLScript 1.1内部所支持的基本数据类型如表3-17:
表 3-17 typeof返回值
类型 |
返回值 |
整数 |
0 |
浮点数 |
1 |
字符串 |
2 |
布尔型 |
3 |
无效 |
4 |
typeof操作符不会自动将结果转换为其他的类别。
10. isvalid运算符
检测给定表达式的有效性。
例如:
var str = "123";
var ok = isvalid str; // true
var tst = isvalid (1/0); // false
如果表达式是有效的,那么返回值就是true,否则就是false。isvalid操作符不会将返回结果自动转换为其他类型。
11. 表达式
由操作符、常量、数值函数或变量组成。
以下的例子是一个常量或者是变量:
- 567
- 66.77
- "This is too simple"
- 'This works too'
- true
- myAccount
复杂的表达式可以使用简单的表达式、操作符和函数调用组成。
- myAccount + 3
- (a + b) / 3
- initialValue + nextValue(myValues);
WMLScript 1.1支持大多数其他编程语言都支持的表达式。
函数
一个WMLScript 函数作为一个WMLScript 编译单元(编译单元通常是一个WMLScript文件)的一部分,通过名字来标识,可以被其他函数调用而进行一系列的操作,并返回一个值。下面如何声明并调用函数。
1. 函数声明
WMLScript 1.1中函数声明是指声明函数的调用参数和函数体。所有的函数都有以下特点:
- 函数声明不能嵌套。
- 函数名字在同一个文件里必须唯一。
- 函数的调用都是通过传参数值来实现。
- 调用函数的时候,参数个数和类型必须和函数声明保持一致。
- 函数的参数就好像是函数体内的局部变量,在函数调用的时候被初始化。
- 函数始终有返回值,默认是空字符串("")。return语句可以来指定函数的返回值。
- 可以使用extern关键字来声明一个外部函数。
function currencyConverter(currency, exchangeRate)
{
return currency*exchangeRate;
};
extern function testIt()
{
var USD = 10;
var FIM = currencyConverter (USD, 5.3);
};
2. 函数调用
函数调用将返回一个值,例如一个计算的结果。函数如何调用决定于函数是在哪儿声明的。
- 内部函数
声明函数和调用函数在同一个文件中,就称为内部调用。
例如:
function test2 (param)
{
return test1 (param+1);
};
function test1 (val)
{
return val*val;
};
内部调用是很简单的。只要使用函数名,给出参数使用分号结尾就可以啦!当然,参数的数目和类型必须和函数的声明相符合。
一个本地函数可以在其声明之前被调用。
- 外部函数
一个在外部文件声明的函数的调用。
例如:
use url OtherScript "http://www.host.com/script";
function test3(param)
{
return OtherScript#test2(param+1);
};
调用外部函数必须在前面加上外部文件的名字。
必须使用“use url”来指定外部文件。预编译头将外部文件映射为一个可以在内部使用的标识。然后使用这个标识加上井号“#”和标准的函数调用来实现外部调用。
- 库函数
指的是WMLScript 1.1标准的库函数调用。
例如:
function test4(param)
{
return Float.sqrt(Lang.abs(param)+1);
};
调用标准函数可以通过函数库的名字加上点号“.”和库函数的标准调用来实现。
语句
WMLScript 语句是由关键字和表达式按照一定的语法格式构成的。在书写程序时,一条语句可以占用多行,一行中也可以包含多个语句。
1. 空语句
空语句只包含一个分号,例如:
;//This is a empty statement
空语句常用于程序中某处语法上需要一条语句,但实际上又没有操作可执行的情况下。
例如:
while (!poll(device)); // Wait until poll() is true
2. 表达式语句
表达式语句用于指定参数的值,计算数学表达式,调用函数等等。即在一个表达式后面加上“;”号就形成一个表达式语句。
例如:
str = "Hey" + yourName;
val3 = prevVal + 4;
counter++;
myValue1 = counter, myValue 2 = val13;
alert("Watch out!");
retVal = 16*Lang.max(val3, counter);
3. 块语句
块语句以“{”开始,并以“}”结束,其间封装一个语句序列,或者被称为复合语句。
例如:
{
var i = 0;
var x = Lang.abs(b);
popUp("Remember!");
}
块定义可以在任何只需要一条语句的地方使用。
4. 变量语句
变量语句用来声明一个变量并对变量进行初始化(若没有初始化,变量值缺省为空字符串)。变量语句的一般格式为:
var 变量名[=初始值][,变量名[…]];
例如:
function count(str)
{
var result = 0; // Initialized once
while(str != "")
{
var ind = 0; // Initialized every time
// modify string
};
return result
};
function example(param)
{
var a = 0;
if (param > a)
{
var b = a+1; // Variables a and b can be used
}
else
{
var c = a+2; // Variables a, b, and c can be used
};
return a: // Variables a, b, and c are accessible
};
合法的变量名必须是唯一的。它的作用域是当前的文件,表达式在每次调用的时候都重新计算。
5. if语句
一条或者两条根据条件的布尔值来判断其是否执行的语句。
if语句通常包括一个条件表达式,还要有一个或两个语句。If语句有两种形式,一种形式为:
if(表达式) 语句
表达式的值是布尔值或invalid值。
另外一种形式为:
if(表达式)
语句
else
语句
在if语句中,如果第一个条件为true将执行第一条语句。如果为false或者invalid,那么就执行第二条语句。所执行的语句可以是WMLScript 1.1所规定的任何语句,包括其他嵌套的if语句。
例如:
if (sunShines)
{
myDay = "Good"
goodDays++;
} else
myDay = "Oh well...";
6. while语句
通过while语句,可以在给定条件成立的情况下,重复执行某个语句(可以是块语句)。
while语句的格式为:
while(表达式)语句
表达式的值是布尔值或invalid值,如果是其他类型,可以通过类型转换为布尔型。执行时先计算表达式的值,如果值为true,则重复执行语句;表达式的值为false或invalid,则不执行语句,跳出循环,执行while语句后面的语句。每一次重复,都要重新计算表达式的值,当循环条件为真的时候将反复地计算表达式的值。
例如:
var counter = 0;
var sum = 0;
while (counter < 5)
{
counter++;
sum += c;
};
只要循环条件为真,循环将一直执行下去。
7. for语句
for也是一种循环语句。它的一般形式为:
for(表达式1;表达式2;表达式3)
语句
或者是另外一种形式:
for(var变量声明列表;表达式2;表达式3)
语句
for语句有三个可选的部分组成。每个部分使用分号分开,并且都包含在一个括号中,后面紧接所需要执行的循环语句。
典型的,第一个表达式(var index = 0 如下例)是用来初始化变量的数值。在表达式中可以使用关键字var来声明和初始化一个变量。变量的作用域将从声明的地方开始直到函数结束。
第二个表达式可以是任何的WMLScript 1.1布尔表达式。每次开始循环之前都会计算表达式的值。如果结果为true,那么就执行循环。这个表达式是可选的。如果被省略,那么条件值永远是true。
第三个表达式是用来更新或者增加记数器变量的。只要循环条件为真,这条语句就被执行。
例如:
for (var index = 0; index < 100; index++)
{
count += index;
myFunc(count);
};
8. break语句
中断当前的循环,程序将从中断的地方开始继续执行。break语句只能用在while或for语句中,即用在它们的循环体中。当循环体中遇到break语句时,循环立即终止,程序跳过break语句后的其余语句,从循环语句后的第一条语句继续执行。
例如:
function testBreak(x)
{
var index = 0;
while (index < 6)
{
if (index == 3) break;
index ++
};
return index*x;
};
在while或者for语句外使用break语句将导致编译错误。
9. continue语句
中断执行在循环内的语句,直接执行下一个循环。Continue语句只能用在while或for语句的循环体中,用来终止当前的一次循环。当循环体中遇到continue语句时,程序跳过continue语句后的其余语句,开始下一次循环。
例如:
var index = 0
var count = 0
while (index < 5)
{
index++;
if (index == 3)
continue;
count += index;
};
continue不会中断循环的执行:
- 在while循环中,将返回到条件判断的语句。
- 在for循环中,将返回到更新的语句。
注意:在for或者while语句外使用continue将导致编译错误。
10. return语句
在函数体内使用,用来指定函数的返回值。return语句用在一个函数的函数体里,为函数返回一个值。如果一个函数没有return语句,或者虽然有,但是没有执行到return语句,则函数返回一个空字符串。
return语句的形式为:
return [表达式];
例如:
function square (x)
{
if (!(Lang.isFloat(x))) return invalid;
return x * x;
}
九、WMLScript函数库
WMLScript 支持几个标准的函数库:Lang、Float、String、URL、WMLBrowser、Dialogs和Console 。每个库中分别包含一组函数,可以用“库名.函数名”的形式来调用库函数。
十、WAP辅助工具
下面介绍的是在网络上可以找到的有关WAP开发的辅助工具。
1. WAPtelnet
URL:http://www.webdynamite.com
适用于Win95/98/NT/2000、Solaris、HP-UX、AIX、Linux和MacOS操作系统。
WAPtelnet是一个telnet客户端。通过它可以连接到UNIX,路由器和其他支持telnet服务的机器上。WAPtelnet使得使用WAP进行远程管理成为可能。
2. PolarWAP Static Compiler 1.2
URL:http://www.polarwap.com/downloads/index.htm
适用于Windows 95/98/NT/2000操作系统。
使用PolarWAP Static Compiler来提高应用程序的性能。当WAP网关处理WML内容的时候,它们首先需要将内容翻译成二进制再提供给移动设备。这是一个缓慢而且容易出错的阶段。当处理编译后的WML页面,相反就快多了。
3. Enhydra
URL:http://www.enhydra.org/software/downloads/index.html
- 包括数据组件设计室(Data Object Design Studio,DODS)和XML编译器(XML Complier,XMLC)。含源程序。
- 下载Enhydra企业版,包括EJB和CORBA技术。
- 下载新的IDE add-in wizards。
- 下载新的Enhydra Servlet Debugger。
- 下载新的演示、应用、工具、补丁等等。
4. WAP2PDF
URL:http://www.sanface.com/
从WEB或者WAP上创建PDF文件。
5. WAP email form 1.0
URL:http://www.jumbuck.com/downloads/emailform_1_0.zip
将这个使用Perl编写的代码加入到站点里面。就可以收发E-Mail了。有一个简单的readme文件来解释如何建立CGI并测试。
6. HAWHAW
URL:http://www.hawhaw.de/
提供的适用于PHP的WAP工具包,将会使WAP开发更加简单。
7. Zygo Communications
URL:http://www.z-y-g-o.com/
这些工具都是Zygo自己内部使用的工具,也许对其他的WAP开发人员有用。免费的,也没有任何保证。如果崩溃了,读者必须自己承担责任。
- CGI::WML
一个LDS的子类CGI.pm Perl模块。用来生成WML输出名字转换。CGI::WAP在CPAN(http://www.perl.com/CPAN)作为CGI::WML-0.04。
这个版本只适合于CGI.pm 2.67。需要使用最新的版本来升级。
- WML到WMLC
- wml_to_wmlc.pl
一个用Perl语言编写WML到WMLC转换器。基于XML::Parser。不但能转换,而且做一定的优化工作。
- wmlc-0.001.tar.gz
一个用C语言编写的WML到WMLC转换器。基于Thomas Neil的wml_tools工具包。同样也有Perl界面,但是还没有完成。
- HTML到WML
- html_to_wml.pl
一个使用Perl编写的工具。可以将HTML页面转换成WML页面。CGI::WML以上包括了HTML到WML的转换
- WML URL效验
- waptest.pl
一个使用Perl编写的,基于URL语法编写的WML URL合法检测程序。
- Header dump
- hd.pl
查看WML或者HTML浏览器的请求头数据。HTML或者WML输出,依据发送请求的浏览器。