Перевод Жаркова Алексея, www.tay.ru
WML - язык разметки, основанный на XML (extensible Markup Language). Официальная спецификация WML разработана и поддерживается WAP Forum, производственным консорциумом, основанном Nokia, Phone.com, Motorola и Ericsson. Эта спецификация определяет синтаксис, переменные и элементы используемые в файлах WML. Последнее определение типа документа (Document Type Definition) для тех, кто знаком с XML, доступны по адресу: http://www.wapforum.org/DTD/wml_1.1.xml
Любой правильный XML-файл должен соответствовать этому DTD. В противном случае он не будет правильно обработан.
В этом руководстве, мы расскажем об основах XML и представим пример. Этот пример демонстрирует обработку событий, навигацию и обмен информацией с расположенным на сервере скриптом.
WML базируется на XML, языке разметки получившем невероятную поддержку благодаря своей способности описывать данные (HTML, кстати, используется для описания представления данных). HTML - предопределяет те тэги, которые могут быть использованы для описания страницы так, чтобы ее смог правильно понять и обработать броузер. XML, в свою очередь, позволяет создателю документа определять такой набор тэгов, которой он считает необходимым. Этот набор тэгов группируется затем в набор грамматических "правил", называемых по-другому Определение Типа Документа или проще DTD. Как уже упоминалось ранее, DTD, используемый для описания WML, расположен по адресу: http://www.wapforum.org/DTD/wml_1.1.xml
В телефоне или в любом другом коммуникационном устройстве, заявленном как WAP-совместимое, загружено специальное программное обеспечение (известное как микроброузер), которое полностью понимает, как обрабатывать все вариации WML 1.1 DTD.
Самая первая фраза внутри любого XML-документа называется пролог. Поскольку стандартен, он содержит две строчки кода: определение версии XML и DTD (указатель на файл, содержащий DTD)
Пролог выглядит следующим образом.
<?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
Следом за прологом, в каждом XML-документе содержится один единственный элемент, который содержит в себе остальные подэлементы и entities. Так же как и в HTML этими элементами являются угловые скобки: <> и </>. Например: <element>data</element>. В документе должен содержаться только один элемент описывающий сам документ. В WML этим элементом является <wml>. Все остальные элементы содержатся уже внутри него.
Два самых распространенных способа хранения информации внутри XML-документа это элементы и их атрибуты. Элементы определяют структурную разметку внутри документа открытием и закрытием определенных тэгов. Элементы, в свою очередь могут содержать подэлементы. Атрибуты в основном используются для описания элементов. В качестве примера можно привести следующий кусочек кода:
<!-- This is the Login Card --> <card id="LoginCard" title="Login"> Please select your user name. </card>
В этом примере элемент card содержит атрибуты id и title. Комментарий в WML, также как и в HTML заключается между тэгами <!-- и -->. В дальнейшем мы будем использовать элементы и их атрибуты для написания примеров.
В WML описывается набор элементов, которые можно комбинировать для создания WML-документа. Эти элементы можно условно разделить на две группы: Элементы типа Deck/Card и элементы обработки событий.
Элементы типа Deck/Card
wml card template head access meta
Элементы обработки событий
do ontimer onenterforward onenterbackward onpick onevent postfield
Задачи
go prev refresh noop
setvar
input select option optgroup fieldset
Анкоры, Картинки и Таймеры
a anchor img timer
br p table tr td
Каждый из этих элементов может быть использован в документе используя следующий синтаксис.
<элемент> значение элемента </элемент>
Если элемент не содержит внутри себя какую либо информацию (обычно такое случается с элементом форматирования <br>), вы можете использовать тэг с добавленным к нему "/" (например <br/>).
WML был разработан для для устройств с низкой пропускной способностью и маленьким дисплеем. В качестве составной этого дизайна была применена концепция дек и карт. Один WML-документ (а точнее элементы, содержащиеся внутри элемента <wml>) называется декой (deck). Интерактивное взаимодействие с пользователем осуществляется с помощью карт (card). Достоинство такой реализации заключается в том, что несколько экранов могут быть загружены на клиентское устройство за один раз. Используя WMLScript, обработка действий пользователя может быть произведена с использованием находящихся в одной деке карт, исключая тем самым множественные транзакции с сервером. Конечно, в связи с ограниченными ресурсами клиентского устройства возникает другая проблема. Поэтому вам вполне возможно придется разбрасывать ваши карты по разным деками во избежании чрезмерного увеличения объема одного файла.
Поскольку, как мы говорили ранее, в одной деке может содержаться несколько карт, нам потребуется механизм хранения информации из одной карты для ее последующего использования в другой. Этот механизм обеспечивается переменными. Переменные могут быть созданы и определены, используя несколько различных методов.
<setvar name="x" value="123"/>
<select name="x" title="X Value:">
Несмотря на то, что мы не описывает WMLScript, следует отметить, что WML и WMLScript используют одни и те же переменные в рамках одной деки.
В этом примере, мы начнем создавать деку, которая позволяет нам сначала выбрать имя пользователя из предложенного списка, затем ввести пароль после чего выводит на экран полученные данные.
<?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>
Как вы наверно уже заметили, вначале примера идет пролог, в котором мы определяем версию XML и DTD для нашего документа. Затем следует элемент <wml>, дека которая содержит три карты: Login, Password и Result. Каждая из этих карт определяется с использованием элемента <card>. Поскольку карты Login и Password определяют события, они используют элемент <do type="accept"> для определения события которое произойдет, когда пользователь закончит ввод.
Если мы определяем элемент <do> типом "accept" он появляется на экране в качестве опции
Выбор этой опции приведет к анализу введенной пользователем информации.
Атрибут "href" тега <go> работает так же, как и в элементе <a> из HTML. Также как и в HTML, для того, чтобы на экран вывелась другая карты из активной деки, на нее надо сослаться используя символ "#" перед именем карты.
<go href="#result"/>
Эта карта обрабатывает пользовательский ввод и используя определенные в предыдущей карте переменные выводит их содержимое на экран. Вызов переменных осуществляется следующим образом:
$(variable_name)
Без возможности производить различные операции с информацией на сервере, WML остался бы просто средством форматированного вывода текста. Добавление такой возможности, напротив, открывает любому WAP-совместимому устройству пути передачи сообщений через Интернет, промышленному использованию на предприятии и электронной коммерции. WAP-совместимое устройство взаимодействуют с подобными источниками информации через WAP-шлюз. Этот шлюз должен уметь взаимодействовать с различными стандартами сотовой связи, такими как CDMA, GSM или GPRS. Однако, вполне возможно установить тестовый шлюз в сочетании с популярными веб-серверами (такими как MS IIS или Apache) прямо в вашей локальной сети. Мы не будем тут сильно вдаваться в детали процесса установки шлюза, однако нельзя не предостеречь вас от самой распространенной ошибки. Вам обязательно необходимо добавить определения следующих типов в конфигурацию веб-сервера.
WML text/vnd.wap.wml wml WMLScript text/vnd.wap.wmlscript wmls
Теперь мы рассмотрим небольшой примерчик в котором пользователю будет предложено сделать выбор какой-то одной опции а затем на основе этого выбора с сервера будет загружена определенная информация. Для этого примера мы используем ASP. С тем же успехом мы могли написать скрипт использую Javascript, Servlets, Perl или любой другой язык. В следующем листинге приведен исходный код для нашей новой деки. В ней содержится всего один элемент <select>, который предлагает пользователю выбор из нескольких опций. Элемент <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 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>
Скрипт показанный на листинге 3 обрабатывает полученную из деки информацию и выводит на экран результат.
<% 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>
Несколько вещей необходимо напомнить для тех, кто захочет повторить этот пример в своих условиях. Вы обязательно должны "зарегистрировать" MIME типы на своем сервере для того, чтобы файлы WML и WMLScript правильно обрабатывались и отображались сервером.
.wml text/vnd.wap.wml .wmls text/vnd.wap.wmlscript
Если вы хотите использовать картинки (WBMP) вам также необходимо добавить и этот MIME-тип:
.wbmp image/vnd.wap.wbmp
WML предоставляет разработчикам совершенно новую замечательную платформу для создания приложений. Эта платформа бросает нам новый вызов. Новые нюансы, связанные с низкой пропускной способностью, маленьким экраном и различными серверными заморочками, добавятся в процесс дизайна. Несмотря на то, что производителям придется пройти различные стадии осознания новых возможностей и ограничений для того чтобы суметь наконец достаточно внятно сформулировать коммерческое предложение, WAP открывает широкие двери в новую эру разработки и развертывания приложений.
Деки.
Дека определяется элементом wml
<?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN""http://www.wapforum.com/DTD/wml_1.1.xml"> <wml> <card> <p>Hello World!</p> </card> </wml>
Элемент:
Do
Атрибуты:
type - указывает микроброузеру назначение кнопки. В WML определяется девять типов, но в подавляющем большинстве случаев используются "accept" и "options".
label - значение этого атрибута используется для замены названия кнопки. Это помогает кастомизировать приложения. Количество символов на кнопке ограничено возможностями устройства.
name - установка этого атрибута дает возможность разработчику воспользоваться преимуществами иерархической структуры WML-документа. Элемент "do" с именем "one" унаследует свойства определенные элементу с таким же именем в элементе "template" этой деки.
optional - указывает микроброузеру на необязательность показа этой кнопки в случае если атрибуту присвоено значение true.
Элемент
Go
Атрибуты:
href - URL.
sendreferer - этот атрибут необходим серверу в списках контроля доступа. Его значение указывает броузеру на то, что необходимо отослать на сервер URL минимально возможной длины.
method - может принимать значение либо "post" либо "get". Значение аналогично HTML.
accept-charset - указывает кодировку, в которой микроброузер должен посылать ссылку.
Небольшой пример простейшей навигации.
<?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.com/DTD/wml_1.1.xml"> <wml> <card id="Start"> <do type="accept"> <go href="#nextCard"/> </do> <p>Hello World!</p> </card> <card id="nextCard"> <do type="options"> <prev/> </do> <p>Next Card!</p> </card> </wml>
Элемент
Setvar
Атрибуты:
name - имя, присваемое переменной. Переменная так же может выполнять эту функцию, например:
<setvar name=$bogus value=$bear>.
value - значение, присваемое переменной.
Элемент
Postfield
Атрибут:
name имя, присваемое переменной. Переменная так же может выполнять эту функцию, например:
<postfield name=$bogus value=$bear>.
value - значение, присваемое переменной.
<?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.com/DTD/wml_1.1.xml"> <wml> <card id="Start" label="Bob's CGI"> <do type="accept"> <setvar name="lastExecuted" value="bob.cgi"/> <go href="bob.cgi" method="post"> <postfield name="one" value="one one"/> <!-- the server should be able to tell that there are two values for the key one. --> <postfield name="one" value="one"/> <postfield name="two" value="two two"/> </do> <p>Hello World!</p> </card> </wml>
Элемент
Anchor
Атрибуты:
title - имя элемента. Микроброузер может воспользоваться этим атрибутом по своему усмотрению. При перемещении курсора на анкор, микроброузер может вывести его имя в софт-кнопке.
Элемент
A
Атрибут:
href - URL на который ссылается анкор. У этого элемента нет дополнительных атрибутов позволяющих указать статус ссылки или ее метод. Если необходимы эти опции можно воспользоваться элементом "anchor" с внедренным в него элементом "go":
<anchor> click me <go href="#clickedMe"/> </anchor> <a href="#clickedMe">click me</a>
Элемент
Onevent
Атрибуты:
type - Тип события, которое будет обрабатываться
Существует четыре типа событий:
onenterbackward
Сработает при выборе элемента "prev"
onenterforward
Сработает при вызове карты
onpick
Сработает при выборе опции в списке элемента "select"
ontimer
Сработает по истечении времени у элемента "timer".
<?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN""http://www.wapforum.com/DTD/wml_1.1.xml"> <wml> <card id="start"> <do type="accept"> <go href="two"/> </do> <p>Choose Accept.</p> </card> <card id="two"> <do type="accept"> <go href="three"/> </do> <onevent type="onenterbackward"> <prev/> </onevent> <p>Choose Accept</p> </card> <card id="three"> <do type="accept"> <prev/> </do> <p>Choose Accept.</p> </card> </wml>
Элемент
Access
Атрибуты:
domain - имя домена для запрета доступа. Микроброузер будет просматривать и сравнивать со значением этого атрибута все имена доменов встречающиеся в документе. Так если "<access domain="motorola.com"/>" броузер сможет зайти на "http://www.motorola.com/", но не сможет зайти на "http://www.rola.com/" или на "http://www.motorola.net/".
path - путь для сравнения. Работает примерно так же как и атрибут домен. Так если "<access path="/internal"/>" путь "/internal/wml" пройдет проверку, в то время как "/internal-wml" - нет.
Элемент "access" с примерно такими атрибутами: "<access domain="motorola.com" path="/spin"/>" разрешит ссылку на деку только со следующих адресов:
http://www.motorola.com/spin/getuid.cgi
https://www.motorola.com/spin/index.wml
http://www.motorola.com/spin/madk/create_index.cgi?x=123&y=234
А с этих запретит:
http://www.mot.com/spin/getuid.cgi
http://www.motorola.com/internal/spin/getuid.cgi
Элемент
Card
События:
onenterbackward
Сработает при выборе элемента "prev"
onenterforward
Сработает при вызове карты
ontimer
Сработает по истечении времени у элемента "timer".
Атрибуты:
id - атрибут, позволяющий сослаться на эту карточку из других элементов. Ссылка на карточку состоит из символа "#" и значения ее атрибута id (#nextcard).
title - значение этого атрибута может быть использовано для озаглавливания экрана, в котором отображается карточка, а также может появится в списке ранее посещенных страниц, а также в любом другом месте по усмотрению микроброузера.
newcontext - может быть использован для того, чтобы сбросить состояние деки. Этот атрибут может иметь значение "true" или "false".
ordered - сообщает микроброузеру принадлежит ли эта карта к упорядоченному списку карт или нет. Разработчики могут использовать этот атрибут по своему усмотрению и разрабатывать либо деку с последовательным просмотром карточек, либо состоящую из одной большой карточки.
Немного более сложная дека в качестве примера:
<?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 domain="motorola.com" path="/spin"/> </head> <template> <do type="accept" name="accept1" label="OK"> <go href="#accept"/> </do> </template> <card id="start" title="Start Here"> <p> Start Here. </p> </card> <card id="accept" title="Okay Card"> <do type="accept" name="accept1" label="Okay"> <go href="#accept2"/> </do> <p> Card Accept </p> </card> <card id="accept2" title="OK Card" > <do type="accept" > <go href="#start" /> </do> <p> Card Accept2 </p> </card> </wml>
Управляющими элементами в WML являются элементы "select" и "input". У каждого есть несколько подэлементов, а также механизм группировки, для приведения нескольких относящихся друг к другу элемементов ввода к одной логике. Также тут присутствует атрибут tabindex. этот атрибут определяет последовательность в которой происходит передвижение по элементам.
Элемент
Select
Атрибуты
multiple - по умолчанию равно "off". При включении этого атрибута пользователь может выбрать несколько элементов из предложенного списка.
name - обозначает имя переменной в которой будет храниться значение введенной в этом поле информации.
value - значение элемента по умолчанию.
iname - имя выбранного элемента(ов) списка. Значение "0" означает, что в списке нет элементов. Нумерация элементов списка начинается с "1" и постепенно увеличивается.
ivalue - имя переменной, в которой содержится значение(я) выбранных элементов списка. Несколько значений можно ввести, разделяя их ";", например (1;2) . Нельзя вводить пустое значение переменной. Так значение (1;;2) - неправильно.
title - заголовок. Указывается для того, что бы микроброузер определил тип навигационного элемента.
tabindex - очередь следования этого элемента относительно других. Реализация зависит от броузера.
Элемент:
Option
Атрибуты:
value - значение, присваемое переменной элемента select, в случае выбора этой опции
title - заголовок. В зависимости от микроброузера может не выводиться на экран.
onpick - URL на который пойдет микроброузер, в случае выбора этой опции.
Элемент:
Optgroup
Атрибуты:
title - заголовок. В зависимости от микроброузера может не выводиться на экран.
<?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> Bogus: <select name="bogus"> <optgroup title="one"> <option value="uno">uno</option> <option value="eins">eins</option> </optgroup> <optgroup title="two"> <option value="dos">dos</option> <option value="zwei">zwei</option> </optgroup> </select> </p> </card> </wml> <?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN""http://www.wapforum.org/DTD/wml_1.1.xml"> <wml> <template> <do type="options" label="Back"> <prev/> </do> </template> <card id="lists"> <p> <select title="Pick Lists"> <option onpick="#single">Single</option> <option onpick="#multiple">Multiple</option> </select> </p> </card> <card id="single"> <onevent type="onenterbackward"> <prev/> </onevent> <do type="accept"> <go href="#display_fav"/> </do> <p> Pick your fav Stooge: <select name="fav" title="Stooges"> <option value="Moe">Moe</option> <option value="Shemp">Shemp</option> <option value="Larry">Larry</option> <option value="Curley">Curley</option> <option value="Curley Joe">Curley Joe</option> </select> </p> </card> <card id="multiple"> <onevent type="onenterbackward"> <prev/> </onevent> <do type="accept"> <go href="#display_fav"/> </do> <p> Pick your fav Marx Bro. <select multiple="true" title="Marx Bros" name="fav" > <option value="Groucho">Groucho</option> <option value="Harpo">Harpo</option> <option value="Chico">Chico</option> <option value="Zeppo">Zeppo</option> </select> </p> </card> <card id="display_fav"> <p> Your fav was $fav. </p> </card> </wml>
Элемент:
Input
Атрибуты:
name - то же, что и в элементе select. обозначает имя переменной в которой будет храниться значение введенной в этом поле информации.
value - значение поля по-умолчанию.
type - имеет значение либо "text" либо "password". В зависимости от микроброузера поле типа "password" может отображаться на дисплее видимым текстом.
format - маска ввода.
A - Любая буква в верхнем регистре [A-Z]
a Любая буква в нижнем регистре и пунктуация [a-z]
N - любая цифра [0-9]
X - любой символ в верхнем регистре [A-Z,0-9]
x - любой символ в нижнем регистре [a-z,0-9]
M - любой символ
m - любой символ
*f - любое количество символов определенного формата, например *N -любое количество цифр
nf - "n" это целое число так например "3A" означает 3 буквы в верхнем регистре или пунктуации.
\c - символ ввода, так например "\(3N\)\ \3N\-4N" означает номер телефона с кодом местности в американском формате.
emptytok - разрешает пустой ввод
size - ширина поля ввода. Реализация зависит от броузера.
Maxlength - определяет максимальное количество вводимых.
Title - заголовок, показывается броузером в некоторых случаях. Рекомендуется использовать атрибут title во всех элементах, которые им располагают, потому что в некоторых телефонах заполнение поля ввода реализовано в виде отдельного окошка, при этом title будет выводится в качестве напоминания, какое именно поле в настоящий момент заполняет пользователь.
Элемент:
Fieldset - Использование зависит от микроброузера.
Атрибуты:
title - Заголовок
<?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN""http://www.wapforum.org/DTD/wml_1.1.xml"> <wml> <template> <do type="options" label="Back"> <prev/> </do> </template> <card id="fields"> <p> Field Type: <select title="Field type"> <option onpick="#nested">Nested</option> <option onpick="#password">Password</option> </select> </p> </card> <card id="nested"> <onevent type="onenterbackward"> <prev/> </onevent> <do type="accept" label="Done"> <go href="#done"/> </do> <p> First Name: <input title="First" name="fname"/> Last Name: <input title="Last" name="lname"/> Gender: <select title="Gender" name="gender"> <option value="male">Male</option> <option value="female">Female</option> </select> </p> </card> <card id="done"> <p> $fname $lname is a $gender. </p> </card> <card id="password"> <onevent type="onenterbackward"> <prev/> </onevent> <do type="accept" label="Done"> <go href="#passwd_done"/> </do> <p> Input a password:<br/> Min 3 chars. <input title="Password" name="passwd" type="password" format="*m"/> </p> </card> <card id="passwd_done"> <p> Password was $passwd. </p> </card> </wml>
Элемент:
timer
Атрибуты:
value - промежуток времени в десятых долях секунды.
<?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="first" ontimer="#next"> <timer value="100"/> <p>Wait ten seconds</p> </card> <card id="next"> <timer value="10"/> <onevent type="timer"> <go href="#first"/> </onevent> <p>Подождите минутку</p> </card> </wml>
У элемента p нет атрибутов
У элемента br нет атрибутов