The Wireless Markup Language (WML)
Introduction
WML is a markup language that is based on XML (eXtensible Markup Language). The official WML specification is developed and maintained by the WAP Forum, an industry-wide consortium founded by Nokia, Phone.com, Motorola, and Ericsson. This specification defines the syntax, variables, and elements used in a valid WML file. The actual WML 1.1 Document Type Definition (DTD) is available for those familiar with XML at:
http://www.wapforum.org/DTD/wml_1.1.xml
A valid WML document must correspond to this DTD or it cannot be processed.
In this tutorial, we’ll present WML basics and an example. This example will demonstrate events and navigation as well as data retrieval from server CGI scripts. Discussion of client-side scripting and state management will be presented in the WMLScript tutorial.
NOTE: We will only discuss features contained in the WML standard. Information on non-standard WML capabilities added by vendors can be obtained by consulting that vendor’s documentation.
Next: Understanding the Wireless Markup Language
Understanding the Wireless Markup Language
WML is based on XML, a markup language that has garnered enormous support due its ability to describe data (HTML, meanwhile, is used to describe the display of data…a big difference). While HTML predefines a “canned” set of tags guaranteed to be understood and displayed in a uniform fashion by a Web browser, XML allows the document creator to define any set of tags he or she wishes to. This set of tags is then grouped into a set of grammar “rules” known as the Document Type Definition, or DTD. As mentioned earlier, the DTD used to define WML is located at:
http://www.wapforum.org/DTD/wml_1.1.xml
If a phone or other communications device is said to be WAP-capable, this means that it has a piece of software loaded onto it (known as a microbrowser) that fully understands how to handle all entities in the WML 1.1 DTD.
The first statement within an XML document is known as a prolog. While the prolog is optional, it consists of two lines of code: the XML declaration (used to define the XML version) and the document type declaration (a pointer to a file that contains this document’s DTD). A sample prolog is as follows:
<xml version=’1.0′>
<!DOCTYPE wml PUBLIC “-//WAPFORUM//DTD WML 1.1//EN” “http://www.wapforum.org/DTD/wml_1.1.xml”>
Following the prolog, every XML document contains a single element that contains all other subelements and entities. Like HTML all elements are bracketed by the
<>
and
</>
characters. As an example: <code><element>datadatadata</element></code>. There can only be one document element per document. With WML, the document element is <code><wml></code>; all other elements are contained within it.
The two most common ways to store data within an XML document are elements and attributes. Elements are structured items within the document that are denoted by opening and closing element tags. Elements can also contain sub-elements as well. Attributes, meanwhile, are generally used to describe an element. As an example, consider the following code snippet:
<!– This is the Login Card –>
<card id=”LoginCard” title=”Login”>
Please select your user name.
</card>
In the code above, the card element contains the id and title attributes. (On a side note, a comment in WML must appear between the tags.) We will make use of the WML-defined elements and their attributes later as we build our examples.
Valid WML Elements
WML predefines a set of elements that can be combined together to create a WML document. These elements include can be broken down into two groups: the Deck/Card elements and the Event elements.
Deck/Card Elements
wml |
card |
template |
head |
access |
meta |
Event Elements
do |
ontimer |
onenterforward |
onenterbackward |
onpick |
onevent |
postfield |
Tasks
go |
prev |
refresh |
noop |
Variables
setvar |
User input
input |
select |
option |
optgroup |
fieldset |
Anchors, Images, and Timers
a |
anchor |
img |
timer |
Text Formatting
br |
p |
table |
tr |
td |
Each of these elements is entered into the document using the following syntax:
<element> element value </element>
If an element has no data between it (as is often the case with formatting elements such as <br>), you can save space by entering one tag appended with a \ character (for instance, <br/>).
Next: Building Applications With WML
Building Applications With WML
WML was designed for low-bandwidth, small-display devices. As part of this design, the concept of a deck of cards was utilized. A single WML document (i.e. the elements contained within the <wml> document element) is known as a deck. A single interaction between a user agent and a user is known as a card. The beauty of this design is that multiple screens can be downloaded to the client in a single retrieval. Using WMLScript, user selections or entries can be handled and routed to already loaded cards, thereby eliminating excessive transactions with remote servers. Of course, with limited client capabilities comes another tradeoff. Depending on your client’s memory capabilities, it may be necessary to split multiple cards up into multiple decks to prevent a single deck from becoming too large.
Using Variables
Because multiple cards can be contained within one deck, some mechanism needs to be in place to hold data as the user traverses from card to card. This mechanism is provided via WML variables. Variables can be created and set using several different methods. For instance:
- Using the <setvar> element as a result of the user executing some task. The <setvar> element can be used to set a variable’s state within the following elements: go, prev, and refresh. The following element would create a variable named x with a value of 123:
·
· <setvar name=”x” value=”123″/>
·
- Variables are also set through any input element (input, select, option, etc.). A variable is automatically created that corresponds with the name attribute of an input element. For instance, the following element would create a variable named x:
·
· <select name=”x” title=”X Value:”>
·
Although we haven’t discussed WMLScript yet, it is important to note that WML and WMLScript within a document share the same variables.
Creating A WML Deck
In this example, we’ll start by creating a WML deck that allows us to first select a username from a list, enter in a password, then have our selections repeated back to us. This will illustrate the basic handling of user input, events, and variables all within one deck using multiple cards.
Listing 1 - WMLExample.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=”Login” title=”Login”>
<do type=”accept” label=”Password”>
<go href=”#Password”/>
</do>
<p>
UserName:
<select name=”name” title=”Name:”>
<option value=”John Doe”>John Doe</option>
<option value=”Paul Smith”>Paul Smith</option>
<option value=”Joe Dean”>Joe Dean</option>
<option value=”Bill Todd”>Bill Todd</option>
</select>
</p>
</card>
<card id=”Password” title=”Password:”>
<do type=”accept” label=”Results”>
<go href=”#Results”/>
</do>
<p>
Password: <input type=”text” name=”password”/>
</p>
</card>
<card id=”Results” title=”Results:”>
<p>
You entered:<br/>
Name: $(name)<br/>
Password: $(password)<br/>
</p>
</card>
</wml>
As you can see, the prolog of this document contains the XML version number to be used as well as the Document Type Definition to be referenced. Following this comes the wml document element (the deck) that contains three cards: Login, Password, and Results. Each of these cards is defined using the element. Because the Login and Password cards also define events, they use the element to define the event to be triggered. Figure 1 shows the initial card loaded in a test browser.
Figure 1 |
When the “accept” type of the do element is encountered, it is displayed as an option on the WAP device display (see Figures 2, 3, and 4).
Figure 2 |
Figure 3 |
Figure 4 |
Selecting this option causes the element to be analyzed.
If you are familiar with the anchor tag () in HTML, you know that it specifies an href attribute that tells the browser where to link to if this anchor is selected. The WML element’s “href” attribute works in the same manner. As with HTML, to link to another card in the document, you simply prepend a # symbol before it. For example, to link to the Results card, we define the following element:
<go href=”#Results”/>
This Results card makes use of variables by retrieving and displaying the contents of the name and password variables. Recall that variables are substituted into a card or deck by using the following syntax:
$(variable_name)
Calling A Server Script
Without the ability to perform server transactions, WML would only serve to provide a standardized way to display text on a client. Adding in the ability to dynamically connect to remote servers opens up every WAP device to the world of Internet messaging, enterprise data, and e-commerce. WAP devices interact with these data sources through a WAP gateway as mentioned in our WAP Overview tutorial. This gateway must interface with a carrier such as CDMA, GSM, or GPRS. However, it is possible to install and test gateway products in conjunction with popular Web servers (such as Microsoft Internet Information Server or Apache) on your LAN. This tutorial won’t go into the details of installing and configuring a gateway (see our WAP Tools Comparison tutorial for more information) but to eliminate a very common beginner’s error, we’ll remind you to be sure to add the following MIME types to your Web server:
WML text/vnd.wap.wml wml
WMLScript text/vnd.wap.wmlscript wmls
Once this has been done, you’re ready to go! We’ll now create a very simple example which allows the user to select an option and then retrieve data from a server based on that option. For this example, we’re using Microsoft Active Server Pages (ASP) technology for the server-side scripting since that is the technology supported by our hosting provider. You could just as easily use other popular server scripting tools such as Java Servlets, JavaScript, or Perl. Listing 2 gives the WML source code for our new deck. It basically contains a single
<select>
element that gives the user a few options for retrieval. The
<go>
element for this select list calls a server script with the appropriate arguments.
Listing 2 - WMLExample2.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=”Order” title=”Query Inventory”>
<p>
<select name=”Items” title=”Items”>
<option value=”Books”>Books</option>
<option value=”Music”>Music</option>
<option value=”Video”>Video</option>
<option value=”Software”>Software</option>
</select>
</p>
<do type=”accept” label=”Query”>
<go href=”http://127.0.0.1/WML/Inventory.asp” method=”post”>
<postfield name=”Items” value=”$(Items)”/>
</go>
</do>
</card>
</wml>
The server script (shown in Listing 3) examines the input and produces WML output to be displayed on the device.
Listing 3 - Inventory.asp
<%
Dim Body
If Request.Form(”Items”) = “Books” Then
Body = “You selected Books!”
ElseIf Request.Form(”Items”) = “Video” Then
Body = “You selected Video!”
ElseIf Request.Form(”Items”) = “Software” Then
Body = “You selected Software!”
ElseIf Request.Form(”Items”) = “Music” Then
Body = “You selected Music!”
End If
Response.ContentType = “text/vnd.wap.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>
<p>
<%Response.write(Body)%>
</p>
</card>
</wml>
Figures 5 and 6 show the Music option being selected and the resultant screen retrieved from the ASP script.
Figure 5 |
Figure 6 |
A few things should be mentioned for those wishing to run this example on their local Web server. You must register the proper MIME types with your Web server so that WML content can be properly sent. The two MIME types that should be registered are:
.wml text/vnd.wap.wml
.wmls text/vnd.wap.wmlscript
If you’d like to use Wireless Bitmap images (the image format supported by WAP), also add:
.wbmp image/vnd.wap.wbmp
Finally, I’d like to mention one error I continually received when developing this example using the Nokia WAP Toolkit 1.2. I’ve seen numerous postings on WAP Development boards concerning this error so I thought I’d explain the problem and solution here. Although I registered the MIME types with IIS 4.0, I still received the message “Mime type not supported.” It turns out that even though I was loading the WML source via my local machine’s Web server, the Toolkit was switching over to a file://-based URL since the file was local to my machine. When I then attempted to run the script using href=”Inventory.asp”, I got the error. Switching the href over to http://127.0.0.1/WML/Inventory.asp forced the loading of the script through the Web server which allowed for proper recognition of the WML MIME types.
Conclusion
WML offers software developers an entirely new, exciting platform on which to deploy their applications. With this new platform, however, comes a host of tradeoffs and challenges. A new wrinkle will be added to the design process as things like server round-trips, bandwidth, and display sizes become issues to contend with. While it may take several iterations for developers and vendors to get their product offerings right, there is no doubt that WAP opens the door to a new era in application development and deployment.
Next: Adding Client-Side Logic To WAP Using WMLScript
Adding Client-Side Logic To WAP Using WMLScript
WMLScript is the WAP corollary to the JavaScript scripting language that was popularized by Netscape Communications. Standardization efforts by Netscape helped produce the ECMAScript standard, a standard that WMLScript was based on. While JavaScript has since been coopted by server tool vendors (including Netscape and Microsoft), WMLScript is a client-only scripting platform used in combination with WML to provide client side procedural logic. Like WML, WMLScript is compiled via a WAP gateway into binary form to provide intelligence to mobile clients. In this brief tutorial, we’ll discuss what WMLScript is and how to use it. For more information on WMLScript, visit the WAP Forum.
WMLScript Language Syntax
WMLScript syntax is based on the ECMAScript programming language. Unlike ECMAScript, however, the WMLScript specification also defines a bytecode and interpreter reference architecture for optimal utilization of current narrowband communications channels and handheld device memory requirements. The following bullets help summarize some basic syntactical features of the language:
- The smallest unit of execution in WMLScript is a statement and each statement must end with a semicolon (;).
- WMLScript is case-sensitive.
- Comments can either be single-line (beginning with //) or multi-line (bracketed by /* and */). This syntax is identical to both C++ and Java.
- A literal character string is defined as any sequence of zero or more characters enclosed within double (”") or single (‘) quotes.
- Boolean literal values correspond to true and false.
- New variables are declared using the var keyword (i.e. var x;)
Data Types
WMLScript is a weakly typed language. This means that no type-checking is done at compile- or run-time and no variable types are explicitly declared. Internally, the following data types are supported:
Boolean
Integer
Floating-point
String
Invalid
The programmer does not need to specify the type of any variable; WMLScript will automatically attempt to convert between the different types as needed. One other point to note is that WMLScript is not object-oriented (such as Java or C++). Therefore, it is impossible to create your own user-defined data types programmatically.
Operators
WMLScript supports a variety of operators that support value assignment operations, arithmetic operations, logical operations, string operations, comparison operations, and array operations. For more information on the wide variety of WMLScript operators, see the WMLScript specification.
Flow Control Statements
The operators and expressions supported by WMLScript are virtually identical to those of the JavaScript programming language so we will not discuss them here. Java does support a number of control statements for handling branching within programs. These include the if-else, for loop, while loop, break, and continue statements.
Functions
Related WMLScript statements can be executed together as a unit known as a function. A function declaration has the following syntax:
extern function identifier(FormatParameterList) Block ;
The extern keyword is optional and is used to specify a function that can be called from outside the current compilation unit in which the function is defined. A sample WMLScript function declaration looks like this:
function RunTime(distance, speed) { var time = distance / speed; return time; };
The above example simply takes two input variables, distance and speed, and uses them to calculate a time variable. The return keyword is then used to return a value.
When calling a function included with one of the WMLScript standard libraries (see below), the library name must be included with the function call. For example, to call the String library’s length() function, use the following syntax:
var a = String.length(”1234567890″);
Next: The WMLScript Standard Libraries
The WMLScript Standard Libraries
While WMLScript does not support the creation of new objects via object-oriented programming, it does provide six “pre-built” libraries that aid in the handling of many common tasks. These libraries (with a brief description of each) include:
- Lang - This library contains a set of functions that are closely related to the WMLScript language core. Included in this library are functions for data type manipulation, absolute value calculations, and random number generation.
- Float - The Float library is optional and is only supported on those clients who have floating-point capabilities. Typical functions provided by this library include sqrt(), round(), and pow().
- String - The String library contains a set of functions for performing string operations. Some of the functions included in this library are length(), charAt(), find(), replace(), and trim().
- URL - This library contains a set of functions for handling both absolute URLs and relative URLs. Typical functions include getPath(), getReferer(), and getHost().
- WMLBrowser - This library contains functions by which WMLScript can access the associated WML context. These functions must not have any side effects and must return invalid in cases where the system does not support WMLBrowser and where the interpreter is not invoked by the WML Browser. Commonly used functions in this library include go(), prev(), next(), getCurrentCard(), and refresh().
- Dialogs - This library contains a set of typical user interface functions including prompt(), confirm(), and alert().
Next: Validating User Input Via WMLScript
Example: Validating User Input Via WMLScript
In the following example, we will build a simple WML card that asks the user to input a social security number (an identification number used by the U.S. Social Security Administration). We will then use WMLScript to verify that the user’s input was formatted correctly. Following this verification, we’ll alert the user via WMLScript to let them know whether their number was accepted or not. This example, though simple, represents a typical usage of WMLScript on a client.
To build this example, we create a normal WML file containing two cards: an input card and a results card (see Listing 1 below). Accepting the input will result in our validateSSN() function being called. Note that this function is stored in a separate .wmls file (WMLScriptExample.wmls) and is declared within that file using the extern keyword. extern allows a function to be called by other functions or WML events that exist outside of the function’s source file. To keep a function “private”, simply declare the function without using the extern keyword.
Listing 1 - WMLScriptExample.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=”SSN” title=”SSN:”>
<do type=”accept” label=”Results”>
<go href=”WMLScriptExample.wmls#validateSSN($(SSN))”/>
</do>
<p>
Enter SSN: <input type=”text” name=”SSN”/>
</p>
</card>
<card id=”Results” title=”Results:”>
<p>
You entered:<br/>
SSN: $(SSN)<br/>
</p>
</card>
</wml>
Listing 2 - WMLScriptExample.wmls
extern function validateSSN(SSN)
{
if (String.length(SSN) != 9)
{
WMLBrowser.setVar(”SSN”, “Error: String must be 9 digits long.”);
}
WMLBrowser.go(”WMLScriptExample.wml#Results”);
};
Figure 1 |
Figure 2 |
For more information on the WML code above, see our WML tutorial. The WMLScript function shown in Listing 2 makes use of two of the standard WMLScript libraries: WMLBrowser and String. The WMLBrowser.setVar() function sets the value of a WML variable while the WMLBrowser.go() function redirects execution of the script to a card within a WML source file.