WML開發介紹
這裏介紹WAP協議標準組織所製定的標記語言WML,由於和以前介紹的HDML在手機瀏覽器專用網頁的特征上基本一致,所以概念部分就略去了,直接講述語言。
1。基本規則
* WML使用XML文檔字符集,目前支持Unicode 2.0,和HDML不同,WML的所有標簽,屬性和規定的可接收值必須小寫,CARD的名字和變量也是區分大小寫的。和HDML一樣,對於連續的空字符,隻顯示一個空格。標簽內屬性的值必須用"或者'括起來,屬性名,=和值之間不能有空格。對於不成對出現的標簽,必須在 > 前加 / ,比如<br/>。在對變量的引用上和HDML基本相同,有:
$(var1:esc)
$(var1:noesc)
$(var1:unesc)
三種形式,具體含義參見前麵HDML的相關部分。在對保留字符的處理上也基本相同,對應的取代字符有:
< <
> >
? ' '
" "
& &
$ $$
空格
- ­
這裏要指出的是在URL的傳遞過程中,用來連接參數的 & 必須轉化為 & 。
2。基本格式和文件頭
wml文件的一般格式:
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "">
<wml>
<head>
<access/>
<meta..../>
</head>
<card>
Some contents...
</card>
<wml>
結構看上去和HTMl文件很類似,對於每一個DECK,在其文檔開頭必須指明以下的類型聲明。
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "">
千萬注意字母的大小寫。對於一個DECK,其文件大小最好不要超過1.2K。
<wml>標簽和HTML中的<html>標簽一樣,用來表明這是一個WML的DECK,它有一個可選的xml:lang屬性來製定文檔的語言,比如<wml xml:lang="zh">表示文檔語言為中文。
和HTML一樣<head>標簽包含了該DESK的相關信息。<head>標簽之間可以包含一個<access>標簽和多個<meta>標簽。
<access domain="域" path="/路徑" />相當於HTML中的<BASE>標簽,指定該DECK的訪問控製信息,它用兩個可選的屬性,domain用來指定域,默認值為當前域,path用來指定路徑,默認值為"/",即根目錄。由於<access>單獨使用,所以要用/結尾,以後對於類似的情況不再贅述。
<meta 屬性 content="值" scheme="格式" forua="true|false"/>和HTML中的類似,提供了該DECK的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"/>指定DECK在手機內存緩存中的存儲時間段,默認的為30天(除非內存耗盡),在該期間,手機對於訪問過的DECK直接從緩存裏調用。如果信息是對時間敏感的,可以用max-age指定DECK在緩存裏的生存期,最小單位是秒,如果指定為0,則每次都需通過連接服務器來調用該DECK。
<meta user-agent="vnd.up.markable" content="false"/>和<meta user-agent="vnd.up.bookmark" content="指定的URL"/>類似於普通瀏覽器的書簽功能。當用戶將一個CARD做了書簽後,手機瀏覽器首先用一個標記記錄該CARD,這個標記默認的是<card>標簽中的title屬性(以後會講到),然後當用戶選擇了該書簽以後,瀏覽器就會打開被記錄的URL。但是因為在默認的情況下,手機會記錄所有的DECK,所以,一般<meta>被用來使手機不要記錄當前的URL,即<meta user-agent="vnd.up.markable" content="false"/>。此外,如果要為書簽指定不同於當前DRECk的URL,用<meta user-agent="vnd.up.bookmark" content="指定的URL"/>。
一個DECK可以包含多個CARD,每個CARD的內容可能不止一屏顯示,注意DECK,CARD和屏幕顯示範圍的關係。一個CARD用<card>和</card>包含。<card>可以包含以下可選的屬性:
<card title="label" newcontext="false" ordered="true" onenterforward="url" onenterbackward="url" ontimer="url">
*id屬性用來指定CARD的名字,可用來在CARD間跳轉,相當於在HTML中在頁內跳轉時用<A NAME="jumpHere">。
*title屬性用來作為書簽的標記,該屬性一般不會顯示在屏幕上。
*newcontext屬性,默認值為false,用來指示當跳轉到本CARD時,手機是不是要清除以前保留的信息,包括變量,堆棧裏的曆史記錄,重新設置手機狀態等。
*ordered屬性,默認值是true,表明該CARD裏的內容是按固定的順序顯示,還是按用戶的選擇來顯示。這點和HTMl不同,CARD頁麵裏的內容可以按一定的順序顯示,默認的是按線性順序顯示,即按代碼的順序,但是,要注意的是,以下三個標簽必須按以下順序來寫<onevent> <timer> <do>,(這和以後要講的“事件”有關)。這樣做是為了方便填表單,當ordered設置為true時,如果一個表單的內容不能在一屏裏顯示完,就分成多屏顯示;當ordered設置為false時,手機可以顯示一個概要CARD來總結有效的選項,用戶可以從中選取表單選項來填寫。
*onXXX屬性,類似於HTML標簽中的onXXX屬性,用來捕捉事件,當事件被觸發時執行指定的操作(任務),在這裏是轉向某個URL。
3。顯示文本
在文本的顯示上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屬性和前麵提到的一樣是對齊方式。表格中可以包含文字和圖片。
test1.wml
--------------
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "">
<wml>
<card>
<p align="center">
<i>Hello</i><br/>
<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>
4。顯示圖片
顯示圖片(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手機都支持這些屬性。
test2.wml
---------------
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "">
<wml>
<card>
<p align="center"><img alt=":)" src="xxx.bmp" localsrc="smileyface"/></p>
</card>
</wml>
5。錨和任務
連接是HTML頁麵裏最基本的功能,在WML裏也一樣用<a href="url" title="label">和</a>來包括用來建立連接的文字,必選屬性href指定了要打開的URL,可選的title屬性給該連接取個標記名字,這個名字將作為軟按鈕之一的ACCEPT鍵(詳見以前的HDML入門文章)的標記顯示在屏幕的軟按鈕區,所以通常可以將屬性作為提示文字是用。
然而,以上的連接在WML裏隻是任務的一種情況,為了能夠使用其它任務,所以引進了新的標簽<anchor title="label">任務標簽 文本</anchor>,<a>其實是當任務標簽為<go/>時的簡單表示方式。
test3.wml
---------------
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "">
<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>,還可以用在事件中:
1)<go>用來指示瀏覽器顯示指定的URL,包括DECK的第一個CARD或者指定的CARD。語法如下:
<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>。
2)<prev>用來將當前頁麵的URL壓入URL曆史堆棧,並打開此前的URL,若該URL不存在,則<prev>無效。語法類似<go>:<prev><setvar name="name" value="value"/></prev>,<prev>和</prev>之間可加入一句或多句<setvar name="name" value="value"/>,若不加,則必須變成<prev/>的形式。
3)<refresh>用來刷新當前的頁麵,從而使得頁麵內的變量刷新,語法為<refresh><setvar name="name" value="value"/></refresh>。
4)<noop>,表示什麼也不做,該標簽不能用在<anchor>中,一般用在覆蓋DECK級的<do>(以後會說明)。
6。顯示表單
類似於HTML的<FORM>,<fieldset>可用來包括一組表單選項,但不是必須的。前麵說過,當<card>的ordered設置為false時,手機可以顯示一個概要CARD來總結有效的選項,方便用戶從中選取表單選項來填寫,概要CARD就是根據<fieldset>和獨立的輸入框<input>以及選單<select>來總結的。語法為,<fieldset title="label">表單內容</fieldset>,可選的title屬性除了可用來表示表單的名字外,還在概要CARD裏作為選擇項的標題。表單內容可以是嵌套的<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屬性的值)標記型字符。
標記 描述
A 任何符號或者大寫字母(不包括數字)
a 任何符號或者小寫字母(不包括數字)
N 任何數字(不包括符號或者字母)
X 任何符號、數字或者大寫字母(不可改變為小寫字母)
x 任何符號、數字或者小寫字母(不可改變為大寫字母)
M 任何符號、數字或者大寫字母(可改變為小寫字母)或者多個字符,默認為首字大寫
m 任何符號、數字或者小寫字母(可改變為大寫字母)或者多個字符,默認為首字小寫
*maxlength屬性,指定了用戶可輸入的最大字符長度,最大限製為256個字符。
*emptyok屬性,表示用戶可否不填輸入框,默認為false,即要填。
*size屬性,輸入框顯示長度,目前未被支持。
*tabindex屬性,類似於在HTML表單中按TAB鍵後,焦點落在哪個選項上,該值決定了這個選擇順序,數字大的排在後麵。目前未被支持。
test4.wml
---------------
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "">
<wml>
<card 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>
將上例<card>中的odered的值改為"true"試試看,然後再在<p>和</p>內加入<fieldset title="field1">和</fieldset>試試看。
<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。
test5.wml
---------------
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "">
<wml>
<card 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>
7。事件
WML的事件基本上分為兩大類,一類是鍵盤(包括軟硬按鈕)輸入事件,用<do>標簽來處理,另一類是相關頁麵內部的事件,用<onevent>標簽來處理。
<do>的語法如下:<do type="type" label="label" name="name" optional="false|true">任務</do>,任務就是以前提到的四種任務。<do>的屬性中,type是必選的,其他為可選。
*label屬性,指定了軟按鈕在屏幕上的顯示文本。目前type屬性為delete,help,prev時該屬性無效。
*name屬性,為<do>取個名字,同一的CARD裏的<do>不能重名。如果CARD級的<do>和DECK級的<do>同名,則覆蓋DECK級的<do>。
*optional屬性,指定手機是不是可以忽略這個事件,默認值是false。
*type屬性,指定觸發的事件,具體如下;
type值 觸發原因
accept 調用ACCEPT按鈕機製
delete 調用DELETE按鈕機製
help 調用HELP按鈕機製
options 調用選擇按鈕機製
prev 調用PREV按鈕機製
reset 調用清除和重新設定手機狀態時的RESET機製(目前不支持)
unknown 調用unknown機製,等於type=""(目前不支持)
vnd. co-type 調用廠商特定的機製(目前不支持)
X-*, x-* 供以後使用(不保留)(目前不支持)
test6.wml
---------------
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "">
<wml>
<head>
<meta http-equiv="Cache-Control" content="max-age=0"/>
</head>
<card 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 >
<p>
You name is $(userName:noesc).
</p>
</card>
</wml>
<onevent>的語法如下,<onevent type="type">任務</onevent>,必選屬性type的取值如下:
type值 如果用戶執行了以下操作就執行任務
onpick 用戶選擇或不選一個<option>項時。
onenterforward 用戶使用<go>任務到達一個CARD時。
onenterbackward 用戶使用<prev>任務返回到前麵的CARD時,或者按BACK按鈕時。
ontimer 當<timer>過期時。
test7.wml
---------------
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "">
<wml>
<head>
<meta http-equiv="Cache-Control" content="max-age=0"/>
</head>
<card 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 >
<p>
You are Living in $(city:noesc)
</p>
</card>
</wml>
<timer/>可以用來在用戶不進行任何操作的一段時間後,自動執行一個任務,任何激活CARD頁麵的任務和用戶操作都會啟動<timer/>,而任務進行時,<timer/>就停止。每個CARD隻能有一個<timer/>,一個<timer/>隻能觸發一個任務。語法如下:<timer name="variable" value="value"/>,其中name為可選屬性,指定為一個變量名,當退出該CARD時,該變量存儲此時定時器的值,當定時器超時時,手機將該變量設為0;value為必選屬性,用來設置定時器的定時值,最小單位為0.1秒。
test8.wml
---------------
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "">
<wml>
<head>
<meta http-equiv="Cache-Control" content="max-age=0"/>
</head>
<card ontimer="#card2">
<timer name="time1" value="50"/>
<p align="center">
After 5s, goto card2
</p>
</card>
<card >
<onevent type="ontimer">
<go href="#card1"/>
</onevent>
<timer name="time2" value="50"/>
<p align="center">
Here is card2!
</p>
</card>
</wml>
再提一下,<onevent> <timer> <do>三者必須按以上順序寫。
此外在DECK級還可以加入<template>,用來將事件捆綁在DECK級上,語法如下:
<template onenterforward="url" onenterbackward="url" ontimer="url">
<do>或者<onevent>
</template>
test9.wml
---------------
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "">
<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 ordered="false">
<do type="accept" label="cardPress" name="do1">
<go href="#card02"/>
</do>
<p>
Press ACCEPT...
</p>
</card>
<card >
<p>
Here is card01
</p>
</card>
<card >
<p>
Here is card02
</p>
</card>
</wml>
8。CGI編程
1)在WEB服務器上添加WML的MIME類型
對於IIS4,可在其管理器裏的站點屬性中加入新的MIME類型,後綴.wml和MIME類型text/vnd.wap.wml。
對於PWS,可修改注冊表,先在HKEY_CLASSES_ROOT層加入主鍵.wml,再加入串值Content Type為text/vnd.wap.wml,然後在HKEY_LOCAL_MACHINE/Software/CLASSES/MIME/Database/Content Type/中加入主鍵text/vnd.wap.wml,再加入串值Extension為.wml。
以前提到的HDML也用類似的方法。
2)以http方式訪問wml文件
在手機瀏覽器的URL欄裏輸入,就可以訪問WML文件了。
////////------------------------------////////
3)CGI設計
和普通CGI變成的方式差不多,隻是返回結果時,先要輸出Content-Type為text/vnd.wap.wml,然後再輸出WML內容。
test10.wml
---------------
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "">
<wml>
<head>
<meta http-equiv="Cache-Control" content="max-age=0"/>
</head>
<card >
<do type="accept" label="Input Name" name="do1">
<go href="" method="post">
<postfield name="uid" value="123456"/>
<postfield name="uname" value="$(userName:esc)"/>
</go>
</do>
<p>
NAME:<input name="userName" title="User Name" type="text" format="*M" emptyok="false" maxlength="12"/>
</p>
</card>
test10.asp
---------------
<%
uid=Request.Form("uid")
userName=Request.Form("uname")
Response.ContentType="text/vnd.wap.wml"
%>
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "">
<wml>
<card>
<p>
USERNAME:<%=userName%>
USER__ID:<%=uid%>
</p>
</card>
</wml>
最後更新:2017-04-02 00:06:42