伊峰独居

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  30 随笔 :: 30 文章 :: 5 评论 :: 0 Trackbacks

 

  有许多技术可用于用 PHP 读取和编写 XML。本文提供了三种方法读取 XML:使用 DOM 库、使用 SAX 解析器和使用正则表达式。还介绍了使用 DOM 和 PHP 文本模板编写 XML。

  用 PHP 读取和编写可扩展标记语言(XML)看起来可能有点恐怖。实际上,XML 和它的所有相关技术可能是恐怖的,但是用 PHP 读取和编写 XML 不一定是项恐怖的任务。首先,需要学习一点关于 XML 的知识 —— 它是什么,用它做什么。然后,需要学习如何用 PHP 读取和编写 XML,而有许多种方式可以做这件事。

  本文提供了 XML 的简短入门,然后解释如何用 PHP 读取和编写 XML。

  什么是 XML?

  XML 是一种数据存储格式。它没有定义保存什么数据,也没有定义数据的格式。XML 只是定义了标记和这些标记的属性。格式良好的 XML 标记看起来像这样:

<name>Jack Herrington</name>

  这个 <name> 标记包含一些文本:Jack Herrington。

  不包含文本的 XML 标记看起来像这样:

<powerUp />

  用 XML 对某件事进行编写的方式不止一种。例如,这个标记形成的输出与前一个标记相同:

<powerUp></powerUp>

  也可以向 XML 标记添加属性。例如,这个 <name> 标记包含 first 和 last 属性:

<name first="Jack" last="Herrington" />

  也可以用 XML 对特殊字符进行编码。例如,& 符号可以像这样编码:

  &

  包含标记和属性的 XML 文件如果像示例一样格式化,就是格式良好的,这意味着标记是对称的,字符的编码正确。清单 1 是一份格式良好的 XML 的示例。

  清单 1. XML 图书列表示例


<books>
<book>
<author>Jack Herrington</author>
<title>PHP Hacks</title>
<publisher>O'Reilly</publisher>
</book>
<book>
<author>Jack Herrington</author>
<title>Podcasting Hacks</title>
<publisher>O'Reilly</publisher>
</book>
</books>

  清单 1 中的 XML 包含一个图书列表。父标记 <books> 包含一组 <book> 标记,每个 <book> 标记又包含 <author>、<title> 和 <publisher> 标记。

  当 XML 文档的标记结构和内容得到外部模式文件的验证后,XML 文档就是正确的。模式文件可以用不同的格式指定。对于本文来说,所需要的只是格式良好的 XML。

  如果觉得 XML 看起来很像超文本标记语言(HTML),那么就对了。XML 和 HTML 都是基于标记的语言,它们有许多相似之处。但是,要着重指出的是:虽然 XML 文档可能是格式良好的 HTML,但不是所有的 HTML 文档都是格式良好的 XML。换行标记(br)是 XML 和 HTML 之间区别的一个好例子。这个换行标记是格式良好的 HTML,但不是格式良好的 XML:

<p>This is a paragraph<br>
With a line break</p>

  这个换行标记是格式良好的 XML 和 HTML:

<p>This is a paragraph<br />
With a line break</p>

  如果要把 HTML 编写成同样是格式良好的 XML,请遵循 W3C 委员会的可扩展超文本标记语言(XHTML)标准(参见 参考资料)。所有现代的浏览器都能呈现 XHTML。而且,还可以用 XML 工具读取 XHTML 并找出文档中的数据,这比解析 HTML 容易得多。

  使用 DOM 库读取 XML

  读取格式良好的 XML 文件最容易的方式是使用编译成某些 PHP 安装的文档对象模型 (DOM)库。DOM 库把整个 XML 文档读入内存,并用节点树表示它,如图 1 所示。

  图 1. 图书 XML 的 XML DOM 树
图书 XML 的 XML DOM 树

  树顶部的 books 节点有两个 book 子标记。在每本书中,有 author、publisher 和 title 几个节点。author、publisher 和 title 节点分别有包含文本的文本子节点。

  读取图书 XML 文件并用 DOM 显示内容的代码如清单 2 所示。

  清单 2. 用 DOM 读取图书 XML


<?php
$doc = new DOMDocument();
$doc->load( 'books.xml' );

$books = $doc->getElementsByTagName( "book" );
foreach( $books as $book )
{
$authors = $book->getElementsByTagName( "author" );
$author = $authors->item(0)->nodeValue;

$publishers = $book->getElementsByTagName( "publisher" );
$publisher = $publishers->item(0)->nodeValue;

$titles = $book->getElementsByTagName( "title" );
$title = $titles->item(0)->nodeValue;

echo "$title - $author - $publisher\n";
}
?>


  脚本首先创建一个 new DOMdocument 对象,用 load 方法把图书 XML 装入这个对象。之后,脚本用 getElementsByName 方法得到指定名称下的所有元素的列表。

  在 book 节点的循环中,脚本用 getElementsByName 方法获得 author、publisher 和 title 标记的 nodeValue。nodeValue 是节点中的文本。脚本然后显示这些值。

  可以在命令行上像这样运行 PHP 脚本:

% php e1.php
PHP Hacks - Jack Herrington - O'Reilly
Podcasting Hacks - Jack Herrington - O'Reilly
%

  可以看到,每个图书块输出一行。这是一个良好的开始。但是,如果不能访问 XML DOM 库该怎么办?

  用 SAX 解析器读取 XML

  读取 XML 的另一种方法是使用 XML Simple API(SAX)解析器。PHP 的大多数安装都包含 SAX 解析器。SAX 解析器运行在回调模型上。每次打开或关闭一个标记时,或者每次解析器看到文本时,就用节点或文本的信息回调用户定义的函数。

  SAX 解析器的优点是,它是真正轻量级的。解析器不会在内存中长期保持内容,所以可以用于非常巨大的文件。缺点是编写 SAX 解析器回调是件非常麻烦的事。清单 3 显示了使用 SAX 读取图书 XML 文件并显示内容的代码。

  清单 3. 用 SAX 解析器读取图书 XML


<?php
$g_books = array();
$g_elem = null;

function startElement( $parser, $name, $attrs )
{
global $g_books, $g_elem;
if ( $name == 'BOOK' ) $g_books []= array();
$g_elem = $name;
}

function endElement( $parser, $name )
{
global $g_elem;
$g_elem = null;
}

function textData( $parser, $text )
{
global $g_books, $g_elem;
if ( $g_elem == 'AUTHOR'
$g_elem == 'PUBLISHER'
$g_elem == 'TITLE' )
{
$g_books[ count( $g_books ) - 1 ][ $g_elem ] = $text;
}
}

$parser = xml_parser_create();

xml_set_element_handler( $parser, "startElement", "endElement" );
xml_set_character_data_handler( $parser, "textData" );

$f = fopen( 'books.xml', 'r' );

while( $data = fread( $f, 4096 ) )
{
xml_parse( $parser, $data );
}

xml_parser_free( $parser );

foreach( $g_books as $book )
{
echo $book['TITLE']." - ".$book['AUTHOR']." - ";
echo $book['PUBLISHER']."\n";
}
?>

  脚本首先设置 g_books 数组,它在内存中容纳所有图书和图书信息,g_elem 变量保存脚本目前正在处理的标记的名称。然后脚本定义回调函数。在这个示例中,回调函数是 startElement、endElement 和 textData。在打开和关闭标记的时候,分别调用 startElement 和 endElement 函数。在开始和结束标记之间的文本上面,调用 textData。

  在这个示例中,startElement 标记查找 book 标记,在 book 数组中开始一个新元素。然后,textData 函数查看当前元素,看它是不是 publisher、title 或 author 标记。如果是,函数就把当前文本放入当前图书。

  为了让解析继续,脚本用 xml_parser_create 函数创建解析器。然后,设置回调句柄。之后,脚本读取文件并把文件的大块内容发送到解析器。在文件读取之后,xml_parser_free 函数删除解析器。脚本的末尾输出 g_books 数组的内容。

  可以看到,这比编写 DOM 的同样功能要困难得多。如果没有 DOM 库也没有 SAX 库该怎么办?还有替代方案么?

  用正则表达式解析 XML

  可以肯定,即使提到这个方法,有些工程师也会批评我,但是确实可以用正则表达式解析 XML。清单 4 显示了使用 preg_ 函数读取图书文件的示例。

  清单 4. 用正则表达式读取 XML

<?php
$xml = "";
$f = fopen( 'books.xml', 'r' );
while( $data = fread( $f, 4096 ) ) { $xml .= $data; }
fclose( $f );

preg_match_all( "/\<book\>(.*?)\<\/book\>/s",
$xml, $bookblocks );

foreach( $bookblocks[1] as $block )
{
preg_match_all( "/\<author\>(.*?)\<\/author\>/",
$block, $author );
preg_match_all( "/\<title\>(.*?)\<\/title\>/",
$block, $title );
preg_match_all( "/\<publisher\>(.*?)\<\/publisher\>/",
$block, $publisher );
echo( $title[1][0]." - ".$author[1][0]." - ".
$publisher[1][0]."\n" );
}
?>

  请注意这个代码有多短。开始时,它把文件读进一个大的字符串。然后用一个 regex 函数读取每个图书项目。最后用 foreach 循环,在每个图书块间循环,并提取出 author、title 和 publisher。

  那么,缺陷在哪呢?使用正则表达式代码读取 XML 的问题是,它并没先进行检查,确保 XML 的格式良好。这意味着在读取之前,无法知道 XML 是否格式良好。而且,有些格式正确的 XML 可能与正则表达式不匹配,所以日后必须修改它们。

  我从不建议使用正则表达式读取 XML,但是有时它是兼容性最好的方式,因为正则表达式函数总是可用的。不要用正则表达式读取直接来自用户的 XML,因为无法控制这类 XML 的格式或结构。应当一直用 DOM 库或 SAX 解析器读取来自用户的 XML。

  用 DOM 编写 XML

  读取 XML 只是公式的一部分。该怎样编写 XML 呢?编写 XML 最好的方式就是用 DOM。清单 5 显示了 DOM 构建图书 XML 文件的方式。

   清单 5. 用 DOM 编写图书 XML


<?php
$books = array();
$books [] = array(
'title' => 'PHP Hacks',
'author' => 'Jack Herrington',
'publisher' => "O'Reilly"
);
$books [] = array(
'title' => 'Podcasting Hacks',
'author' => 'Jack Herrington',
'publisher' => "O'Reilly"
);

$doc = new DOMDocument();
$doc->formatOutput = true;

$r = $doc->createElement( "books" );
$doc->appendChild( $r );

foreach( $books as $book )
{
$b = $doc->createElement( "book" );

$author = $doc->createElement( "author" );
$author->appendChild(
$doc->createTextNode( $book['author'] )
);
$b->appendChild( $author );

$title = $doc->createElement( "title" );
$title->appendChild(
$doc->createTextNode( $book['title'] )
);
$b->appendChild( $title );

$publisher = $doc->createElement( "publisher" );
$publisher->appendChild(
$doc->createTextNode( $book['publisher'] )
);
$b->appendChild( $publisher );

$r->appendChild( $b );
}

echo $doc->saveXML();
?>

  在脚本的顶部,用一些示例图书装入了 books 数组。这个数据可以来自用户也可以来自数据库。

  示例图书装入之后,脚本创建一个 new DOMDocument,并把根节点 books 添加到它。然后脚本为每本书的 author、title 和 publisher 创建节点,并为每个节点添加文本节点。每个 book 节点的最后一步是重新把它添加到根节点 books。

  脚本的末尾用 saveXML 方法把 XML 输出到控制台。(也可以用 save 方法创建一个 XML 文件。)脚本的输出如清单 6 所示。

清单 6. DOM 构建脚本的输出

% php e4.php
<?xml version="1.0"?>
<books>
<book>
<author>Jack Herrington</author>
<title>PHP Hacks</title>
<publisher>O'Reilly</publisher>
</book>
<book>
<author>Jack Herrington</author>
<title>Podcasting Hacks</title>
<publisher>O'Reilly</publisher>
</book>
</books>
%

  使用 DOM 的真正价值在于它创建的 XML 总是格式正确的。但是如果不能用 DOM 创建 XML 时该怎么办?

  用 PHP 编写 XML

  如果 DOM 不可用,可以用 PHP 的文本模板编写 XML。清单 7 显示了 PHP 如何构建图书 XML 文件。

清单 7. 用 PHP 编写图书 XML

<?php
$books = array();
$books [] = array(
'title' => 'PHP Hacks',
'author' => 'Jack Herrington',
'publisher' => "O'Reilly"
);
$books [] = array(
'title' => 'Podcasting Hacks',
'author' => 'Jack Herrington',
'publisher' => "O'Reilly"
);
?>
<books>
<?php

foreach( $books as $book )
{
?>
<book>
<title><?php echo( $book['title'] ); ?></title>
<author><?php echo( $book['author'] ); ?>
</author>
<publisher><?php echo( $book['publisher'] ); ?>
</publisher>
</book>
<?php
}
?>
</books>

  脚本的顶部与 DOM 脚本类似。脚本的底部打开 books 标记,然后在每个图书中迭代,创建 book 标记和所有的内部 title、author 和 publisher 标记。

  这种方法的问题是对实体进行编码。为了确保实体编码正确,必须在每个项目上调用 htmlentities 函数,如清单 8 所示。

清单 8. 使用 htmlentities 函数对实体编码

<books>
<?php

foreach( $books as $book )
{
$title = htmlentities( $book['title'], ENT_QUOTES );
$author = htmlentities( $book['author'], ENT_QUOTES );
$publisher = htmlentities( $book['publisher'], ENT_QUOTES );
?>
<book>
<title><?php echo( $title ); ?></title>
<author><?php echo( $author ); ?> </author>
<publisher><?php echo( $publisher ); ?>
</publisher>
</book>
<?php
}
?>
</books>

  这就是用基本的 PHP 编写 XML 的烦人之处。您以为自己创建了完美的 XML,但是在试图使用数据的时候,马上就会发现某些元素的编码不正确。

  结束语

  XML 周围总有许多夸大之处和混淆之处。但是,并不像您想像的那么难 —— 特别是在 PHP 这样优秀的语言中。在理解并正确地实现了 XML 之后,就会发现有许多强大的工具可以使用。XPath 和 XSLT 就是这样两个值得研究的工具。




添加评论
单击隐藏此项的评论。

[转贴]DOM知识的翻译与整理

先来看一张简单的文档树

很明显树的顶层节点是NodeA节点,接下来可以通过指定的合适节点移动到树中的任何点,结合以下的代码你可以更好的了解这棵树节点间的相互关系:
NodeA.firstChild = NodeA1
NodeA.lastChild = NodeA3
NodeA.childNodes.length = 3
NodeA.childNodes[0 ] = NodeA1
NodeA.childNodes[1] = NodeA2
NodeA.childNodes[2] = NodeA3
NodeA1.parentNode = NodeA
NodeA1.nextSibling = NodeA2
NodeA3.prevSibling = NodeA2
NodeA3.nextSibling = null
NodeA.lastChild.firstChild = NodeA3a
NodeA3b.parentNode.parentNode = NodeA

DOM定义对操作一个文档对象的节点结构提供了实用的方法,它提供了像执行对象插入,更新,删除,克隆等这些常用的方法
insertBefore()--在参考子节点之前插入一个新的子节点.如果参考的子节点为null,则新的子节点将作为调用节点的最后一个子节点插入
replaceChild()--在childNodes集合种使用指定的newChild来代替oldChild;如果代替成功,则返回oldChild;如果newChild是null,则只需删除oldChild即可
removeChild()--从节点的ChildNodes集合中删除removeChild指定的节点,如果删除成功,则返回删除的子节点
appendChild()--添加一个新节点到childNodes集合的末尾,如果成功,则返回新节点
cloneNode()--创建一个新的、复制的节点,并且如果传入的参数是true时,还将复制子节点,如果节点是一个元素,那么还将复制相应属性,返回新的节点

为了在一棵文档树中访问或者建立一个新的节点,可以用下面这些方法:
getElementById()
getElementsByTagName()
createElement()
createAttribute()
createTextNode()
注意:在一个页面中只有一个文档对象,除了getElementsByTagName()外,其它方法均只能通过document.methodName()调用.

再看一下下面这个例子:
<html>
<head>
<title></title>
</head>
<body>
<p>This is a sample paragraph.</p>
<SCRIPT LANGUAGE="JavaScript">
<!--
alert(document.documentElement.lastChild.firstChild.tagName);
//-->
</SCRIPT>
</body>
</html>

结果将会显示"P",下面是一些解释
document.documentElement - gives the page's HTML tag.
lastChild - gives the BODY tag.
firstChild - gives the first element in the BODY.
tagName - gives that element's tag name, "P" in this case.
另一个:

<html>
<head>
<title></title>
</head>
<body>

<p>This is a sample paragraph.</p>
<SCRIPT LANGUAGE="JavaScript">
<!--
alert(document.documentElement.lastChild.firstChild.tagName);
//-->
</SCRIPT>
</body>
</html>

这个例子和上面并没有什么大的区别,仅仅是多了一个空行,但是在NS中,会自动为空行加上一个节点所以返回值是"undefined",而在IE中将跳过空行仍然指向P标签

更常用的方法:
<p id="myParagraph">This is a sample paragraph.</p>

...

alert(document.getElementById("myParagraph").tagName);
这种方法你不用关心节点在文档树的哪一个地方,而只要保证在页面中它的ID号是唯一的就可以了

接下来一种访问元素节点的方法是document.getElementsByTagName(),它的返回值是一个数组,例如你可以通过下面的例子改变整个页面的连接
var nodeList = document.getElementsByTagName("A");
for (var i = 0; i < nodeList.length; i++)
nodeList[i].style.color = "#ff0000";

attribute和attributes
attribute对象和元素相关,但是却没有被认为是文档树的一部分,因此属性不能作为子节点集合的一部分来使用.
有三种方法可以为元素建立新的属性
1.
var attr = document.createAttribute("myAttribute");
attr.value = "myValue";
var el = document.getElementById("myParagraph");
el.setAttributeNode(attr);
2.
var el = document.getElementById("myParagraph");
el.setAttribute("myAttribute", "myValue");
3.
var el = document.getElementById("myParagraph");
el.myAttribute = "myValue";
你可以在html标签种定义自己的属性:
<p id="myParagraph" myAttribute="myValue">This is a sample paragraph.</p>

...

alert(document.getElementById("myParagraph").getAttribute("myAttribute"));
返回值将是"myValue".但是请注意这里必须使用getAttribute,而不是AttributeName,因为有一些浏览器并不支持自定义属性

attributes也可以被轻易的从一个元素中删除,你可以使用removeAttribute()或者将element.attributeName指向一个null值.
通过attributes我们就可以产生一些动态效果:
<p id="sample1" align="left">Text in a paragraph element.</p>

... code for the links ...

document.getElementById('sample1').setAttribute('align', 'left');
document.getElementById('sample1').setAttribute('align', 'right');
另一种:
<p id="sample2" style="text-align:left;">Text in a paragraph
element.</p>

... code for the links ...

document.getElementById('sample2').style.textAlign = 'left';
document.getElementById('sample2').style.textAlign = 'right';
跟上面的例子一样,展示了可用通过元素修改style中的属性,甚至是class中的.唯一要提到的是textAlign是从style中的text- align中演变而来的,有一条基本规律,就是style中的属性如果出现-则在dom中将会被去掉并且随后的一个字母将改为大写,还有一点就是如果即使元素中没有style属性,上述例子同样可以使用

text nodes:
先看一下例子
<p id="sample1">This is the initial text.</p>

... code for the links ...

document.getElementById('sample1').firstChild.nodeValue =
'Once upon a time...';
document.getElementById('sample1').firstChild.nodeValue =
'...in a galaxy far, far away';
首先text nodes并没有像elements那样具有id属性,所有它并不能直接通过document.getElementById()或者document.getElementsByTagName()访问
看一下下面的结构也许会更明白一些

可以看出通过document.getElementById('sample1').firstChild.nodeValue就可以读取或者设置text nodes的值了

另一个更加复杂一点的例子
<p id="sample2">This is the <b>initial</b> text.</p>
它的文档结构

在这里通过document.getElementById('sample1').firstChild.nodeValue讲仅仅改变"This is the"
initial text.将不会改变.在这里大家应该看到了它和innerHTML的不同了.当然你也可以这样用
document.getElementById('sample3').firstChild.nodeValue =
'<b>Once</b> upon a time...';
document.getElementById('sample3').firstChild.nodeValue =
'...in a galaxy <i>far, far</i> away';
其中的html代码将不会被解释,浏览器将把他们当成普通的文本来显示

创建和删除text nodes:
var myTextNode = document.createTextNode("my text");
通过上面的代码你可以创建一个新的text node,但是它并不是文档树的一部分,要让它显示在页面上就必须让它成为文档树中某一个节点的child,因为
text nodes不能有儿子,所以你不能将它加入到一个text nodes中,attribute也不属于文档树的一部分,这条路也不行,现在只剩下elements nodes
了,以下的例子展示了如何添加和删除一个text node
<p id="sample1">Initial text within a paragraph element.</p>

... code to add a text node ...

var text = document.createTextNode(" new text " + (++counter1));
var el = document.getElementById("sample1");
el.appendChild(text);

... code to remove the last child node ...

var el = document.getElementById("sample1");
if (el.hasChildNodes())
el.removeChild(el.lastChild);
增加文本是很容易的,上面的代码建立了一个新的text node并且通过appendChild()方法将其加入到childNodes数组的末尾,并设置了一个counter1的全局变量,利于观察
hasChildNodes()的返回值是true or false;用来判断当前节点是否还有child,以阻止当其没有child的时候调用removeChild()产生的错误

创建element nodes
有了上面的基础,应该更容易理解了,先看一下下面的代码
<div id="sample1">This text is in a DIV element.</div>

... code for the link ...

var paraEl, boldEl;

paraEl = document.createElement("p");
boldEl = document.createElement("b");
paraEl.appendChild(document.createTextNode("This is a new paragraph with "));
boldEl.appendChild(document.createTextNode("bold"));
paraEl.appendChild(boldEl);
paraEl.appendChild(document.createTextNode(" text added to the DIV"));
document.getElementById("sample1").appendChild(paraEl);
你还可以直接为新加的element nodes设置attribute,以下两种都可以:
boldEl.style.color = "#ffff00";
paraEl.appendChild(boldEl);
或者:
paraEl.appendChild(boldEl);
boldEl.style.color = "#ffff00";

注:此文主要来自于一些英文资料和身边的一些参考书,如果有错误大家请指出,一起讨论,DOM我一点也不熟.


转自:http://www.blueidea.com/tech/program/2003/334.asp

添加评论
单击隐藏此项的评论。
7月10日

[转贴]给希望做程序员的应届毕业生的一些建议

    这几个月,不断的看到网站上关于计算机专业的应届毕业生的就业、未来和工作能力的讨论,有很多的感想,面试了不少的毕业生,简历看了几百份,了解、熟悉、精通等等的副词就不说了,实际编程能力都比较有限,上网聊天玩游戏水平比较高。这些都是事实,然而,如何快速的融入公司的开发工作中?不断的学习和实践。
    最近不断的有应届毕业生到公司实习,对于问题的接受能力,有的快些,有的慢些,学习新知识的能力也不同,但是有时候给我的印象比较深刻,看书看的很卖力,实际编程却总是不理想。后来跟一个毕业生聊天,他说:看的东西老是记不住。还有的在看VC的书,一边看一遍记笔记,他说这样加深印象,可以记住,将来编程的时候不至于不知道怎么写代码,远远的看过去,给人的感觉好想要考研究生。
    我不知到其人是如何学习新知识的,我个人觉得,上大学与工作之后学习的方式有很大的不同,上大学,为了考试,很多东西需要记住,毕业以后,知道到哪里查找资料就可以了,没有必要刻意记住一些细节。当然,能记住细节固然好,但是不要被细节搞成了苦行僧。
    看程序的代码是一个很好的学习方式,对于同样的代码,初学者关注的可能是一些系统函数的使用方法,数据类型的使用,派生和继承的关系和作用,重载的效果。对于具备了一定的编程经验之后,不再特别关注代码中的函数,变量,类的定义和使用,更多关注的是代码的设计的思路,设计思想,模块之间的关系,模块之间的接口等等。关键是理解,理解之后,自然就会记住。
    MFC中有很多的类和很多的函数,还有很多与标准C++不一样的数据类型,有必要全部记住吗?只需要记住一些基本的常用的就可以了如VC中的 CString,CDialog,CDocument,CView,AWinApp,CMDIFrameWnd,CButton,CEdit, CListBox,CComboBox,CTreeCtrl等等,这些类必须知道他们是干什么的,有什么用途,具体的使用可以看帮助, AfxMessageBox,try catch,TRACE,LPCTSTR,UINT,DWORD,WPARAM,LPARAM,SendMessage等等也是需要记住的,这些都是编写 VC程序经常用到的。没有必要记住太多,关键是学会使用MSDN,将主要的精力放在代码的设计上,不知道一个函数如何调用没有关系,知道如何使用F1键就够了。MSDN上没有可以到CSDN上搜搜,或者到Codeproject上看看。
    不要一直埋头写代码,抽时间到一些技术网站上看看,知道哪里有什么样的资料,或许有一天,你知道到哪里查找有关的信息,学会利用互联网上的免费资源。
    不要总是加班,不要抽太多的烟,程序员不是吃青春的,除非你自己选择吃青春饭。bill gates比我们的年龄大,单却是微软的首席软件设计师,从事Windows底层设计的人肯定不是20多岁的小伙子。中国软件的发展也不能靠吃青春饭。
    学会与同事交流和协作,是一个优秀的团队成员最基本的素质。JAVA的流行,一个非常重要的原因是java语言可以平台,通过java写的程序,记可以在 windows下运行,还可以在Linux或UNIX下运行,java是一个非常优秀的语言。一个优秀的程序员没有必要掌握一种跨平台的语言,然而,他自身必须具备一种“跨平台”的能力,这就是团队精神和合作意识,这一种能力,到任何一个公司,任何一个项目组,任何一个团队,无论他们使用Windows、 Linux还是Unix,无论是开发CS结构的程序还是开发BS结构的程序,也无论开发硬件还是软件,都是最重要的最受欢迎的一种能力。我对我们公司的实习生讲,如果谁把自己封闭起来,相互之间不帮助,不团结,首先会出局。
    经常在网上看到关于学习什么语言的讨论,什么样的语言最有前途,什么语言容易学,什么语言工资高等等。个人认为,对于应届毕业生,在公司的产品开发中不起主导作用,基本上没有权力选择语言,除非你离开公司,因为公司的已有的产品或项目决定了使用什么语言,或者是产品的主要的开发人员决定了使用什么语言,所以你只有接受。但是这有什么关系吗?应该使用什么语言,你参与的产品使用什么语言,那你就使用什么语言,具体学习什么语言不是特别重要,最重要的是在实践中学习一种好的设计思想,用计算机语言思考问题,学会对现实问题的抽象和概况,学会用一种计算机的模型来描述现实世界中的东西。经过一段时间之后,你对一门语言非常熟悉了,再看其他的语言,觉得都很相似,都有if else ,for,while,=,>.<,Stirng,class,try catch等等类似的东西,也有很多的差别,你再学习一个新的语言就非常容易了。当然,很多情况下我们会接触几种语言。我和同事一直使用VC,最近使用 C#写了个实现事务预约的程序,3个星期,程序测试通过,现蒸现卖,还不错。
    上面文字仅是个人的理解,仅供参考。
添加评论
单击隐藏此项的评论。

关于函数的自定义属性

JavaScript中的函数有许多内置属性,比如说length(取得函数参数的个数),prototype(取得Function对象建立的事例的原形对象)。
而对于函数我们也可以自定义属性,函数声明在代码执行之前处理
 
// Create and initialize the "static" variable.
// Function declarations are processed before code is executed, so
// we really can do this assignment before the function declaration.
uniqueInteger.counter = 0;
 
// Here's the function. It returns a different value each time
// it is called and uses a "static" property of itself to keep track
// of the last value it returned.
function uniqueInteger(  ) {
    // Increment and return our "static" variable
    return uniqueInteger.counter++;
}
document.write(uniqueInteger());
document.write(uniqueInteger());
 
输出结果为:
0
1
为什么不是两个0呢?因为函数的属性可以保存/修改值,所以可以看成是一个全局变量。
添加评论
单击隐藏此项的评论。

异常处理机制

JavaScript中使用try/catch/finally语句来进行异常的捕获及处理,这点和Java中的异常处理有点想象。
for example:
 
function exception(x)
{
 if(x<0) throw new Error("您输入的数字是负数");/*调用错误对象,当然你也可以调用自己想用的任何对象,比如说new String("字符串")等等。*/
 else
 alert(x);
}
 
//异常处理开始
try {
 tp = prompt("输入一个正数","");
 exception(tp);
}
catch(ex) {//将异常对象引用给变量ex
 alert(ex);//处理异常
}
finally {
 alert("处理完毕");//finally语句不管在什么情况下都会运行,它和catch属于可选语句。
}
 
添加评论
单击隐藏此项的评论。
7月7日

JavaScript学习(六)

JavaScript中存在两种数据类型,分别是基本类型引用类型数值、布尔值、NULL、未定义值(undefined)属于基本类型数组、对象、函数则属于引用类型。对于基本类型,JavaScript分配8个字节的空间;而对于引用类型由于是动态的,没有固定大小,因此不能直接分配空间,而是使用引用来指向内存地址,虽然引用不是数据本身,但是指向了存储的位置,这点和C中的指针以及Java中的引用很相似。

考虑以下代码:

var a=1;//定义并初始化
var b=a;//把变量a的值复制给b
a=2;//改变了a的值,并没有改变b的值
document.write(b);

输出结果:
1


再看以下代码:

var a=[1,2,3,4];
var b=a;//将地址引用复制到新的变量b
b[0]=100;//都是指向同一个 位置
document.write(a);

输出结果:
100,2,3,4

注意到字符串(String)不属于上面两种数据类型,这是因为一方面字符串具有可变的大小(因此不属于基本类型);另一方面又具有和基本数据类型很相似的表现。虽然是引用地址,但不能改变字符串的值。因此无论是将String看成是基本数据类型还是引用类型都是可以的。
添加评论
单击隐藏此项的评论。

JavaScript学习(五)

变量的作用域

在JavaScript中,声明变量使用var,如果不使用var,那么这个变量将会是全局变量,在函数中也是一样

function test()
{
    a=10;
    var b=20;
}
test();
document.write(a);
document.write(b);

输出结果为:
10
undefined

*在函数中声明的局部变量在整个函数中都有定义*

还有一个值得注意的地方
var var1 = 100;
function test()
{
    alert(var1);
    var var1 = 11;//initialized here,but define everywhere.这里初始化,但是在函数的内部到处都定义了。
}
test();

输出结果为:
undefined
为什么会是undefined而不是我们所期望的100 呢?原因是由于在函数中声明或者初始化的局部变量在整个函数中都有定义,因而同名的全局变量被隐藏了,那么上面的代码等同于下面的:
var var1 = 100;
function test()
{
    var var1;
    alert(var1);
    var1 = 11;//initialized here,but define everywhere.这里初始化,但是在函数的内部到处都定义了。
}
test();

为了避免这样的问题,我们可以在函数中将所有要声明的变量集中放在开头


再来看一下,循环,控制语句中的变量。在函数中它们的作用范围是整个函数,而不是单独的块级变量

function test(o) {

var i = 0; // i is defined throughout function

if (typeof o == "object") {

var j = 0; // j is defined everywhere, not just block

for(var k = 0; k < 10; k++) { // k is defined everywhere, not just loop

document.write(k);

}

document.write(k); // k is still defined: prints 10

}

document.write(j); // j is defined, but may not be initialized

}
test(new Object());

输出结果为:
0
1
2
3
4
5
6
7
8
9
10
0


添加评论
单击隐藏此项的评论。
7月6日

JavaScript学习(四)

对象
JavaScript中内置了很多对象,通过JavaScript与Html交互就是对DOM的操作,比如window就是一个对象,document也是一个对象等等。

访问一个对象的属性和方法很简单,直接使用点(.)来访问,比如:document.write()方法,str.length属性等等。
另外我们在访问对象的属性时候还可以通过数组的形式来访问。比如有个对象image,有两个属性width,height,那么我们除了可以使用image.width和image.height来访问image对象的width和height之外,还可以使用image["width"]和image["height"]来访问

注意:仅仅用在对象的属性上面,不可用在对象方法上。

建立对象的方法有:
var1={x:1,y:2,z:3};

也可以套嵌
var1={lst1:{x:1,y:2},lst2:{z:3,o:4}};

//循环输出
for(it in var1)
{
for(rt in var1[it])
{
document.write(var1[it][rt]);
}
}
输出结果为:
1
2
3
4

最后还有一种创建对象的方法就是利用Object对象
var1 = new Object() //建立一个对象
var1.lft = "left"; //开始分配属性
var1.rht = "right";

document.write(var1.lft);
document.write(var1.rht);
for(it in var1)
document.write(var1[it]);

输出结果:

left
right
left
right

添加评论
单击隐藏此项的评论。

JavaScript学习(三)

小议JavaScript中的函数

var test1 = function(a)//定义函数的非常规方法
{
    return(a);
}

function test2(b)//定义函数的常规方法
{
    return(b);
}


var test3 = new Function("c","return(c);");//非常规定义函数的方法

alert(test1("fuc1"));
alert(test2("fuc2"));
alert(test3("fuc3"));

我们用的最频繁的函数定义方法就是第二种了。

添加评论
单击隐藏此项的评论。

JavaScript学习(二)

接着讨论数组,先看一个例子
//arr = new Array("one","two","three");
arr = ["one","two","three"];
document.write(arr);

输出结果为:
one,two,three
注意到数组直接输出是以逗号(,)连接起来的。

好了,数组差不多就这些了,再看字符串

arr = "four";
for(it in arr)
document.write(arr[it]);

输出结果:
f
o
u
r

注意到字符串也可以利用索引来访问单个的字符

字符串有很多方法和属性,这些方法和属性是继承了基类的,比如length属性就是取得字符串的长度

length属性

str="hello world";
document.write(str.length);

输出结果为:
11

我们再看

str="你好";
document.write(str.length);

输出结果为:
4
为什么呢?这是因为汉字是有两个字节构成的,一个汉字当作两个字符来处理。

charAt(num)方法
描述:取得指定位置num的单个字符,注意索引从0开始,和利用字符串数组的性质一样。

str="hello world";
document.write(str.charAt(str.length - 3));

输出结果为:
r

substring(start,end)方法
描述:取得从start开始的end-start个子字符串。

str="hello world";
document.write(str.substring(1,4));

输出结果为:
ell

再看个例子:
str="你好";
document.write(str.substring(0,2));

输出结果为:


如果改一下的话
str="你好";
document.write(str.substring(0,3));

输出结果为(想想都知道是乱码了):
你??????矍獋矍???

只要注意一下汉字的2个字节性质就清楚了。

indexOf(string str)方法
描述:取得字符串str第一次出现的位置

str="hello world";
document.write(str.indexOf("wo"));

输出结果为:
6


提示:
我们注意到字符串采用了类似对象的格式来访问基类的属性和方法,但是这并不意味着字符串在JavaScript是对象。实际上字符串是一种特殊的数据类型,它使用对象的语法格式来访问相应的属性和方法,但它本身并不是对象。
添加评论
单击隐藏此项的评论。

JavaScript学习

//正常的定义数组的格式为
arr = new Array("one","two","three","four");//define a new array object
document.write(arr[0]);//index from 0;
document.write(arr[1]);
document.write(arr[2]);
document.write(arr[3]);

//use for...in retrieving all array elements
for(it in arr)
document.write(arr[it]);

//也可以定义复杂的数组,带有自定义索引的
rarr = ["one","two","three","four"];//注意创建的方式
for(it in rarr)
document.write("rarr[\""+it+"\"] = "+rarr[it]);


//JavaScript中,对象可以作为数组来被访问,其中数组索引从0开始,举个例子:
function class_test()//定义一个类(在这里其实就是一个函数)
{
   this.var1 = 1;//不需要声明,直接赋值即可
   this.var2 = 2;
   this.var3 = 3;
   //....
   //必须使用this来指定对象属性(变量)。
}

ct1= new class_test();//创建一个对象
document.write(ct1['var1']);//通过索引来访问,这里的索引就是对象中的属性(变量)

for(it in ct1)//或者也可以通过for in的形式来遍历对象
document.write("ct1[\""+it+"\"] = "+ct1[it]);


/*
结果为
one
two
three
four
one
two
three
four
rarr["a"] = one
rarr["b"] = two
rarr["c"] = three
rarr["d"] = four
1
ct1["var1"] = 1
ct1["var2"] = 2
ct1["var3"] = 3
*/





//note the follow code
arr = {"a":"one","b":"two","c":"three"};//初始化对象
arr[0] = "four";//插入一个元素,注意必须指派一个索引    可以是数字或者字符串
for(it in arr)
document.write(arr[it]);
arr["a"] = "a";//更改一个元素项
for(it in arr)
document.write(arr[it]);

/*
输出结果
one
two
three
four
a
two
three
four
*/


arr = {"a":"one","b":"two","c":"three"};
arr = "four";//此时重定义了arr,变成了字符串,注意字符串也可以通过索引来访问单个字符
for(it in arr)
document.write(arr[it]);

/*
输出结果
f
o
u
r
*/
添加评论
单击隐藏此项的评论。
7月5日

WAP初级教程(六)

WAP初级教程(6)—事件EVENT

[日期:2004-10-23] 来源:破釜沉舟  作者: [字体:]
事件 (EVENT)
·  <anchor> 链接 ·  <onevent> 固有事件 ·  <timer> 计时器 ·  <do> 用户触发事件
·  DECK级事件      

任务不能在真空中生存,它们必须绑定倒某个事件上才能做一些有用的事情。事件发生--〉任务执行,这才是完整的进程控制。

有4个元素可以帮助你完成事件对任务的绑定:<anchor>、<onevent>、<timer>和<do>。

<anchor> 链接
象HTML一样,WML也可以定义到其他程序的链接。在HTML中,链接通常用下划线和特殊颜色的方式表示跟其他内容的区别。在WAP终端上则没有严格的规则说如何表示一个链接,一般采用反白的显示方式。

<anchor>的语法如下:

<anchor
   title="STRING"
   xml:lang="STRING"
>
  <br>, <go>, <img>, <prev>, <refresh>, TEXT
</anchor>

title:链接的标题;
xml:lang:语言编码。

在这种定义方式中,实际上链接一般是通过<anchor>中包括的<go>元素完成的。比如下面的例子定义了2个CARD,点击第一个CARD里的“click me”链接会跳转到第2个CARD:

<?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="Hello" title="Hello">
  <p>Hello,
  <anchor>click me
   <go href="#bye"/>
  </anchor>
  </p>
</card>

<card id="bye" title="Bye">
  <p>Bye, guys</p>
</card>
</wml>

点击前显示:点击后显示:
------- Hello -------
Hello,

-------- bye --------
Bye, guys

链接还有一种短格式,语法如下:

<a
   href="STRING"
   title="STRING"
   xml:lang="STRING"
>
  <br>, <img>, TEXT
</a>

除了跟原来一样的两个属性以外,多了href属性,可以对它直接指定URL。例如下面的例子定义了一个带有图像的链接:

<a title="HotBars" href="wap.hucn.com/HotBars.wml">
  <img src="hot.wbmp" alt="Hot Bars" />
</a>

除了跟原来一样的两个属性以外,多了href属性,可以对它直接指定URL。

<onevent> 固有事件[TOP]
WML定义了4种由用户终端触发的固有事件:

oneventforward:当用户被<go>任务或其他机制(如一个SCRIPT过程)引导到一个CARD时触发;
oneventbackward:当用回被<prev>或其他机制(如在设备上按BACK按钮)引导到一个CARD时触发;
ontimer:当TIMER计时结束时触发。定义TIMER计时器可以使用<timer>元素,见下一节;
onpick:当用户按下一个<option>选项时触发(可以是选中或取消选择)。

把这些事件绑定到一个任务要使用<onevent>元素,它的语法如下:

<onevent
  type="oneventforward | oneventbackward | ontimer | onpick"
>
  <go>, <noop>, <prev>, <refresh>
</onevent>

下面的例子演示了如何使用固有事件在CARD调入时清空变量。

<?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">
  <onevent type="oneventforward">
  <refresh>
   <setvar name="firstname" value=""/>
   <setvar name="lastname" value=""/>
  </refresh>
  </onevent>
  <p>
   You have no name!
  </p>
</card>
</wml>

<timer> 计时器[TOP]
看名字就知道,这是个计时器,它在经过规定的计时时间以后产生一个任务。<timer>计时器只在所属CARD里有效:当进入CARD时,计时器开始工作;时间一到,触发任务;如果离开CARD,计时器停止。语法如下:

<timer
 name="STRING"
  value="NUMBER"
/>

name:可选。指定一个包含计时时间的变量,在计时器开始工作以后,变量的值会逐渐减少。如果这个变量在<timer>之前就已经存在并且赋值为一个非负整数,那后面value属性的值会被忽略,直接使用变量里的值作为计时时限。
value:必选。指定计时时间,以1/10秒为单位。

下面的例子每隔1秒显示不同的文字(当然,你有兴趣改成图像也可以)。

<?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="Hello" title="Hello">
  <onevent type="ontimer">
   <go href="#card2">
  </onevnet>
  <timer value="10"/>
  <p>Hello!</p>
</card>

<card id="Take care">
  <onevent type="ontimer" title="Take care">
   <go href="#card3">
  </onevnet>
  <timer value="10"/>
  <p>R U tired?</p>
  </card>

<card id="Rest">
  <onevent type="ontimer" title="Rest">
   <go href="#card1">
  </onevnet>
  <timer value="10"/>
  <p>Take a rest!</p>
</card>

</wml>


显示结果如下,注意会不断循环。 Sport选择:
第1秒
第2秒
第3秒
------ Hello ------
Hello!

----- Take care ----
R U tired?

------- Rest -------
Take a rest!

还有一个例子,通常用来做网站封面,显示一段欢迎词以后进入正式内容。这里没有使用图片,各位可以自己加上试试看。

<?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 to WAP86" ontimer="wap86.wml">
  <timer value="30"/>
  <p>
   Hello!
   Welcome to WAP86 - the paradise of WML developers.
  </p>
</card>

</wml>

部件功能
accept 确认,接受输入
prev 退回历史页面访问堆栈里上一个CARD
help 上下文关联的帮助信息
reset 重设设备状态
options 上下文关联的选项或附加操作
delete 删除当前内容或选择
unknown

由开发者自己定义

<do> 用户触发事件[TOP]
每个WAP终端都预定义了一系列用户界面部件,如手机上的按钮、触摸屏上的图表、声音指令或者其他一些很容易是别的部件。WML1.1定义了右面那些WAP 兼容终端必须支持的部件。但是要说明的是,只有prev有预先定义的功能,其他的只是概念上的定义,需要根据开发者激活并赋予一定的动作。

当用户激活这些部件的时候会产生相应的事件。你可以使用<do>元素捕获这些事件并对其做出反应。下面是<do>的语法:

<do
 type="accept | prev | help | reset | options | delete | unknown"
  lebel="STRING"
  name="STRING"
  optional="true | false"
  xml:lang="STRING"
>
<go> | <noop> | <prev> | <refresh>
</do>

type:必选属性,内容只能是那7种;
label:用户接口部件的显示标签。如果终端不能显示则被忽略。WML1.1建议此属性长度限制在6个英文字符以内;
name:标志“事件/任务”绑定关系的唯一名称(在CARD范围内)。CARD级的<do>事件替换同名的DECK级<do>事件(见下一节)。如果不指定name属性或name为空字符串,则name默认为type的类型;
optional:告诉终端此软按钮在屏幕中是否显示。如果此值设为true,则忽略本<do>元素。默认值为false;
xml:lang任务:语言代码。

跟其他“事件/任务”绑定关系一样,<do>里的任务定义必须是<go>、<noop>、<prev>或<refresh>中的一个。
下面例子演示了<do>的使用方法。用户按了不同的按钮会被导向不同的CARD。

<?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" title="WAP86 Links">
  <do type="accept" label="Links" optional="false">
    <go href="#Links"/>
  </do>
  <do type="help" label="Help" optional="false">
    <go href="#Help"/>
  </do>
 <p> WAP86’s perfect links</p>
</card>

<card id="Links" title="WAP86 Links">
  <p> Select one:<br><br>
   <a href="wap.hucn.com">hucn</a><br>
   <a href="wap.hucn.com">hucn</a>
  </p>
</card>

<card id="help" title="Help">
  <do type="accept" label="Links" optional="false">
   <go href="#Links"/>
  </do>
  <p>
    Select "Links" button to view the links.
  </p>
</card>

</wml>

显示结果
主画面
按下“Links”按钮以后:
按下“Help”按钮以后:
---- WAP86 Links ---
WAP86’s perfect links

Links      Help

---- WAP86 Links ---
Select one:

>[ WAP86 ]
[ AT86 ]
------- Help -------
Select "Links" button to view the links.

Links

DECK级事件[TOP]
前面(DECK一节,关于<template>)已经讲过可以用<template>元素定义DECK级事件,做法跟CARD级事件一样,只要在 <template>元素里包含<do>或<onevent>事件就可以。这种做法可以定义一些在每个CARD里都需要定义的事件,而不需要重复说明。比如下面的例子给所有的CARD定义了BACK按钮以便返回上一页:

<?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="prev" label="BACK" optional="false">
   <prev/>
  </do>
</template>

<card id="Links" title="WAP86 Links">
  <do type="help" label="Help" optional="false">
   <go href="#Help"/>
  </do>
  <p> Select one:<br><br>
   <a href="wap.hucn.com">hucn</a><br>
   <a href="wap.hucn.com">hucn</a>
  </p>
</card>

<card id="help" title="Help">
  <do type="accept" label="Links" optional="false">
   <go href="#Links"/>
  </do>
  <p>
   Select "Links" button to view the links.
 </p>
</card>

</wml>
添加评论
单击隐藏此项的评论。

WAP初级教程(五)

WAP初级教程(5)—任务TASK

[日期:2004-10-23] 来源:破釜沉舟  作者: [字体:]
任务(TASK)
·  <noop> ·  <prev> ·  <refresh> ·  <go>

前面我们已经讲过如何在WML中显示内容。不过任何程序员都知道,没有结构和进程就没有程序。在WML中定义进程有很多方法,最简单的就是任务。

WAP1.1定义了几种类型的任务,任务通过对事件(有关事件的详细解释见下一章事件)的响应改变程序的运行顺序。有四种WML任务:·  <noop>、· <prev>·  <refresh> ·  <go>

<noop>[TOP]
这个任务不做任何事情,一般用于屏蔽DECK级事件(参见桌面事件),语法非常简单:

<noop/>

<prev>[TOP]
当用户激活该任务时,终端就转回上次用户访问过的URL。语法如下:

<prev>
   <setvar>
   ......
</prev>


如果<prev>中包含了<setvar>元素,就会优先处理。下面例子定义了一个只有Back按钮的的DECK,按下以后会返回前面看过页面。

<?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>
    Back
    <prev/>
   </anchor>
  </p>
</card>
</wml>

<refresh>[TOP]
当用户激活该任务时,就执行一个刷新过程。如果这个任务里使用<setvar>定义了变量,变量值将被重新设置。语法如下:

<prev>
   <setvar>
   ......
</prev>

如果当前CARD含有<timer>元素,那么在刷新时<timer>优先启动。
下面的例子定义在屏幕刷新时重设firstname、lastname和age变量。

<do type="refresh">
  <refresh>
   <setvar name="firstname" value="david">
   <setvar name="lastname" value="smith">
   <setvar name="age" value="29">
  </refresh>
</do>

<go>[TOP]
当用户激活该任务时,就引导用户去WML中指定URL,可以是服务器上其他的DECK,也可以是本DECK中其他的CARD。语法如下:

<go
   accept-charset="STRING"
   href="URL"
   method="post|get" sendreferer="true|false" >
   <postfield>, <setvar>......
</go>

href:必选属性,指向一个合法URL。如果是其他的DECK,则该DECK的第一个CARD会显示出来。如果是本DECK中的其他CARD,而历史堆栈里保存的是最新数据的话,则堆栈保持不变,直接调入该CARD。

sendreferer:如果为true,用户主体信息(USER AGENT)必须传送给WAP网关。传送时使用HTTP的提交头信息,即尽可能简短的相对URL。这个属性可以用来给服务器控制存取URL的权力。默认值为false。

Method:值必须为get或post。分别用来产生HTTP的GET和POST请求。若为get,则在URL中列出参数,例如:“http: //www.wap86.net/bob.cgi?argone=one”;若为post,则数据在请求内部传送,不需要在URL中列出。

Accept-charset:指定字符集名称列表,服务器在接受<go>的时候必须接受这个编码规则。默认值为unknown。具体内容这里不作解释,在以后的高级教程中描述。

下面是一个简单的例子:

<go href="../topic.wml" sendreferer="true">

<postfield>[TOP]
<postfield>并不是一个任务,但是跟<go>任务有关,所以在这里介绍。它用来定义“名称/值”对以便通过<go>向服务器发送HTTP请求。语法如下:
当用户激活该任务时,就引导用户去WML中指定URL,可以是服务器上其他的DECK,也可以是本DECK中其他的CARD。语法如下:
下面是一个简单的例子:

<postfield name="STRING" value="STRING" />

当一个含有<postfield>的任务被执行的时候,终端要完成这样一个过程:

1、识别“名称/值”对并准备参数变量;
2、参数变量转换成正确的字符集;
3、根据URL的ESCAPE规则对参数进行ESCAPE转码,编译成application/x-www-form-urlencoded的MIME类型;
4、根据method指定的请求模式提交任务。

下面的例子演示get模式的用法:

<go href="../news.asp" sendreferer="true" method="get">
  <postfield name="newstype" value="technology"/>
  <postfield name="newstext" value="wml"/>
</go>

服务器将收到这样的get请求:

GET ../news.asp?newstype=technology&newstext=wml HTTP/1.1
.
. 其他HTTP头信息
.

如果把前面的请求模式改成post,则同样的<go>任务产生的这样的post请求:

POST../news.asp HTTP/1.1
content-type="xxx-urlencoded" .
. 其他HTTP头信息
.
newstype=technology&newstext=wml
添加评论
单击隐藏此项的评论。

WAP初级教程(四)

WAP初级教程(4)—桌面DECK

[日期:2004-10-23] 来源:破釜沉舟  作者: [字体:]
桌面 (DECK)
·  XML说明 ·  <wml> ·  <head> ·  <template>
·  <card> ·  不同浏览器指标    

由于网络带宽以及某些WAP服务器DECK传输的限制,所以DECK越小越好,最好不要超过1.2K。如果你的需求很复杂,最好分成几个DECK来完成。

完整的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>
   .
   . 头信息......
   .
  </head>
  <template>
   .
   . 模板定义......
   .
  </template>
  <card>
   .
   . 内容......
   .
   </card>
   .
   . 其他card(可有可无)......
   .
</wml>

XML说明 [TOP]

DECK开头必须指明以下的XML类型声明:

<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
  "http://www.wapforum.org/DTD/wml_1.1.xml">

第一行指出XML版本,紧跟的文档类型(DOCTYPE)声明指出所引用的语言标准定义(wml_1.1.xml的内容可以察看本教程附录中的DTD说明)。

这两句的位置和顺序不可更改,而且中间不能有空行。

<wml> [TOP]
语法:

<wml>标签和HTML中的<html>标签一样,用来表明这是一个WML的DECK。xml:lang属性来指定文档的语言,比如<wml xml:lang="zh">表示文档语言为中文。

<head> [TOP]

<head>标签包含了该DECK的相关信息。<head>标签之间可以包含一个<access>标签和多个<meta>标签。

<access>语法:

<access
   domain="STRING"
   path="STRING" />

<access>相当于HTML中的<BASE>标签,指定该DECK的访问控制信息,它的两个属性是可选的。

domain:指定域,默认值为当前域。
path:指定路径,默认值为"/",即根目录。

<meta>语法:

<meta
   http-equiv="STRING" | name="STRING"
   forua="true|false"
   content="STRING"
   scheme="STRING" />

和HTML中<META>的类似,<meta>提供了该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"/>。

<template> [TOP]
<template>元素声明一个DECK级的事件/请求,对DECK页面中所有CARD有效,当然某个CARD可以通过定义同名的事件来替代<template>声明中的事件处理。

语法:

<template
   onenterforward="STRING"
   onenterbackward="STRING"
   ontimer="STRING" />

onenterforward:当用户通过<go>进入CARD时调入的链接。
onenterbackward:当用户通过<prev>退回CARD时调入的链接。
ontimer:<timer>事件激活时调入的链接。

例子(其中涉及的其他命令参考其他章节):

<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>

另外可以参看事件(EVENT)

<card> [TOP]
一个DECK可以包含多个CARD,每个CARD的内容可能不止一屏显示,注意DECK、CARD和屏幕显示范围的关系。一个CARD用<card>和</card>包含。

语法:

<card
  id="STRING"
  title="STRING"
  newcontext="true|false"
  ordered="true|false"
  onenterforward="STRING"
  onenterbackward="STRING"
  ontimer="STRING"
  xml:lang="STRING">

每个CARD元素可以有一个标号(ID)和标题(TITLE)。当然,这都不是必须的。

id:CARD的名字,在DECK中唯一,可用作URL已进行跳转。

title:CARD的标题,用户BOOKMARK一个CARD时的名字。该属性在某些用户终端上会显示出来。

newcontext:用来指示当跳转到本CARD时,用户终端(手机、模拟器等)是不是要清除以前保留的信息如变量、堆栈历史记录、终端状态等。默认值为FALSE。

ordered:表明该CARD里的内容是按固定的顺序显示,还是按用户的选择来显示。默认值是TRE。这点和HTML不同,CARD页面里的内容可以按一定的顺序显示,默认的是按线性顺序显示,即按代码的顺序,但是,要注意的是,以下三个标签必须按以下顺序来写<onevent>  <timer> <do>,(这和以后要讲的“事件”有关)。这样做是为了方便填表单,当ordered设置为true时,如果一个表单的内容不能在一屏里显示完,就分成多屏显示;当ordered设置为false时,手机可以显示一个概要CARD来总结有效的选项,用户可以从中选取表单选项来填写。

onenterforward:当用户通过<go>进入CARD时调入的链接。
onenterbackward:当用户通过<prev>退回CARD时调入的链接。
ontimer:<timer>事件激活时调入的链接。

不同浏览器指标
[TOP]

 >

Nokia 7110>

Ericsson R320>

Ericsson R380>

UP.Browser>

CARD最大字节数>

1397 字节>

3000 字节>

3800 字节>

1492 字节>

图象最大字节数>

1397 字节>

3000 字节?>

3800 字节?>

1492 字节?>

显示行数>

4 (含标题行)>

5>

7>

视终端不同>

S3568i:6>

显示列数>

19>

14>

不知道>

视终端不同>

显示宽度(象素)>

95>

101>

304>

视终端不同>

显示高度(象素)>

45>

52>

98>

视终端不同>

象素比例>

1:1.25>

不知道>

1:1.23>

视终端不同>

字体>

>

Small, Bold, Emphasis, Strong>

Small, Big, Bold, Italic, Emphasis, Strong>

Small, Big, Bold>

文字位置>

没有,强制居左>

居左、居中、居右>

居左、居中、居右、段落缩进>

不知道>

图象位置>

强制居左>

不知道>

不知道>

不知道>

表格支持>

不支持>

最多5x5>

不知道>

不知道>

触摸屏>

>

>

>

>

图标键>

>

>

>

不知道>

WML页面内拨号>

"提取号码" 功能>

通过WTAI支持>

通过WTAI支持>

3.1以上版本的浏览器支持>

输入>

在行内输入>

在设置位置输入>

在设置位置输入>

不知道>

输入格式>

只有大小写>

不知道>

不知道>

不知道>

图形链接>

>

>

>

不知道>

链接格式>

在行内>

在设置位置>

在设置位置>

不知道>

DECK下载顺序>

文字,然后图形,再开始选择性计时>

文字,开始选择性计时,然后是图(结果有可能是CARD还未下载完毕就已过时)>

不知道>

 >

HTTP Redirect>

支持>

支持>

支持>

支持>

添加评论
单击隐藏此项的评论。

WAP初级教程(三)

WAP初级教程(3)—显示内容

[日期:2004-10-21] 来源:破釜沉舟  作者: [字体:]
显示内容
·  段落与换行标记 ·  文字样式标记 ·  表格 ·  图像

CARD里可以显示象文本、图像这样的内容。象HTML一样,WML也提供一些标记对内容进行排版。

段落与换行标记 [TOP]

<p>
段落标记,用来对段落进行分段。语法:

<p
  aligh="left|right|center"
  mode="wrap|nowrap";
  xml:lang="STRING" >

aligh:文字对齐方式,左(left)、右(right)、居中(center)。
mode:文字超出屏幕时是否折行,各种终端处理方式不同。
xml:lang:显示语言编码。

<br>行分隔标记,产生回车效果。语法:

<br
  xml:lang="STRING" />

xml:lang:显示语言编码。
段落和换行的例子:

<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
 "http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>
<card title="Paragraphs">
<p>
This is a paragraph
</p>
<p>
This is a another<br/>with a line break
</p>
</card>
</wml>

显示结果如下:

------ Paragraphs ------
This is a paragraph
This is another
with a line break
标记字体样式
<b>粗体 
<big>大字体
<em>强调字体
<i>斜体
<small>小字体
<strong>加重强调字体
<u>下划线字体

文字样式标记[TOP]
WML提供了一系列文字样式的标记,如右表所示。不过WML鼓励大家尽量使用<strong>和<em>标记,因为某些WAP终端会忽略其他标记。
每个文字样式标记语法都一样,都有一个标志语言代码的xml:lang属性。
下面是一个例子:

 



<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
  "http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>
<card title="Formatting">
  <p>
   normal<br/>
   <em>emphasized</em><br/>
   <strong>strong</strong>
   <br/> <b>bold</b> <br/>
   <i>italic</i><br/>
   <u>underline</u><br/>
   <big>big</big><br/>
   <small>small</small>
  </p>
</card>
</wml>

在你的终端上可能会有这样的显示 (不过别太当真,前面说了有的终端会忽略文本样式标记):

list.asp%3fid=3

所以变量有可能需要标志为是否对其内容进行ESCAPE转换,变量定义就有如下几种特殊方式:

----- Formatting -----
normal
emphasized

strong

bold

italic

underline

big

small

表格[TOP]
WML支持简单的表格标记<table>、<tr>和<td>。语法如下: 

<table
  align="L|R|C"
  columns="NUMBER"
  TITLE="STRING"
 <tr>
  <td> 内容... </td>
  其他列...
 </tr>
  其他行...
</table>

在WML里定义一个表格必须先指定列数,即columns属性。而在表格里就必须有相应数量的<td></td>标记对。因该注意的是,align(对齐)属性的内容只能是L(左对齐)、R(右对齐)和C(居中),跟其他标记不同(是不是有点怪?)。

下面的例子演示了表格的基本功能:

<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
  "http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>
<card title="SALARY">
<p>
<table columns="2">
<tr>
<td>NAME</td>
<td>PAYED</td>
</tr>
<tr>
<td>Johnson</td>
<td>$7810.11</td>
</tr>
<tr>
<td>Faye</td>
<td>$8912.00</td>
</tr>
</table>
</p>
</card>
</wml>

显示结果(注意WML里没有表格线):

------ SALARY ------
NAME     PAYED
Johnson    $7810.11
Faye     $8912.00

图像[TOP]
相对于多媒体泛滥的HTML网站,在资源紧张的WAP设备上显示图像就有点奇怪了。但是WML还是提供了图像显示的支持,毕竟一个设计精巧的图像会比一段话表达意思更清楚,或许占用空间更小。

WML支持WBMP(Wireless Bitmap)格式的图像,需要用特殊工具制作。显示图像使用<img>标记,语法如下:

<img
 alt="STRING"
 src="STRING"
 align="top|middle|bottom"
 height="NUMBER"
 width="STRING"
 hspace="NUMBER"
 vspace="STRING"
 localsrc="STRING" />

alt: 图像无法显示时的替换文字。
src: 图像的url。
localsrc: 储存于ROM(或RAM)中图像的名字,各种终端支持不同。
align: 上下对齐方式。
height: 图像显示高度。
width: 图像显示宽度。
hspace: 图像左右的空白,以pixel数或百分比表示。
vspace: 图像上下的空白,以pixel数或百分比表示。

上面的属性只有alt和src是必须的。其他附加属性基本上仅仅用来指示用户终端,大多数情况下会被忽略。下面是个例子:

<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
 "http://www.wapforum.org/DTD/wml_1.1.xml">

<wml>
<card title="Congratulation">

<p>
WAP86, <img src="wonderful.wbmp" alt="wonderful"/>!
</p>

</card>
</wml>

下面分别是在支持和不支持图像的终端上的显示结果:

--- Congratulation ---
WAP86,!
--- Congratulation ---

WAP86, wonderful!

添加评论
单击隐藏此项的评论。

WAP初级教程(二)

WAP初级教程(2)—WML变量

[日期:2004-10-21] 来源:破釜沉舟  作者: [字体:]
WML变量
·  格式 ·  替换文本 ·  ESCAPE转换

格式 [TOP]
象HTML一样WML可以定义变量,可以让你的页面设计更简单和富有逻辑性。变量格式如下显示:

$identifier
$(identifier)
$(identifier:conversion)

圆括号在变量带有空格时使用,第3种格式本节后面说明。
变量的优先权最高,所以当出现与变量符号相同的字符时,它将被认为是变量的标志。因此如果想在WML页面中显示$符号时必须在其后面再跟一个$符号。如下例:

You account has $$1650.00 in it.

变量名是由US-ASCII码、下划线和数字组成,并且只能以US-ASCII码开头。变量名大小写敏感。
WML变量没有类型,均表示为字符串。变量没有被赋值的时候,内容为空,即空字符串。可以在运行过程中改变它的值。

创建变量
创建变量最简单的方法是使用<setvar>元素,语法如下:

<setvar
  name="string"
   value="string" />

<setvar>只能在<go>、<prev>和<refresh>中使用(具体操作见本教程任务(TASK))。下例定义了一个叫vNAME的变量并赋值为“Jeff”:

<setvar name="vNAME" value="Jeff" />

另外,还可以在<input>、<select>和<postfield>中定义变量,参考本教程(任务(TASK)数据输入

替换文本[TOP]
变量可以用作替换用途,但只能在文本类型(如显示字符、URL等)中使用。任何元素和属性都不能使用变量来替代。例如:

Hello, $vNAME.

将显示:

Hello, Jeff.

ESCAPE
转换
[TOP]
前面说过变量可以用作替换用途,但是在URL中使用时,变量的内容必须遵守[RFC2396]标准。这个标准规定某些特殊字符在URL里使用的时候必须用特殊表示方法,即ESCAPE八进制表示。例如:

list.asp?id=3

在URL中要表示为:

list.asp%3fid=3

所以变量有可能需要标志为是否对其内容进行ESCAPE转换,变量定义就有如下几种特殊方式:

效果表达方式1表达方式2表达方式3
对变量中ESCAPE字符进行转换 $(var:e) $(var:E) $(var:escape)
不进行ESCAPE转换 $(var:u) $(var:U) $(var:unesc)
变量中没有ESCAPE字符 $(var:n) $(var:N)

$(noesc)


给变量进行ESCAPE转换是WML的默认方式,特殊字符ESCAPE码请参考本教程字符实体
添加评论
单击隐藏此项的评论。

WAP初级教程(一)

WAP初级教程(1)—WML基础

[日期:2004-10-21] 来源:破釜沉舟  作者: [字体:]
WML基础
·  WML的基本情况 ·  建立网页制作环境 ·  WML文件结构 ·  WML字符集
·  WML元素:标记(Tag)和属性 ·  WML注释 ·  链接(URL
·  CDATA      

WML 的基本情况 [TOP]
用于WAP的标记语言就是WML(Wireless Markup Language)。
WML的语法跟XML一样,WML是XML的子集。
HTML、XML和WML的文件有很多相似之处,这样网页开发者在过去10年中所学的东西今天依然适用。
WML页面文件的后缀是 *.WML,就象HTML的 *.HTML后缀。
XML规定定义了一个规范的XML文件的规格。任何违反这个规定的WML文件会出错。WML文件通常使用XML解释器起来解释。

建立网页制作环境[TOP]
WML文件本身就是文本文件,所以编辑不成问题,顺手的编辑器都可以用。
当然,由于目前的浏览器还都不能显示WML页面,而我们又不能总在手机上进行测试(速度太慢),所以需要模拟器。现在象NOKIA、ERICSSON、 MOTOROLA等手机制造商都生产了相应的产品,你只要下载就行了。当然除了模拟器以外,还需要图形制作转换器(用来制作WAP格式的图形文件)、字符转码器(汉字〈-〉UNICODE)等等。

WML
文件结构[TOP]
WML 的页面通常叫做桌面(DECK),由一组互相链接的卡片(CARD)组成。当移动电话访问一个WML页面的时候,页面的所有CARD都会从WAP服务器下载到设备里。CARD之间的切换由电话内置的计算机处理,不需要再到服务器上取信息了。CARD里可以包含文本、标记、链接、输入控制、任务(TASK)、图像等等。CARD之间可以互相链接。

文档的实体包含在<wml>...</wml>标记中,文档里每个CARD又包含在<card>...</card>标记中,然后实际的文字段落则包含在<p>...</p>标记中。

简单例子:

<?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="HELLO" title="HELLO">
 <p>
 Hello world!
 </p>
</card>
</wml>

显示结果如下:

------ HELLO ------



Hello World!

DECK里面各个组成部分的具体解释在本教程的其他部分有说明。

WML字符集[TOP]
WML是XML的子集,继承了XML的字符集设置。WML文档缺省的字符集是UTF-8。
要显示中文,有两种办法。最简单的办法就是在文档头使用encoding,即把第一行改为:

<?xml version="1.0" encoding="gb2312"?>

然而令人丧气的是,这种方法有些手机和模拟器并不支持(将来会的),所以目前第2种方法更普遍:不改变字符集设置,但是在写中文的时候采用UNICODE代表中文字符,如:

<b>&#x901A;&#x8BAF;&#x5F55;</b>

代表:
通讯录

WML元素:标记(Tag)和属性[TOP]
WML的主要内容是文本,由于标记会降低与手持设备的通讯速度,所以WML标准里仅仅使用了很少一部分。用于表格和图像的的标记几乎都被排除了。

与XML一样,在WML语言中,所有元素都放在符号"<" 和 ">"中,并且包含一个开始标志、一个结束标志和一个内容标志,或者使用自身结束的控制标记。就象这样:

<tag>内容</tag> 例如:<p>Hello world!</p>

<tag/> 例如:<br/> 和 <go href="#done"/>

WML同样支持在标志中标出属性。属性是标志的附加信息,与元素的内容不一样,它并不在屏幕上显示出来。属性通常在元素的开始标志后指定。如上面最后一个例子。

由于WML是XML的一种应用,因此所有的WML标记和属性都是大小写敏感的(<wml>跟<WML>完全不同),而且所有的标记都必须正确地结束。WML要求属性的值必须放在双引号或单引号内。单引号可放在属性标志内或双引号内。字符亦可作为属性的值。

WML注释[TOP]
XML支持这样的注释格式:

<!这句话你在手机上看不到-->

这些注释在浏览器中并不显示出来。
WML不支持嵌套元素注释。

链接(URL[TOP]
WML外部引用方式跟HTML相同

http://www.wap86.net/great.wml 或
http://www.wap86.net/great.wml#login

内部引用,如果next是当前DECK中的一个CARD时,可以用这种方式:

#next

提供链接功能的WML元素有2个:<go>(参见任务)和<anchor>(参见事件)。

CDATA[TOP]
XML支持CDATA的概念,以显示不需要解释的文本。下面的例子使用CDATA元素在WML页面中显示WML命令文本。

<! [CDATA [ <card name="bogus"><p&gtthis is data</p></card> ] ]>

浏览器窗口将显示如下内容:

<card name="bogus"><p>this is data</p></card>
添加评论
单击隐藏此项的评论。

WAP教程(六)

第六章 WML Script标准函数库(上)
(Penny 2001年05月25日 16:17)

这节会讨论标准的WML Script函数库。

6.1 WML Script规则

这些标准函数库提供一个扩展WML Script语言的机制,这些特定的函数库必须遵循WML Script的规则。

支持的数据格式

下面的WML Script格式使用于程序的定义之中,这样能记录程序参数与回转值的格式。

Boolean
Integer
Float
String
Invalid

除此之外,如果整数与浮点数参数值格式都能接受的话,则能使用number来记录参数格式,如果使用的格式是所支持的格式,则能用any来记录。

数据格式转换

函数库程序发生错误的处理方式和WML Script语言一样。

invalid程序参数会产生invalid的回传值。

程序的参数无法转成所需要使用参数格式,则会产生invalid的回传值。

与程序相关的错误得出回传一个适当的错误码,至于这个值就要看每个程序如何定义。

6.2 Lang函数库

名称:Lang

说明:这个函数库所含的程序同WML Script语言的核心有很密切的关系。

abs

程序:abs(value)
说明:回传给予数的绝对值。
如果给予的数是整数,则回传整数。
如果给予的数是浮点数,则回传浮点数。
参数:value=数字。
回传值:数字或invalid。
例外状况:var a =-3;
var b =Lang.abs(a);//b=3

min


范例:var a = -3
var b = Lang.abs(a);
var c = Lang.min(a.b);
var d = Lang.min(45、76.3);//d=45(ingteger)
var e = Lang.min(45、76.3);//e=45(ingteger)

max

程序:max(value1,value2)
说明:回传值给予的两个数之间的较大值,回传的值于格式同所选数值的值与格式相同,其选取的方式如下:
WML Script运算符数据格式的整数与浮点数转换法则可用来确认数据格式,以便执行比较的动作。
参数:value1 =数字
value2 =数字
回传值:数字或invalid
例外状况:无
范例:var a =-3;
var b =Lang.abs(a);//b=3
var c = Lang.min(a.b);
var d = Lang.min(45、76.3);//d=45(ingteger)
var e = Lang.min(45、76.3);//e=45(float)

parseInt

程序:parseInt(value)
说明:回传由字符串value所定义的整数值,合法的整数语法由WML Script数值字符串文法或是近值整数是字所界定,下列为额外的解析法则:
第一个字符不是由+、-或十进制数字当开头的话,解译结束。
结果:解析过的字符串回转换整数值。
范例:var i =Lang.parseInt("1234"); // i=1234
var j =Lang.parseInt("100 m/s"); // j=100

parseFloat

程序:parseFloat(value)
说明:回传由字符串value所定义的浮点数值,合法的浮点数语法由WML Script数值字符串文法或是近值整数实字所界定,下列为额外的解析法则:
第一个字符无法解析成浮点数表达式,解析结束。
结束:解析过的字符串回转换成浮点数。
参数:value=字符串
回传值:浮点数或invalid
例外状况:解析错误则传回invalid
范例:var a =Lang.parseFloat("123.7 Hz"); // a=123.7
var b =Lang.parseFloat("7.34e2 Hz"); // b=7.34e2
var c =Lang.parseFloat("70.0e-2 F"); // c=70.0e-2
var d =Lang.parseFloat("-1.c"); // d=0.1
var e =Lang.parseFloat("100"); // e=100.0
var f =Lang.parseFloat("Number:5.5"); // f=invalid
var g =Lang.parseFloat("7.3e meters"); // g=invalid
var h =Lang.parseFloat("7.3e- m/s"); // h=invalid

isInt

程序:isInt(value)
说明:如果各预的值value能使用parseInt(value)转成整数则回传布尔值ture,否则传回false。
参数:value=任意值
回传值:布尔值或invalid
例外状况:无
范例:var a=Lang.inInt("-123"); //ture
var a =Lang.minInt("123.33"); //ture
var a =Lang.minInt("string"); //false
var a =Lang.minInt("#123"); //false
var a =Lang.minInt("invalid"); //invalid

isFloat

程序:isFloat(value)
说明:如果各预的值value能使用parseInt(value)转成整数则回传布尔值ture,否则传回false。
参数:value=任意值
回传值:布尔值或invalid
例外状况:无
范例:var a=Lang.inInt("-123"); //ture
var a =Lang.minInt("123.33"); //ture
var a =Lang.minInt("string"); //false
var a =Lang.minInt("#123"); //false
var a =Lang.minInt("invalid"); //invalid

maxInt

程序:maxInt()
说明:传回最大的整数值。
参数:无
回传值:整数2147483647
例外状况:无
范例:var a =Lang.minInt();

minInt

程序:minInt()
说明:传回最小的整数值
参数:无
回传值:整数-2147483647
例外状况:无
范例:var a =Lang.minInt();

float

程序:float()
说明:如果有支持浮点数的话传回ture,没有的话传回false。
参数:无
回传值:布尔值
例外状况:无
范例:var floatsSupported = Lang.float();

exit

程序:exit(value)
说明:结束WML Script位码的解译然后回到调用WML Script解译器者的控制,并回传指定值value,你可以使用这个程序来执行由一般程序的结束,而且WML Script位码的执行必须停止。
参数:valre=任意值
回传值:无,这个程序结束解译
例外状况:无
范例:Lang.exit("Value:" + myVal);//Returns a string
Lang,exit(invalid);// Returns invalid

abort

程序:abort(errorDescription)
说明:中止WML Script位码的解译然后回到调用WML Script解译器者的控制,并回传 errorDescription,你能使用这个程序执行不正常的中止,调用程序者检测到有严重错误,WML Script的执行并须中断。
如果errorDescription的格式为invalid,字符串invalid用代替errorDescription的使用。
参数:errorDescription =字符串
回传值:无,这个程序结束解译
例外状况:无
范例:Lang.abort("Error:" + errVal); // Error value string

radndom

程序:random(value)
说明:回传一个正数的整数值,也就是说要大于或等于零,但必须要小于给定值value,回传值是由近是正常分布所随机选取的值。
参数:value=整数
回传值:整数或invalid
例外状况:如果value等于0,则程序回传0
如果value小于0,则程序回传invalid
范例:var a =10;
var b =Lang.random(5.1)*a;//b=0..50
var c = Lang.random("string"); // c=invalid

reed

程序:seed(alue)
说明:初始化需随机数字顺序并回传一个空字符串
如果value为0或正整数,给予的value则用来初始化,反之则使用随机初始化的值。
如果value为浮点数,则会先使用Float.int()来计算确切的整数值。
参数:value=整数
回传值:字符串或invalid]
例外状况:无
范例:var a =Lang.reed(123);// a=""
var b =Lang.random(20); // b=0..20
var c = Lang.seed("seed"); // c=invalid (random seed //left unchanged)

characterSet

程序:characterSet()
说明:回传WML Script解译器所支持的字集,回传只是个整数用来记录由IANA所设定的MIB Enum值,这个只能表示所有的字集。
参数:无
回传值:整数
例外状况:无
范例:Var charset = Lang.characterSet(); //charset = 4 for latinl

6.3 Float函数库

名称:Float
说明:这个函数库包含了典型与常用的浮点数算术程序。

int

程序:int(value)
说明:回传给予值的整数部分。
参数:value=数字
回传值:整数或invalid
例外状况:无
范例:var a =3.14;
var b =Float.in(a); //b=3
var c =Float.in(-2.8); //c=-2

floor

程序:floor(value)
说明:回传整数值,这个只要最接近给予值但不能大于它。
如果value已经是个整数,其结果就是这个值本身。
参数:value=数字
回传值:整数或invalid
例外状况:无
范例:var a =3.14;
var b =Float.in(a); //b=3
var c =Float.in(-2.8); //c=-3

ceil

程序:ceil(value)
说明:回传一个只要最接近给予值但不能小于它的整数值。
如果value已经是个整数,其结果就是这个值本身。
参数:value=数字
回传值:整数或invalid
例外状况:无
范例:var a =3.14;
var b =Float.in(a); //b=4
var c =Float.in(-2.8); //c=-2

pow

程序:pow(x,y)
说明:回传x的y次方值。
如果x是负数,则y必须为正数。
参数:x=数字
   y=数字
回传值:浮点数或invlid
例外状况:如果x= =0而且 y<0,则回传invalid
如果x<0而且y不是个整数,则回传invalid
范例:var a =3
var b =Float.pow(a,2); //b=9

round

程序:round(value)
说明:传回最接近给予值的整数
若两个整数值跟value接近的程序相等,则选择比较大的数。
若value已经是个正数,其结果就是value本身。
参数:value=数字
回传值:整数或invalid
例外状况:无
范例:var a=Float.round(3.5); // a=4
var b=Float.round(-3.5); //b=-3
var c=Float.round(0.5); // c=1
var d=Float.round(-0.5); //d=0

squt

程序:sqrt(value)
说明:传回给予值value的平方根近似值。
参数:value=浮点数
回传值:浮点数或invalid
例外状况:如果value负数,则回传invlid
范例:var a=4;
var b=Float.squt(a); //b=2.0
var c=Float.squt(5); //c=2.2360679775

maxFloat

程序:maxFloat()
说明:传回IEEE 754所支持的但准浮点数格式中最大的浮点数值。
参数:无
回传值:浮点数3.40282347E+38
例外状况:无
范例:var a=Float.maxFloat();

minFloat

程序:minFloat()
说明:传回IEEE 754所支持的但准浮点数格式中最小的浮点数值。
参数:无
回传值:浮点数1.17549435E-38
例外状况:无
范例:var a=Float.minFloat();

6.4 string函数库

名称:字符串
说明:这个函数库包含了字符串程序的集合,一个字符串可以是字符数组,每个字符都有个索引,字符串的第一个字浮的索引为0,字符串的长度是字符在数组中的数目。

你能使用一些特殊的分隔符号来界定不同的字符串,这样你就能存取这些有分隔符号予元素索引所界定出的元素,字符串中第一个元素的索引值为0,每个字符串分隔符号回分隔出两个元素,但字符是不能用来做分隔符号。

一个空格的字符可能是下列字符其中之一:

TAB:水平跳格定位(horizontal tabulation)
VT:垂直跳格定位(ertival tabulation)
FF:跳页(from feed)
SP:空格(space)
LF:跳行(line feed)
CR:归位(carriage return)

length

程序:length(string)
说明:传回给予字符串的长度(字符的数目)。
参数:string=字符串
回传值:整数或invalid
例外状况:无
范例:var a="ABC";
var b=string.length(a); //b=3
var c=string.length(""); //c=0
var d=string.length(342); //d=3

is Empty

程序:is Empty(string)
说明:如果字符串长度为零则传回布尔值true,反之传回false。
参数:string=字符串
回传值:布尔值或invalid
例外状况:无
范例:var a="Hello;
var b="";
var c=sting.isEmpty(a); //c=false
var c=sting.isEmpty(b); //d=ture
var c=sting.isEmpty(ture); //e=false

charAt

程序:charAt(sting.index)
说明:回传string中index值所指定的字符。
参数:string=字符数
index=数字(回传回index所指定的字符)
回传值:字符串或invalid
例外状况:如果index的值超过字符串的范围,则回传空字符串("")
范例:var a="My name is Joe"
var b=sting.charAt(a,0); //b= "M"
var c=sting.charAt(a,100); //c= ""
var d=sting.charAt(34.0); //d="3"
var e=sting.charAt(a,"first"); //e=invalid

subString

程序:subString(string,startIndex,length)
说明:传回一个新的字符串来代替所给予的字符串, 这个新字符串给定的索引值开始,它的长度有所给予的length决定。
如果startIndex小于0,则会0来当作索引值。
如果length大于剩余字符的数目,则lenght会由剩余的字符数来代替。
如果startIndex予lenght是浮点数,则会先使用Float.int()来计算正确的整数值。
参数:string=字符数
startIndex=数字
lenght=数字
回传值:字符串或invalid
例外状况:如果startIndex大于最后的索引值,则回传会空字符串("")
如果lenght<=0,传会空字符串("")
范例:var a="ABCD";
var b=String.subString(a,1,2); //b="BC"
var c=String.subString(a,2,5); //c="CD"
var d=String.subString(1234,0,2); //d="12"

find

程序:find(string,substring)
说明:传会所要寻找的字符串substring和原始字符串string相符的第一个字符的索引值。
如果没有相符,则传会整数值-1。
两个字符传如果是相等的话,是定义为不符合。
参数:string=字符串
substring=字符串
回传值:整数或invalid
例外状况:无
范例:var a="abcde";
var b=String.find(a,"cd"); //b=2
var c=String.find(34.2,"de"); //c=-1
var d=String.find(a,"gz"); //d=-1
var e=String.find(34,"3"); //e=0

replace

程序:eplace(tring,oldSubString,newSubString)
说明:传会新字符串,这个新字符串是由和所给予字符串string相符的旧字符传oldSubString使用新字符串newSubString字符串加以代替。如果两字符串相等的话,定义为相符。
参数:string=字符串
oldSubString=字符串
newSubString=字符串
回传值:字符串或invalid
例外状况:无
范例:var a="Hello Joe.What is up Joe?";
var newName="Don";
var oldName="Joe";
var c=String.replace(a,oldName,newName); //c="Hello Don.What is up Don?"
var d=String.replace(a,oldName,newName); //c="Hello Don.What is up Don?"

element

程序:element(string,separator)
说明:回传分隔符号separator所分隔的字符串string的元素数目,空字符串("")是有效的元素,这表示了这程序永远不会回传一个小于或等于0得值。
参数:string=字符串
separator=字符串
回传值:整数或invalid
例外状况:如果separator是个空字符串,则回传invalid
范例:var a="My name is Joe;Age 50";
var b=String.elements(a,"");//b=6
var c=String.elements(a,";");//c=3
var d=String.elements("",";");//d=1
var e=String.elements("a","");//e=1
var f=String.elements(";",";");//f=2
var g=String.elements(";;,;",";,");//g=4
separator=;

elementAt

程序:elementAt(string,index,separator)
说明:寻找字符串string的第index个元素,这些元素是由分隔符号separator所加以分开,并回传相对应的元素。
如果index值小于0,则回传第一个元素。
如果index值大于元素的数目,则回传最后一个元素。
如果字符串为空字符串,则回传空字符串。
如果index值为浮点数,则须先使用Float.int()来计算出正确的索引值。
参数:string=字符串
index=数字
separator=字符串
回传值:字符串或invalid
例外状况:如果separator是个空字符串,则回传invalid
范例:var a="Hello Joe.What is up Joe?";
var b=String.elementAt(a,0,""); //b="My"
var b=String.elementAt(a,14,";"); //c=" "
var b=String.elementAt(a,1,";"); //d="Age 50"

removeAt

程序:removeAt(string,index,separator)
说明:将符合索引值index的分隔号separator与元素有字符串string中移出,并回传这个新字符串。
如果index值小于0,则回传第一个元素。
如果index值大于元素的数目,则回传最后一个元素。
如果字符串为空字符串,则回传空字符串。
如果index值为浮点数,则须先使用Float.int()来计算出正确的索引值。
参数:string=字符串
element=字符串
index=数字
separator=字符串
回传值:字符串或invalid
例外状况:如果separator是个空字符串,则回传invalid
范例:var a=" A A;B C D";
var s= "";
var c=String.removeAt(a,1,s); //b="A B C D"
var d=String.removeAt(a,0,";"); //c=" B C D"
var e=String.removeAt(a,14,";"); //d="A A"

replaceAt

程序:replaceAT(string,index,separator)
说明:在特定的index中的元素,使用所给予的元素element来代替,并回传这个新字符串。
如果index值小于0,则回传第一个元素。
如果index值大于元素的数目,则回传最后一个元素。
如果字符串为空字符串,则回传空字符串。
如果index值为浮点数,则须先使用Float.int()来计算出正确的索引值。
参数:string=字符串
element=字符串
index=数字
separator=字符串
回传值:字符串或invalid
例外状况:如果separator是个空字符串,则回传invalid
范例:var a= "B C; E";
var s="";
var d=String.replaceAT(a,"A",0,s); //b="A C;E"
var e=String.replaceAT(a,"F",5,";"); //d="B C;F"

InsertAt

程序:insertAt(string,index,separator)
说明:将元素element与相对应的分隔符号separator插入与原始字符串string,在特定的element中的元素
如果index值小于0,则0会用来当索引值。
如果index值大于元素的数目,则元素element会附加上字符串string的为端。
如果字符串string为空字符串,则回传包含所给予元素element的新字符串。
如果index值为浮点数,则需先使用Float.int()来计算出正确的索引值。
参数:string=字符串
element=字符串
index=数字
separator=字符串
回传值:字符串或invalid
例外状况:如果separator是个空字符串,则回传invalid
范例:var a= "B C; E";
var s="";
var b=String.insertAt(a,"A",0,s); //b="A B C;E"
var c=String.insertAt(a,"X",3,s); //c="B C;E X"
var d=String.insertAt(a,"D",1,";"); //d="B C;D;E"
var e=String.insertAt(a,"F",5,";"); //e="B C;E;F"

squeeze

程序:squeeze(string)
说明:将字符串string中所有连续的空格减少为一个空格。
参数:stromg=字符串
回传值:字符串或invalid
例外状况:无
范例:var a="Hello";
var b="Bye Jon.See you!";
var c=String.squeeze(a); //c="Hello"
var d=String.squeeze(b); //d="Bye Jon.See you!"

trim

程序:trim(string)
说明:将字符串string中所有开头与连续的空格删除。
参数:string=字符串
回传值:字符串或invalid
例外状况:无
范例:var a="Hello";
var b="Bye Jon.See you!";
var c=String.squeeze(a); //c="Hello"
var d=String.squeeze(b); //d="Bye Jon.See you!"

compare

程序:compare(string,string2)
说明:这个程序的回传值会指出string1与string2在语汇上关系,这个关系是基于自然字集的字符码之间,其回传值如下:
如果string1小于string2,传会-1。
如果string1等于string2,传会-1。
如果string1大于string2,传会-1。
参数:string1=字符串
string2=字符串
回传值:整数或invalid
例外状况:无
范例:var a="Hello";
var b="Hello";
var c=String.compare(a,b); //c=0
var d=String.compare("Bye","Jon"); //d=-1
var e=String.compare("Jon","Bye"); //e=1

toString

程序:toString(value)
说明:回传一个能表示所给予的值value的字符串,这个程序跟WML Script的转换是一样的,除了invlaid值会回传一个"invalid"字符串。
参数:value=任意值
回传值:字符串
例外状况:无
范例:var a=string.toString(12); // a="12"
var a=string.toString(true); // b="true"

format

程序:format(format,value)
说明:将给予的值value转换成字符串,并依照所给予的格式format提供的格式化的字符串,这个格式字符串只能由一种特定格式,并能放置于字符串的任何地方,如果超过一种以上的格式需要使用,则能会使用最左边的格式,至于其他格式则有空字符串代替,这些格式如下:

[width][.precision]type
width参数为非负的是近制整数,这个参数控制与显现字符的最小数目,如果输出的字数小于指定的宽度width,则会在字符串的左边加上空白,直到符合最小宽度的要求,width参数永远不会是值value被删减,如果输出的字数大于特定的宽度或并没指定宽度的话,value中所有的字符都会被显现。

precision参数是个非负的十进制整数,这个引号之前必须限价上(.)的符号,其目的是用来设定输入值的精确度,这个值的解议会跟给予的格式有关:

d 界定数字最小的显现数目,如果value中数字的数目超过precision的值,输入值会在其左边加上0,如果数字的数目超过precision值, value的值并不会被删减,预设的precision值为1,如果precision值设定为0,而且value页被转换成0,则结果将是一个空字符串。

f 界定十进制小数后的数字数目,如果十进制的小数点出现了,在小数点之后至少要有一位数,这个值会被四舍五入到近似的数字数值,预设的precision为 6,如果precision为0或小数点(.)后没有数字,则不会显现小数点,当value值的小数点后数字数目小于precision的值,字母0为被加入直到填满栏位(如:String.format("%2.3f",1.2)会是"1.200")

s 界定字符所要显现的最大数目,预设值是显现所有的字符,当width值大于precision值,width值是可以忽略的,跟width值不同的是,precision只可能会造成浮点数值的四舍五入或输入值的删减。

type参数是唯一格式的参数,他出现在任何的格式栏为选项之后,type字符决定了所给予的value将会解译成整数,浮点数或字符串,支持的type参数如下:
d 整数:输入值的格式[-]dddd,这里的dddd是一个或以上的十进制数字。
f 浮点数:输入值的格式[-]dddd.dddd,这里的dddd是一个或以上的十进制数字,在小数点之前的数字数目和数字的大小有关,小数点之后的数字数目和精确度有关。
s 字符串:字符的显现跟精确度有关。
百分比字符(%)在格式字符串中能使用额外的百分比字符加以表示(%%)。
参数:format=字符串
value=任意值
回传值:字符串或invalid
例外状况;无效的格式会回传invalid值。
范例:var a=45;
var b=-45;
var c="now";
var d=1.2345678;
var e=String.format("e:%6d",a); //e="e:45"
var e=String.format("%6d",b); //f="-45"
var e=String.format("e:%6d",a); //g="0045"
var e=String.format("%6.4d",b); //h="-0045"
var e=String.format("Do it %s",c); //i="Do it now"
var e=String.format("%3f",d); //j="1.2345678"
var e=String.format("%10.2f%%",a); //k="1.23%."
var e=String.format("%3f %2f",a); //l="1.234567."
var e=String.format("%.0d",0); //m=""
var e=String.format("%.7d","Int"); //n="invalid"
var e=String.format("%s",ture); //o="ture"


第六章 WML Script标准函数库(下)
(Penny 2001年05月25日 16:17)

6.5 URL函数库

名称:URL
说明:这个函数库包含了处理绝对的URL与相对URL的程序,一般的URL语法如下:://:/;?#

isValid

程序:isValid(url)
说明:如果给予的url值是正确的URL语法,则回传ture,否则回传false
绝对与相关URL都能支持
相关URL不会被转成绝对URL
参数:url=字符串
回传值:布尔值或invalid
例外状况:无
范例:var a=URL.isValid
("http://www.acme.com/script#func()"); //a=ture
var b=URL.isValid("../common#test()"); //b=ture
var c=URL.isValid
("experimental?://www.acme.com/pub"); //c=false

getScheme

程序:getScheme(url)
说明:回传给予url的调用方式scheme
绝对与相关URL都能支持
相关URL不会被转成绝对URL
参数:url=字符串
回传值:字符串或invalid
例外状况:如果遇到不正确的URL语法,则回传invalid
范例:var a=URL.geScheme("http://w.a.com"); //a="http"
var b=URL.getSceme("w.a.com"); //b=""

getHost

程序:getHost(url)
说明:回传给予url的主机
绝对与相关URL都能支持
相关URL不会被转成绝对URL
参数:url=字符串
回传值:字符串或invalid
例外状况:如果遇到不正确的URL语法,则回传invalid
范例:var a=URL.geHost("http://www.acom.com/pub"); //a="www.acm.com"
var b=URL.getHost("path#fray"); //b=""

getPort

程序:getPort(url)
说明:回传给予url的端口(port)
如果port没有制定,则回传空字符串
绝对与相关URL都能支持
相关URL不会被转成绝对URL
参数:url=字符串
回传值:字符串或invalid
例外状况:如果遇到不正确的URL语法,则回传invalid
范例:var a=URL.getPort("http://www.acom.80/path"); //a="80"
var b=URL.getPort("http://www.acom./path"); //b=""

getPath

程序:getPath(url)
说明:回传给予url的路径(path)

参数:url=字符串
回传值:字符串或invalid
例外状况:如果遇到不正确的URL语法,则回传invalid
范例:var a=URL.getPath("http://w.a.com/home/sub/comp#frag"); //a="/home/sub/comp"
var b=URL.getPath("../home/sub/comp#frag"); //b="../home/sub/comp"

getParameters

程序:getParameters(url)
说明:回传给予url的路径(parameter)
如果没有指定参数,则回传空字符串
绝对与相关URL都能支持
相关URL不会被转成绝对URL
参数:url=字符串
回传值:字符串或invalid
例外状况:如果遇到不正确的URL语法,则回传invalid
范例:var a=URL.getParameters("http://w.a.c/scr;3;2?x=1&y=3"); //a="3;2"
var b=URL.getParameters("../scr3;2?x=1&y=3"); //b="../home/sub/comp"

getQuery

程序:getQuery(url)
说明:回传给予url的询问部分(query)
如果没有指定的询问部分,则回传空字符串
绝对与相关URL都能支持
相关URL不会被转成绝对URL
参数:url=字符串
回传值:字符串或invalid
例外状况:如果遇到不正确的URL语法,则回传invalid
范例:var a=URL.getParameters("http://w.a.c/scr;3;2?x=1&y=3"); //a="3;2"

getFragment

程序:getFragment(url)
说明:回传给予url的片断(fragment)
如果没有指定片断,则回传空字符串
绝对与相关URL都能支持
相关URL不会被转成绝对URL
参数:url=字符串
回传值:字符串或invalid
例外状况:如果遇到不正确的URL语法,则回传invalid
范例:var a=URL.getFragment("http://www.acom.com/cont#fray"); //a="fray"

getBase

程序:getBase()
说明:回传次WML Script程序的绝对URL(没有fragment的部分)。
参数:无
回传值:字符串
例外状况:无
范例:var a=URL.getBase(); //Result;
"http://www.acme.com/test.scr"

getReferer

程序:getReferer()
说明:回传调用目前程序资源的最小相关URL(与目前程序的基本URL的相关)
内部程序调用并不会改变参照者
如果目前的程序并没有参照者,则回传空字符串
参数:无
回传值:字符串
例外状况:无
范例:var base=URL.getBase(); //base
="http://www.acme.com/current.scr"
var prferer=URL.getReferer(); //referer="app.wml"

resolve

程序:resolve(baseUrl,embeddedUrl)
说明:根据RFC2396的文件,由给予的基本base与插入embeddedUrl回传绝对URL
参数:baseUrl=字符串
embeddedUrl=字符串
回传值:字符串或invalid
例外状况:如果遇到不正确的URL语法,则回传invalid
范例:var a=URL.resolve(http://www.foo.com/,"foo.vcf"); //a="http://www.foo.com/foo.vcf"

escapeString

程序:escapeString(string)
说明:这个程序会将所给与string字符串之中的特殊字符使用十六进制逃脱序列来替代(你必须使用量为逃脱序列格式%xx),这些逃脱字符如下:
控制字符(control characters):US-ASCII编码的字符00-1F与7F
空格(Space):US-ASCII码编字符20十六进制
保留字(Reserved):";"|"/"|"?"|":"|"@"|"="|"+"|"$"|","
Unwise:"{"|"}"|"|"|"\"|""|"["|"]"|"`"
Delimes:"<"|">"|"#"|"%"|"<>"
给予的字符串如果已经是使用逃脱自负,则不会执行URL解析
参数:string=字符串
回传值:字符串或invalid
例外状况:如果字符串string含有非US-ASCII的字符,则回传invalid
范例:var a=URL.escapeString
("http://w.a.c/dck?x=u007ef#crd");
// a="http%3a2f%2fw.a.c%2fdck%3fx%3def%23crd"

unescapeString

程序:unescapeString(string)
说明:这个程序会将所给与string字符串之中每个可能是由URL.escapeString() 程序所产生的逃脱序列使用它所代表的字符加以替代。
参数:string=字符串
回传值:字符串或invalid
例外状况:如果字符串string含有非US-ASCII的字符,则回传invalid
范例:var a="http%3a2f%2fw.a.c%2fdck%3fx%3def%23crd";
var b=URL.unescapeString(a); //b
="http://w.a.c/dck?x=12#crd"

loadString

程序:loadString(url,contentType)
说明:回传有所给予的绝对URL与contenttype所指出的内容。
如果内容格是不是下列法则所规范的话,则是错误的:
你只能界定一种内容格式,整个字符串必须和一种内容格式相符,而 且你不能有额外的前或后空格。
格式必须是正文,但次格式没有限制,格式的开头一定是"text/"。
这个程序的动作如下:
文件的内容会载入使用给予的contentType与url,其他所需的数形式有使用用户界面的预设面。
如果载入成功而且回传的内为格式与所给予的contentType相符,则内文会被转换成字符串再回传。
如果载入成功或回传的内文格式不正确的话,则会回传特定的错误码。
参数:url=字符串
contentYype=字符串
回传值:字符串、整数或invalid
例外状况:如果载入失败其回传的错误码和所使用的URL Scheme有关
如果使用HTTP或WSP架构,会回传HTTP错误码。
如果给予的contentType错误的话,则会回传invalid
范例:var a="http%3a2f%2fw.a.c%2fdck%3fx%3def%23crd";
var b=URL.unescapeString(a); //b
="http://w.a.c/dck?x=12#crd"

loadString

程序:loadString(url,contentType)
说明:回传有所给予的绝对URL与contenttype所指出的内容。
如果内容格是不是下列法则所规范的话,则是错误的:
你只能界定一种内容格式,整个字符串必须和一种内容格式相符,而 且你不能有额外的前或后空格。
格式必须是正文,但次格式没有限制,格式的开头一定是"text/"。
这个程序的动作如下:
文件的内容会载入使用给予的contentType与url,其他内文所需的数形式有使用用户界面的预设面。
如果载入成功而且回传的内容为格式与所给予的contentType相符,则内文会被转换成字符串再回传。
如果载入成功或回传的内文格式不正确的话,则会回传特定的错误码。
参数:url=字符串
contentYype=字符串
回传值:字符串、整数或invalid
例外状况:如果载入失败其回传的错误码和所使用的URL Scheme有关
如果使用HTTP或WSP架构,会回传HTTP错误码。
如果给予的contentType错误的话,则会回传invalid
范例:var myUrl="http://www.acme.com/vcards/myaddr.vcf";
myCard=URL.loadString(myUrl,"text/x-vcard");

6.6 WML浏览器函数库

名称:WML Brower
说明:这个函数库所包含的程序是让WML Script用来存取与WML相关的内文,这些程序不能有任何的副作用,并在下列的状况下回传invalid值。
系统不支持WML浏览器。
WML浏览器无法使用WML Script解译器。

getVar

程序:getVar(name)
说明:回传目前浏览器内文的所给予名称name的变量值。
如果所指定的变量不存在,回传一个空字符串。
变量名称必须依照WML语法来使用。
参数:name=字符串
回传值:字符串或invalid
例外状况:如果变量名称不合语法,则回传invalid
范例:var a=WMLBrowser.getVar("name");
// a"Jon"或者变量的值

setVar

程序:setVar(name,value)
说明:在目前的浏览器之中,如果所给予名称name的变量,它的值同给予的值value设定的一样的话,回传ture,否则回传false。
变量名称必须依照WML语法来使用。
变量值必须是合法的XML CD ATA
参数:name=字符串
value=字符串
回传值:布尔值或invalid
例外状况:如果变量名称或它的值不合语法,则回传invalid
范例:var a=WMLBrowser.setVar("name",Mary); // a=true

go

程序:go(url)
说明:将给予的url所标记的内文载入,这个程序予WML的GO动作意思相同。
如果所给予的url字空字符串(""),则不会载入任何内文。
go()与prev()函数库程序会互相推翻,在回传控制与WML浏览之前都可以加以调用多次。
只有最后的调用设定的会保持作用,如果最后的调用为go()或prev(),其所设定的url为空字符串(""),所有的要求都会被取消。
这个程序回传空字符串。
参数:url=字符串
回传值:字符串或invalid
例外状况:无
范例:varcard="http://www.acme.com/loc/app.dck#start";WMLBrowser.go(card
)

prev

程序:prev()
说明:告诉WML浏览器回到先前的WML Card,这个程序的功能与WML中的prev动作一样。
go()与prev()函数库程序会互相推翻,在回传控制与WML 浏览之前都可以加以调用多次。
只有最后的调用设定是会保持作用,如果最后的调用为go()或prew(),其所设定的url为空字符串(""),所有的要求都会被取消。
这个程序回传空字符串。
参数:无
回传值:字符串或invalid
例外状况:无
范例:WMLBrowser.prev();

newContext

程序:newContext()
说明:将目前WML浏览器的内文清除并回传一个空字符串,这个程序的公用与WML的NEWCONTEXT属性一样。
参数:无
回传值:字符串或invalid
例外状况:无
范例:WMLBrowser.newContext();

getCurrentCard

程序:getCurrentCard()
说明:回传目前WML浏览器所处理card的最小相关URL,如果WML deck所包含目前程序的基本地址不同的话,则此程序会回传绝对URL。
参数:无
回传值:字符串或invalid
例外状况:如果没有目前的card,则回传invalid。
范例:var a=WMLBrowser.getCurrentCard();// a="deck#input"

refresh

程序:refresh()
说明:强制WML浏览器更新它的内文并回传一个空字符串,而用户界面会加以更新以反应更新后的内容,这个程序与WML中的refresh功能一样。
参数:无
回传值:字符串或invalid
例外状况:无
范例:WMLBrowser.setVar("name","Zorro");
WMLBrowser.refresh();

6.7 Dialog函数库

名称:对话
说明:这个函数库包含典型的用户界面程序。

prompt

程序:prompt(message,defaultInput)
说明:显示给予的信息message与用户输入的提示符号,defaultInput参数包含了用户输入所需的初始内文,回传用户输入。
参数:message=字符串
defaultInput=字符串
回传值:字符串或invalid
例外状况:无
范例:var a="09-555 3456"; var b=Dialogs.prompt("Phome number";a);

confirm

程序:confirm(message,ok,cancel)
说明:显示所给予的信息message与两个选项:ok与cancel,等待用户选取其中一个,如果是ok则回传false。
参数:message=字符串
ok=字符串
cancel=字符串
回传值:布尔值invalid
例外状况:无
范例:function onAbort(){return Dialogs.confirm("Are you sure?"),"Yes","No";};

alert

程序:alert(message)
说明:显示所给予的信息message给用户,等待用户确定并回传一个空字符串。
参数:message=字符串
回传值:字符串或invalid
例外状况:无
范例:function testValue(textElement){
if (String.length(textElement)>8) {
Dialogs.alert("Enter name <8 chars!");
};
};

6.8 函数库总结

函数库

函数库名称:

Lang

Float

String

URL

WML Browser

Dialogs

 

函数库与他们的程序:

Lang 函数库

Abs

Min

Max

ParseInt

ParseFloat

IsInt

IsFloat

MaxInt

MinInt

Float

Exit

Abort

Random

Seed

CharacterSet

 

Float 函数库

Int

Ploor

Ceil

Pow

Round

Sqrt

MaxFloat

MinFloat

 

String 函数库

Length

IsEmpty

CharAt

SubString

Pind

Replace

Elements

ElementAt

RemoveAt

ReplaceAt

InsertAt

Squeeze

Frim

Compqre

ToString

format

 

URL 函数库

IsValid

GetScheme

GetHost

GetPort

GetPath

GetParameters

GetQuer

GetFragment

GetBase

GetReferer

Resolve

EscapeString

UnescapeString

loadString

 

WML   Browse 函数库

Get Var

SetVar

Go

Prev

NewContext

GetCurrentCard

Refresh

 

Dialogs  函数库

Prompt

Confirm

Alert


添加评论
单击隐藏此项的评论。

WAP教程(五)

第五章 WMLScript脚本程序设计(上)
(Penny 2001年05月25日 16:17)

作为一种编辑语言,WMLScript提供了强大的函数、语句和库功能,以及外部编辑、访问控制等支持,同时对程序运行中可能产生的错误给出了检测手段和具体的解决办法。这些内容属于WMLScript的脚本程序设计知识和进一步的编程规定,我们本章就对此进行详细介绍。

5.1 语句

前面我们学习了变量、操作符和表达式,但仅由这些内容并不能完成某个完整的功能,因为他们不能形成完整的操作或处理程序。变量就如同与严重的单词,表达式如语言中的词组,他们都不能表达一个完整的意思;只有语句,是语言中完整的句子,能够表达完整的意思并实现某个完整的功能。WML Script提供了丰富的语句功能,使用这些语句我们可以在WML的卡片中建立交互功能和其他需要的复杂功能。

在WML Script中,每条语句的后面都需要以一个分号(;)结尾。为了养成严谨的编程风格,建议大家编写脚本时,语句后一定要加上分号(;),这也有助于我们形成一种良好的编程习惯。

WML Script语句的书写和排列格式比较自由。我们可以在同一程序行中连续写上多个语句,也可以把同一语句分成多行排列。WML Script将根据分号(;)来确定语句的具体内容。

WML Script的语句主要包括两类。第一类是基本语句,如空语句、表达式语句、块语句、变量语句和return语句等;第二类是条件语句,如if语句;第三类是循环语句,如while语句、for语句、break语句和continue语句等。下面我们分别讲解这些语句的语法、功能和使用方法。

5.1.1 基本语句

WML Script基本语句主要用于程序格式控制和变量声明,其中有些语句我们已经不太陌生了。

空语句

空语句用于定义一个空的程序行,它没有任何标识符和操作符,也不执行任何操作。它只是以分号(;)结束。其语法格式为:



显然,空语句是一种十分特殊的语句。由是我们为了让程序具有更好的可读性,通常在程序中的适当地方加上几个空语句,以起到分隔或突出的作用。例如,下面的几行程序中就含有一个空语句:

str="Hello";

val=25;

;

MyVal=val*val+5;

alert("Hi,Hi!!!");

再如,while语句用于判断一个条件并在条件满足的时候执行相应的任务,但如果希望条件满足的时候什么也不作,那么就可以给它配上一个空语句,使之条件满足的执行空操作:

while(!poll(device));

这实际上是while语句和空语句组成的两条语句。其中的分号(;)在这里就代表了空语句。这两条语句的作用是在poll()函数为真()之前一直等待。

表达式语句

表达式语句用于向变量赋值,或进行数学计算,或进行函数调用。表达式语句也是我们最常用的一种语句,语法格式为:

表达式;

下面几行程序都是合法的表达式语句:

str="Hey"+yourName;
val3=prevVal+4
counter++;
myValue1=counter,myValue2=val3
alert("Watch out!");
retVal=16*Lang.max(val3,counter);


块语句

块语句使用两个花括号({ })包含一个语句集,形成一个语句体。WML Script的许多语句都需要使用块语句来实现语句体,快语句的语法格式为:

{

语句列表;

}
下面的简单程序就是使用块语句的例子:


}
vari=0;
var x=Lang.abs(b);
popUp("Remember!");

}

变量语句

变量语句用于生命变量并可进行变量的初始化赋值。如果用户不赋值,那么WML Script会自动将变量语句生命的变量赋予一个空字符串("")。基本的语法格式为:

var 变量名;

如果像一次生命多个变量,则相邻变量名之间使用逗号(,)间隔,其语法格式为:

VAR 变量名1,变量名2......,变量名n;

如果想在生命变量时同时初始化变量,则可按如下语法格式书写:

var 变量名=初始化

为便于大家更好的掌握变量语句,我们给出一个多出使用该语句的程序:


function count(stu){

var result=0; //声明变量的同时初始化变量

while(str!=""){

var ind=0; //每次循环都初始化一次

// 为退出循环,本块语句内应当提供修改变量str值的语句

};

return result

};

function example(param){

var a=0;

if(param>a){

var b=a+1; //声明b变量的同时使用a变量初始化b变量
}else{

var b=a+2; //声明c变量的同时使用a变量初始化c变量
};

return a; //返回a变量的值

};


注释语句

严格来讲,注释语句在WML Script中还不算是真正的语句,它只是一种前指向的规定。不过它也有严格的语法和标注方法,所以我们这里还是像其他编程语言处理的一样,把WML Script注释方法以语句的形式介绍一下。

注释在程序执行的时候没有任何作用,但是可以用于对程序进行解释,则增强程序的可读性。为了形成良好的编程风格,我们应该养成书写注释的良好习惯,注释有两种表达方式:

(1)通过双斜线注释一行,这样在双斜先后的字符将成为注释而不被执行。该注释行可以单独一行书写,也可以放在其他语句的后面。

例如,可以进行如下所示的注释:

//变量j用于小数每月的天数

j=0; //我们这里将j赋值为0

(2)通过符号“/*”和“*/”来规定注释语句,这种注释方式可以进行多行注释,符号“/*”和“*/”之间的内容就是注释语句。例如,可以进行如下所示的多行注释:

/*我们定义了两个变量:i和j。其中:

i用于描述每年中的月数,

而j用于描述每月的天数*/

j=0; /*我们这里将j赋值为0*/

return语句

return语句主要用在函数体中,在函数结束前,可以通过return语句,把函数处理的结果返回给调用函数的语句。它的语法格式如下:

return表达式;

下面的函数给出了应用return语句的例子:


function square(x){

if(!(Lang.isFloat(x)))return invalid;

return x*x

};


5.1.2 条件语句

在条件语句中,当满足某种条件时 ,就会执行指定的一些代码,而在代码组另外某种条件时,则会执行另外一些代码。WML Script的条件语句就是if...else语句,它的一般表达相识如下:

if(条件){

代码块1

}

else{

代码块2

}


这样,当条件满足时,就执行代码块1;如果条件不满足则执行代码块2。代码块和代码块2中如果只有一个条语句,那么,花括号({ })就可以省略;而如果有多条语句,则必须实用花括号将代码块包括在其中。在if...else语句种,其中的else部分是可选的,也就是说,我们可以使用如下的表达形式:

if(条件){

代码块

}

这样,当条件满足时,就执行代码块,如果条件不满足则什么也不做。

例如,如果我们需要对一个学生的成绩进行判定,如果大于等于60分,那么我们就认为该学生成绩合格了,反之则认为不合格,同时一并将状态记录到变量status种,相应的WMLScript语句如下所示:

if(score>=60) status="pass";

else status="fail";

再如,我们可以通过对天气是否阳光普照(sunShines)的情况进行判断,来给变量myDay赋值,并累计好天气(goodDays)的天数。程序如下:

if(sunShines) {
myDay="Good";

goodDays++;

}else

myDays="Oh well...";


5.1.3 循环语句

使用循环语句可以反复执行某个代码块,直到循环结束条件满足后才停止执行。WML Script中有两种循环语句:for语句和while语句,同时还有两终于循环密切相关的操作语言:break语句和continue语句。

for语句

for语句可以创建一个带条件的循环,它还有3个可选的条件表达式,用于控制循环。这3个条件表达式放在一个括号里,并以分号(;)间隔。for语句的一般语法形式如下:

for(初始表达式;循环条件;递增表达式){

代码块

}


for语句的执行主要包括以下几个步骤:

(1)执行初始表达式。在一般情况下,初始表达式完成的功能是在循环中对循环计数器赋初值。所以在这种意义上,初始表达式也可以采用“var 变量声明列表;”的形式来定义。

(2)判断循环条件。如果循环条件为真(ture),则执行循环体中的语句,即至步骤(3);否则,循环条件为假(false)或者invalid,就结束循环;

(3)执行循环代码。然后,在执行递增表达式。一般情况下,我们在递增表达式中对循环计数器进行处理,最后在返回步骤2执行。

例如,下面的for语句建立了一个循环。初始表达式为定义变量index并付初值0,循环条件为index<100,递增表达式为每循环一次index增加1。当index增加到100时候,循环结束。程序如下:


for(var index=0;index<100;index++){

count+=index;

myFunc(count);

};


while 语句

while语句也可常见一个循环,它的一般语法表达式如下:

while(循环条件){

代码块

}


while语句的执行过程包括以下几个步骤:

(1)判断循环条件是否为真。如果循环条件为真,则执行循环;如果为假或为invalid,则跳出循环。

(2)执行循环中的代码块,然后返回步骤(1)

下面的程序就是使用while语句的简单例子:

var counter=0

var total=0

while(counter<3){

counter++;

total+=c;

};


其中建立的循环仅当变量counter的值小于3时执行,否则就结束循环。

显然,如果循环条件不能为假或为invalid,那么while循环就会无休止的反复执行下去。因此,我们在代码块中一定要有能够改变循环条件的变量,否则,就很有可能会陷入死循环而不能终止程序,下面就是一个死循环的例子:

var x=1;

var y=0;

while(x<=1){

y=x+1;

}


这个程序中,因为变量x的值在循环中不能发生变化,所以循环条件在判断的时候永远为真,所以成为了死循环。因此,对于while语句我们往往使用如下所示的语法形式:

初始表达式

while(循环条件){

代码块

递增表达式

}

这种情况下,while语句的功能和for语句的功能就一样了,不过用while语句编写的程序可读性更强一些。所以我们也可以采用while语句来完成index增加到100的循环。

程序如下:

var index=0

while (index<100){

counter+=index;

myFunc(count);

index++;

};


break语句

为了更好的解决死循环问题,WML Script项大多数编成语言一样提供了break语句。break语句可以使程序执行跳出循环。不论是for语句还是while语句,只要在循环中使用了break语句,那么程序执行到break语句后就立即跳出当前循环,然后继续执行下去。

break语句的予发行时如下:

break;

例如,在下面的函数中我们使用了break语句,它是当index=3时跳出循环。如果不是用该语句,函数中的while循环直到index=6时才可以结束。程序如下:

funcition testBreak(x){

var index=0;

while(index<6){

if(index==3)break;

index++

};

retrun index*x;



continue语句

continue语句的功能和break语句的功能看起来有些类似,但实际上却不一样。循环执行时遇到break语句通常是跳出当前循环,但循环执行到 continue语句并不跳出当前循环,而是不执行循环中在continue语句后面的代码块,直接结束循环的本轮运行,然后马上开始下一轮循环的运行。

在while语句的循环中,遇到continue语句后,程序会直接判断循环条件从而开始下一轮循环。在for语句的循环中,遇到continue语句后程序会直接执行递增表达式,然后判断循环条件从而开始下一轮循环。

例如,我们想利用for循环求1到10之间偶数的和,其WML Script语句如下:

var sum=0;

for (var j=1;j<=10;j++){

if(j%2!=0)

continue;

sun+j;

};


在这个例子中,在j%2!=0的情况下,也就是j为奇数的情况下,程序执行continue语句,这时,并没有如同break语句一样跳出循环的运行,而是不执行循环中后面的语句而直接执行递增表达式开始下一轮循环的执行,这样,就可以不将其数j的之类即如总和中。

再如,我们想利用while循环求0到4之间出3以外几个数的和,则可以使用continue语句进行控制。程序如下;

var index=0;

var count=0;

while (index<5){

index++;

if(index==3)

continue;

cont+=index;

};


这以程序中,当index等于3时,“index==3”为真,所以执行continue语句,不再把此时index的值加大count中,而是开始下一轮的循环。


第五章 WMLScript脚本程序设计(下)
(Penny 2001年05月25日 16:17)

5.2 函数的声明与调用

在WML Script中,函数是一种能够完成某种功能的代码块,并可以在脚本中被事件处理或被其他语句调用,也可以被WML程序所处理和调用。一般地,当我们编写 WML Script脚本时,如果脚本中的代码长度还是很长,则一般还可以根据功能将函数再进行划分,分成为几个功能更加单一的函数。虽然说这样对长代码的处理方法并不是编写脚本程序的强制性要求,但通过函数的划分和运用,我们可以使得WML Script脚本具有更好的可读性,也便于我们对脚本程序的编写与调试。而且,如果在某些脚本中有多处完全相同的代码块,那么我们也可以将这些代码快些为一个函数,然后在脚本中调用这个函数,从而提高代码的重要性,简化代码的编写工作。

WML Script的函数共用和Jave语言、C/C++语言的函数有所不同。我们知道,Jave语言、C/C++语言中有函数和过程之分,函数能够完成一定的功能并有返回值,而过程进可完成一定的功能但没有返回值。可是,WML Script中并不区分函数和过程,因为它只有函数,没有过程。WML Script的函数完成一定功能后始终有返回值,不过返回值分两种情况,即非空的返回值和空字符串("")形式的返回值。前者是真正的返回值,后者其实相当于没有返回值。也就是说,WML Script中的函数同时具有其他语言中的函数和过程的功能。

5.2.1 函数的声明

使用函数时,要根据函数的调用使用,而调用函数前必须声明函数,也就是需要先定义函数。WML Script中定义函数的一般方式如下:

function函数名(参数列表)

{

代码块

};

另外,WML Script规定使用extern关键字来声明一个外部函数:

extern function函数名(参数列表)

{

代码块

};

从中可以看出,函数的定义有以下3部分组成:

(1)函数名。即函数的名称,其命名规则应遵守WML Script的标识规则。调用函数时都是通过函数名进行调用的,所以函数必须要有函数名。

函数命名时,一般要使用能够描述函数功能的但此来作为函数名,也可以使用多个单词组合进行命名,这样做的好处是能够提高WML Script脚本的可读性。

函数名在同一个WML Script脚本文件里必须是唯一的。如若不然,则会导致函数定义混乱。

(2)参数列表。即调用函数时需要的参数。参数列表通常是可选的,有的函数需要,有的函数可能不需要。参数列表的作用是向函数传递一些参数,使得函数可以直接使用这些参数的值。

调用函数的时候,参数个数和类型必须和函数定义示所声明的参数个数即类型保持一致。而且函数的参数就如同似函数体内的局部变量,它们在函数调用的时候被初始化。

(3)代码块。它是函数的主体部分。代码块中的代码包含在以对花括号({ })中,代码块可以执行并完成函数的功能。编写代码块是应当遵循WML Script的编程规则。

有时,函数需要返回一个值给调用函数的语句,则应该在代码块的后面一行使用return语句,返回所需的数值。

与C/C++等语言类似,WML Script的函数是可以嵌套的,以就是说,在一个函数中还可以调用其他函数。但是,函数声明是不能嵌套,这是WML Script的强制性规定。

下面几行语句就是定义函数的简单例子:

function currencyConverter(currency,exchangeRate)

{

return currency*exchangeRate;

};


其中,该函数的名称为currencyConverter,参数有currency和exchangeRate两个,函数代码块包含一条语句,用于返回currency和exchangeRate的乘积。

下面是一个使用extern定义外部函数的例子。其中函数名为textIt,它没有参数,函数体中定义了两个赋值变量,一个赋整数,一个赋函数值:

extern function testIt(){

var USD=10;

var FIM =currencyConverter(USD,5.3)

};

5.2.2 函数的调用

编写好的函数必须经过合法的调用,才可以发挥它应用的作用。函数调用将返回一个值,比如一个计算结果。WML Script中的函数主要可以分为内部函数、外部函数和库函数,下面我们就介绍这3类函数的调用方法。

内部函数

所谓内部函数是指函数的定义与其调用函数在同一个脚本文件内的函数,对内部函数的调用称为内部调用。内部函数的调用非常简单,只需提供函数名和所需参数值即可,参数值必须和函数定义时指定的参数个数即类型一致。而且函数调用需要使用操作符来接收或处理被调用的返回值。

内部函数可以在其定义之前调用,也可以在其定义之后调用。例如,下面就是一个在函数定义之后调用的例子。


function test1(val){

return val*val;

};

function test2(param){

return test1(param+1);

};


这个例子中定义了两个函数test1和test2。test1函数用于计算给定参数值的平方并将结果返回;test2函数将给定的参数值加1,然后这个和为参数值,来调用test1函数,得到结果后在将给结果返回到调用test2函数的语句。

注意,本例中test2函数调用了test1函数,这种在函数中调用其他函数的方法称为函数调用嵌套。WML Script的内部函数、外部函数和库函数都支持嵌套调用,后面我们专门介绍这方面的内容。

外部函数

外部函数使一个在WML Scrupt外部文件中定义的函数。调用外部函数的方法与调用内部函数的方法基本类似,不同之处在于调用处外部函数时一是要指定外部文件的地址即名称,二是要在调用的外部函数名的前面加上外部文件的名称。

WML Script规则使用use url来指定外部文件,语法格式为:

use url还有外部函数的外部文件名 外部文件所在的URL;

这样,WML Script的预编译头就可以将外部文件映射为一个可以在内部使用的标识。然后,使用这个标识并加上井号键(#)和标准的函数调用即可实现外部函数调用,语法格式为:

外部文件名#外部函数(参数列表);

例如,http://www.host.com/script下有我们需要的外部文件,名为OtherScript,所以我们可使用use url来指定该文件:

use url OtherScript"http://www.host.com/script"

这一外部文件中含有我们需要调用的外部函数testme,则可采用“外部文件名#外部函数(参数列表)”的形式来调用它:

OtherScript#testme(param+1);

这个例子完整的写出来,就是下面的程序:

use url OtherScript"http://www.host.com/script"

function test(param){

return OtherScript#testme(param+1);

};

库函数

特别指定,WML Script的库函数一律是指它的标准库函数。因为与标准库函数对应,WML Script还有一些非标准的库函数。我们这里先介绍标准库函数,非标准库函数后面再介绍。

所有库函数都有所数的库,函数的库中通常含有一类函数。因此,调用某个库函数时,一要指定它的库名,二要指定它的函数名。WML Script规定,调用标准库函数时可以通过在函数库的名字后面加上句点号(.)和库函数的标准调用来实现,语法格式为:

函数库名.函数名(参数列表);

例如,WML Script的浮点库即Float库中有一个开根方的函数sqrt,该函数只有一个参数,那么调用squrt库函数的方法为:

Float.sqrt(number);//这里要求number大于或等于0

下面给出了调用库函数的简单例子。首先一param参数值调用Lang.abs()函数,返回结果加1后再作为参数调用Float.sqrt()函数,它的返回结果作为内部函数test的返回值:

function test(param){

return Float.sqrt(Lang.abs(param)+1);

};

2.3 函数的嵌套调用

WML Script的函数定义都是互相平行、独立的,定义函数的时候我们不能在一个函数内定义另外一个函数,也就是说,函数定义是不能嵌套的。但是,函数调用确是可以嵌套的,也就是说,我们可以在调用一个函数的过程中调用另外一个函数。

它的执行过程是:

(1)执行a函数开头部分;

(2)遇到调用b函数的操作语句,流程则专区执行b函数;

(3)执行b函数开头部分;

(4)遇到调用c函数的操作语句,流程则专区执行c函数;

(5)执行b函数,如果没有其他嵌套的函数,则完成c函数的全部操作;

(6)返回调用c函数的语句,即返回到b函数;

(7)继续执行b函数中尚未执行的操作,直到b函数结束;

(8)返回a函数中调用b函数的语句;

(9)继续执行a函数的剩余操作,直到函数结束。

function myFunC(param1){

return param1*param1=Float.squt(Lang.abs(param)+1);

};

function myFunB(param0){

return myFunC(param0+1)*|param0+12;

};

function myFunA(param){

return myFunB(param*param+1);

};


5.3 预编译

WML Script的预编译主要用于在编译阶段控制编译器的行为。与编译头一般在文件开头和函数声明之前指定,WML Script规定所有的预编译头都是一关键词use加上指定的预编译属性进行指定。

在大多数的编程中,我们比较长用的预编译行为主要涉及外部文件声明、访问权和Meta信息设置。

5.3.1 外部文件

我们知道,使用URL地址可以定位一个WML Script文件。利用该URL地址;在WML Script编程中我们可以通过预编译来调用WML Script的外部文件,外部文件预编译头的声明方法是use url,其语法格式如下:

use url外部文件名 "URL"地址

这样,我们在当前文件的编程中就可以使用该预编译头声明的外部文件,从而可以调用该外部文件的函数。其语法格式为:

外部文件名#函数名(参数列表);

例如,我们希望在当前的WML Script程序中调用OtherScript外部文件中的check()函数,而且我们知道OtherScript文件的URL地址为http: //www.host.com/app/script。因此,我们可以使用use url来声明这一外部文件:

use url OtherScript"http://www.host.com/script"

随后,我们就可以在程序中调用OtherScript中的check()函数了:

function test(par1,par2)

{

return OtherScript#check(par1,parr2);

};

其中调用执行的过程如下:

(1)找到WML Script外部文件的URL地址;

(2)当前函数从指定的URL地址值装载外部文件;

(3)检测外部文件的内容,并执行其中的check()函数。

ure url 预编译头指定的外部文件名在当前程序中必须唯一,用户不能指定不同URL地址的同名外部文件,否则在调用外部文件时就会发生混乱。

另外,use url预编译头中的URL地址也可以是相对URL地址。相对URL的起始位置是当前程序文件所在的位置,并在此基础上根据URL进行定位。

如果URL地址中的字符包含有转义字符,则WML Script将根据转义要求进行转义。不过,程序在编译的时候编译器并不会对他们进行转义,而是在程序执行时完成,检查URL格式和URL地址的有效性。

5.3.2 访问权限

我们可以使用访问权限预编译设保护文件的内容,实现访问控制。WML Script编程中,必须在调用外部函数之前使用访问权限预编译头声明外部文件的访问权限。不过,WML Script访问权限检查的缺省值是不进行检查,即disabled.但访问权限一经声明,以后当调用外部函数的时候,编译器就会检查外部文件的访问权限,以决定调用这是否有权使用该文件及其内含函数。

访问权限预编译头的声明方法是use access,其语法格式如下:

use access domain操作域名 path操作路径:

访问权限预编译头通过指定domain和path属性来决定编译器将要进行什么样的检查工作。如果文件有domain或者path属性,那么文件所在的URL就必须和属性中的值一致。比较时,域和路径都依据URL大写规则进行比较。具体的比较预则如下:

(1)操作域与URL中的域后缀相匹配。与后缀匹配是值所有的子域从后向前都必须一致。例如:www.wapforum.org和wapforum.org相匹配,而与forum.org并不匹配。

(2)操作路径和URL中的路径前缀相匹配。路径前缀匹配是值从前向后必须一致。例如:“/X/Y”与“/X”相匹配,而不是和“/XZ”相匹配。

(3)却省的domain数行为当前的文件域,就是“/”。

不过,为了简化编程,有时WMLScript并不需要直到外部文件的绝对路径,我们只需提供文件的相对URL即可,用户浏览器执行程序是卡相对路径自动转换为绝对路径,根据路径属性进行匹配。例如:如果访问权限预编译头及其指定属性为:

use access domain"wapforum.org"path"/finance";

则可以使用以下的路径来调用指定文件中的外部函数,它们都符合相对URL地址匹配规则:

http://wapforum.org/finance/money.cgi

http://www. wapforum.org/finance/money.cgi

http://www. wapforum.org/finance/demos/packages.cgi?x+123&y+456

而以下的路径调用则非法的,因为它们或者操作域不对,或者URL地址不能与指定的相对URL相匹配:

heep//www.test.net/finance

http//www.qapforum.org/internal/foo.wml

需要强调指出的是,WML Script规定,同一程序中只能定义一个访问权限与编译头,否则就会导致编译错误。

5.3.3 Meta 信息

我们还可以通过与编译头的形式声明WML Script文件的Meta信息。Meta信息主要用于指定文件所需Mete属性的属性名(Property name)、属性值(Content)以及文件的配置(信息),属性都属于字符串类型的数据。Mate信息域编译头使用use meta声明,其语法格式为:

usr meta 属性 该属性Meta信息:

Meta的属性主要包括Name、HTTP Equiv和User Agent三种,下面我们分别讲解它们的声明方法:

(1)Name。该属性用于指定服务器使用的Meta信息。这些信息仅供服务使用,用户浏览器并不理会这些信息。

例如,以下Name属性的Meta信息指定了服务器的创建时间:

use meta name "Created""26-June-2000";

该信息只会作用于服务器,而不会影响用户浏览器的操作。

(2)HTTP Equiv。该属性用于指定需要解释为HTTP头的Meta信息。对于已经编译的文件来说,当它到达用户浏览器前,WML Script将根据HTTP Equiv属性指定的Meta信息将文件转换为WSP或HTTP的响应头,进行文件的解释和执行。

例如,以下声明的http equiv属性指定按照脚本语言的关键字来解释当前文件:

use meta http equiv"Keywords""Script,Language";

(3)User Agent。该属性用于定义用户浏览器使用的数据类型。例如:

use meta user agent"Type""Test";

它指定当前数据必须立即发送给用户浏览器,然后马上清除掉。

5.4 执行时的错误检测与处理

WML Script函数的功能提供用户服务,并希望用户界面能在任何的状况下运作顺利,因此错误的处理是最大的课题,这表示了语言可能不提供预期的机制,如他应该可以防止错误发生或提醒用户注意并采取适当的动作,种植储蓄执行是最后的手段。下面几个小节列出了当为码下载并执行时会发生的错误,一些程序上的错误并不在谈论的范围(如无穷循环),像这类的例子就需要手动来终止。

5.4.1 错误检测

错误检测工具能让你检测错误但会干扰系统的动作,因为WML Script是弱格式语言,所以由一些特殊功能的工具来检测有invalid数据格式所引起的错误:

检测给定的变量包含的是正确值:WML Scritp含有格式确认函数库程序如:Lang.isInt()Lang.isFloat()、Lang.parseInt()、Lang.parseFloat。

检测给定的变量包含的只是正确的格式:WMLScript含有运算符typeof与isvalid能让你使用。

5.4.2错误处理

错误处理是在发生错误之后,有些状况是错误检测无法防止的,如内存限制后外部信号等,或者是数据很难处理,如溢出(overflow)或亏失(underflow),而这些状况可以分为两类:

严重错误(fatalerror):这种错误会造成程序终止,因为WML Scritp程序会让一些用户界面调用,程序终止通常会跟调用它的用户界面发出信号,用户界面就会告知用户这个错误。

错误(non-fatalerrow):这种错误会把信号传回程序,如一些特殊的值,然后由程序决定所要采取的行动。

下列的错误是根据他们的严重性来区分。

5.4.3 严重错误(fatalerror)

下面的小节会讨论WML Script的严重错误。

位码错误(bytedode error)

这些错误跟位码与由WML Script位码解译器所执行的指令有关他们指出了错误的元素群、无效的指令、指令所使用的参数无效,或指令无法执行。

验证错误(verification failed)

说明:调用的程序中的特定位码无法通过验证。
如何发生:每次程序试着用外部程序。
范例:var a = 3*OtherScript#doThis(param)
严重性:严重。
判定状况:当检测位码验证式。
解决方法:终止程序与WML Script解译其调用者的错误信号。

说明:调用一个函数库程序时发生严重错误。
如何发生:每次调用函数库程序。
范例:var a = string.format(param)
严重性:严重。
判定状况:无
解决方法:终止程序与WML Script解译其调用者的错误信号。
说明:调用函数参数的数目跟被调用函数的参数数目不符合。
如何发生:调用外部程序。
范例:编译器参生一个无效的参数给予指令使用,或者被调用的程序参数数目改变了。
严重性:严重。
判定状况:无
严重性:严重。
解决方案:终止程序与WML Script解译器调用着的错误信号。

说明: 在特定的程序中找不到所需要的外部程序。
如何发生:调用外部程序。
范例: var a =3*OtherScript#doThis(param)
严重性:严重。
判定状况:无
解决方案:终止程序与WML Script解译器调用着的错误信号。


说明: 由于在网络服务器的程序存取又无法修复的错误或特定程序并不在网络服务器中所引起的程序无法载入。
如何发生:调用外部程序。
范例: var a =3*OtherScript#doThis(param)
严重性:严重。
判定状况:无
解决方案:终止程序与WML Script解译器调用着的错误信号。

说明: 存取错误,所调用的外部程序加了保护。
如何发生:调用外部程序
范例:var a =3*OtherScript#doThis(param)
严重性:严重。
判定状况:无
解决方案:终止程序与WML Script解译器调用着的错误信号。

说明: 因为程序错误造成stack underflow。
如何发生:程序要取出(pop)一个空堆
范例: 当组译器产生错误码。
严重性:严重。
判定状况:无
解决方案:终止程序与WML Script解译器调用着的错误信号。

说明:执行调用Lang.abort() 是发生的错误。
如何发生:每当程序调用Lang.abort()函数。
范例: Lang.abort("unrecoverable error")
严重性:严重。
判定状况:无
解决方案:终止程序与WML Script解译器调用着的错误信号。

说明:发生堆栈溢出。
如何发生:程序资源太多或要推入太多的变量到运算之中。
范例: function f|(x)(f(x+1););
严重性:严重。
判定状况:无
解决方案:终止程序与WML Script解译器调用着的错误信号。


说明:没有多余的内存可供解译器使用。
如何发生:作业系统无法配置多余的空间给解译器适使用。
范例: function f(x){
x=x+"abcdefghijklmnopqrstuvxyz";
f(x) ;
};
严重性:严重。
判定状况:无
解决方案:终止程序与WML Script解译器调用着的错误信号。

说明:用户终止程序的执行(如按下reset钮)
如何发生:随时。
范例: 当应用程序正在执行是用户按下reset钮。
严重性:严重。
判定状况:无
解决方案:终止程序与WML Script解译器调用着的错误信号。

说明:当程序执行中,发生了外部严重的错误。
如何发生:随时。
范例: 电力微弱,系统自动。
严重性:严重。
判定状况:无
解决方案:终止程序与WML Script解译器调用着的错误信号。

5.4.4 一般错误(Nonfatal error)

下面说明了WML Script的一般错误:

计算错误(computational error)

这些错误是由于WML Script数学上的运算所造成。

除以零(divide by zero)
说明:发生了除以零的状况
如何发生:当程序中有除以零的状况。
范例:var a= 10;
var b= 0;
var x= a/b;
var y= a div b;
var z= a%b;
a/=b;
严重性: 一般。
判定状况:高
解决方案:产生结果为invalid。

说明:发生了除以零的状况
如何发生:程序要执行浮点数运算。
范例:var a = Float.precision();
var b = Float.precision();
var c = a* b
严重性:一般。
判定状况:高,在某些状况很困难。
解决方法:产生的结果为浮点数值0.0

常数参考错误(constant reference error)

说明:所参考的浮点数实字为not a number。
如何发生:程序试着存取一个浮点数实字但组译器产生了not a number的浮点数常数。
范例:参考浮点数常数。
严重性:一般。
判定状况:高
解决方法:这会产生invalid值。

说明:参考的浮点数实字不是正无穷大就是负无穷大的浮点数常数。
如何发生:程序试着存取一个浮点数实字但组译器产生了正无穷大或负无穷大的浮点数常数。
范例:参考浮点数常数。
严重性:一般。
判定状况:高
解决方法:这会产生invalid值。

说明:需要参照浮点数值所发生的错误。
如何发生:程序需要使用浮点数值但环境值支持整数值。
范例:var a = 3.14;
严重性:一般
判定状况:高
解决方法:这会产生invalid值。

转换错误

这个错误的发生同WML Script所支持的自动转换有关。

说明:欲转换成整数值,但这个值超过整数所能接受的范围(正或负)。
如何发生:程序试着自动转换成整数时。
范例: var a = -"99999999999999999999999999999999999999999";
严重性:一般
判定状况:高
解决方法:这会产生invalid值。
说明:欲转换成浮点数,但这个值小于浮点数所能接受的范围(正或负)。
如何发生:程序时值自动转换成浮点数时。
范例:var a = -"99999999999999999999999999999999999999999";
严重性:一般
判定状况:高
解决方法:这会产生invalid值。

说明:欲转换成浮点数,但这个值小于浮点数所能接受的范围(正或负)。
如何发生:程序时值自动转换成浮点数时。
范例:var a = -"99999999999999999999999999999999999999999";
严重性:一般
判定状况:高
解决方法:这会产生浮点数0.0。

添加评论
单击隐藏此项的评论。

WAP教程(四)

第四章 WML Script语法基础
(Penny 2001年05月25日 16:17)

WML Script是属于无限应用协议WAP应用层的一部分,使用它可以向WML卡片组和卡片中添加客户端的处理逻辑,目前最新的版本是1.1版。WML Script1.1是在欧洲计算机制造商协议会制定的ECMAScript脚本语言的基础上,经过修改和优化而指定的。它能够更好的支持诸如移动电话类的乍带宽通信设备,在WML编程中使用WML Script可以有效的增强客户端应用的灵活性,而且,我们也可以把WML Script作为一个工具使用,开发出功能强大的WAP网络应用和无限网页。本章我们将详细讲解WML Script1.1编程的基础预法制时,如基本规则、变量预数据类型、操作赋予表达式等。为了叙述上的简便,以后我们将“WML Script1.1”简称“WMLScript ”。

4.1 WML 程序中调用WML Script函数


经过前两章的学习,熟悉C语言的读者可能会认识到,WML 的函数功能、逻辑运算功能等都是十分有限的。而WMLScript提供了丰富的函数功能,我们在WAP应用开发可以使用WMLScript来增强WML编程。因此,WMLScript成为扩展WML编程能力的主要开发工具。

4.2 WMLScript的主要优点及其字节码解释器

WMLScript 具有一套定义好的字节码和一个解释器参考结构。无线网络传输中WMLScript的数据均以二进制格式进行传输,所以,用户可以使用乍带宽通信信道,从而能够保持客户端手机只需要最小限度的内存。ECMAScript修改后得到的WMLScript能够更快、更小、更容易的编译程序为字节码形式。所有这些特点,是WMLScript具备了WML所不能具备的很多优点和功能。

4.2.1 使用WMLScript的主要优点

WMLScript 的设计宗旨是为WMLScript系统提供一般的脚本处理能力,使用WMLScript我们可以进一步补充基于XML的WML语言的编程功能,开发针对乍带宽的网络应用及内容,如文本、图像、选择列表等,我们可以使用简单的格式编写出更灵活和更具可读性的用户界面。WMLScript具备的WML所不能具备的优点和功能,主要包括如下几个方面: (1)检查用户输入的合法性:

(2)扩展用户浏览器的功能,比如允许程序员开发手机的电话呼叫、发送短信息、存储电话号码、管理电话簿或SIM卡等;

(3)生成用户端的确认、提示、警告信息或操作对话框,并使之快速显示在浏览器上;

(4)在用户浏览器的更改后,能够对浏览器端的软件和参数进行扩展与配置;

(5)最大程度克服客户端的乍带宽通信连接限制,并提供丰富的程序功能;

(6)补充WML并使之实现针对微型移动终端设备的多种服务,如支持高级用户界面、增加客户端智能型、提供用户浏览器外围功能的访问能力,以及在服务器与客户端浏览传输数据是减少带宽占用等。

4.2.2 WMLScript的字节码解释器

在WMLScript 的字节码解释器解释之前,WMLScript语言编写的文本格式的程序将被首先编译为二进制格式的代码。编译时,编译器通常先将WMLScript程序分成若干个编辑单位,每个单位的程序都包含一定数量的语句行和WMLScript函数,然后,WMLScript的编译器将按照这些编译单位,逐一将 WMLScript程序作为输入内容,而把对应的字节码作为输出内容。当用户通过WAP手机调用WMLScript程序时,编译器的编码功能即被激活、执行。

4.3 WMLScript基本规则

WMLScript在许多基本规则方面沿用了WML的做法。不过,由于WMLScript是以C语言为蓝本而指定的,所以它的语法特征和C语言非常相像。如果大家对C语言比较熟悉,那么学习和掌握这部分内容应当是比较容易的。

4.3.1 WMLScript与URL

与WML一样,WMLScript也沿用了WWW和HTML访问资源的URL、HTTP等规范,并扩大了URL使用的范围。在WMLScript中,不仅超链接、文件路径即文件名可以作为URL处理,外部函数、访问控制信息等也可以作为URL处理。

为此,WMLScript采用了WML的变通方法,即改进HTML命名资源为值的方式,采用程序段锚点(Fragment Anchor)的形式来处理资源定位。程序段锚点根据文档URL规则进行定义,并按照程序段标识符前加井字号(#)的方式书写。使用程序段锚点, WMLScript程序可以在WMLScript编译单位内可任意指定的函数,并可在调用该函数的同时传递所需的参数。

4.3.2 词法结构

WMLScript编程中的词法结构并不复杂,我们下面就从大小写敏感、空格、换行、注释即保留字等方面讲解相关的具体规则。

(1)内容类型。WMLScript的内容类型主要针对文件形式和二进制形式两种情况,类型结构可以在服务器端进行指定,具体形式为:

文本形式:text/vnd.wap.wmlscript;

二进制形式:application/vnd.wap.wmlscriptc。

具体指定方法我们在第4章已经介绍过,这里不再重述。

(2)大小写敏感。WMLScript1.1是一种大小写敏感的脚本语言。它所设计的各种关键字、变量和函数名都必须合理的使用大小写。

(3)空格和换行。一般情况下,WMLScript程序值形式将忽略所有的空格、制表符合换行符等。但如果把这些特殊字符通过代码进行表述,或者作为字符串进行处理时,WMLScript将不再忽略它们。了如,字符串"Oct 28,2001"中含有空格,该空格在执行时就不会被忽略,它与不含空格的字符串"Oct28,2001"是不同的。

(4)注释。与WML编程一样,在WMLScript脚本程序中也可以加入注释内容。注释内容不被程序执行,且注释不能嵌套。WMLScript的注释方法有两种:

其一,行注释。即使用双斜行号(//)引导以一行内容,这一行内容全部作为注释内容。如:

//这是以行注释,由双斜杠号开始到结束都是注释。

其二,块选择。即以符号“/*”开始,而以符号“/*”结束的期间所有内容都是注释内容。如:

/*这就是块注释,加在中间的内容就是注释内容*/

(5)数据类型与直接编码。WMLScript允许将4种类型的数据直接编码并可嵌套并可嵌如在程序之中。直接编码的4中数据类型为:整数、浮点数、字符串和布尔值。另外,“无效性”值也可直接编码” 1. 整数。当以十进制、十六进制或八进制方式使用整数时,可对这类整数进行直接编码。

编程序时,十进制的数字均不以0开头,只包含0~9的数值串;十六进制的数据以OX或者Ox开头,只包含0~9、a~f或者A~F的字符串;八进制的数均以0开头,只包含0~7的数字串。

2.浮点数。浮点数通常定义为含有小数点的数字,可以包含小数和指数部分。浮点数的形式较多,可以使十进制的整数或浮点数,可以是分数,也可以是指数;但一个浮点数必须至少有一个数。

指数是以e或E开头,后面跟着一个整数。指数是以10为底幂。例如:e0时10的零次幂,例如:e0时10的另次幂,e-2时10的负2次幂集等于0.01。指数可以带符号,正好(+)或者减号(-),它们分别代表是正指数和负指数。

3.字符串。字符串是指定义在成对的双引号("")或单引号(‘ ’)之间的内容。

由于WMLScript只允许使用成对的双引号或但引号来定义字符串,所以程序中使用一个单引号或一个双引号时就会出现编译错误。

考虑到有些特殊字符不能在字符串中直接显现出来,所以WMLScript提供了转译序列来表示这些特殊字符。

4.布尔型。它只是ture和false两个数值,用于表示WMLScript中的“真值”或“假值”。布尔型数据可参与异、或等运算,具体规则我们后面介绍。

5.无效型。也称为“空类型”,它是WMLScript支持的一个表示无效值的量,以invalid表示。该两与C语言中的NULL类似。

4.保留字。WMLScript中定义有一个保留字集合,含有一些表示特殊意义的单词这些次不能另外定义,也不能最为其他标识符。WMLScript中的保留字如下:

acces http agent if break isvalid continue meta header

div name div= path domain return else typeof while

equiv url extern use for user function var

另外,WMLScript还为将来的版本预留了一些保留字,主要有:

case finally catch import class private const public debugger

sizeof default struct do super enum switch export throw

extends try

WMLScript还有一些没有使用的保留字:

delete null in this lib void new with

7. 标识符。WMLScript的标识符可以指定或命名3种元素:变量、函数和标注。标识符不能以数字开头,但能一段下划线(-)开头,而且,标识符不能是 WMLScript的保留字。例如,timeOfDay、speed 、quality、HOME_ADDRESS、_myName、__、varO等都是合法的标识符;而以数字或非短下划线的特殊符号开头的字串,以及保留字等都属于不合法的标志赋,如while、for、if、my~name、$sys、123、3piecs、take.this等。

由于WMLScript是严格区分大小写的,所以字母相同但大小写不同的标识符不是同一个标识,例如,Work和work就是不同的标识符。

8. 名称空间。WMLScript提供了比较自由的名称空间,同一标识符可以同时用作不同的目的。例如,作为某一函数名称的标识符,还可以同时用作变量名、函数参数、程序标注等,使用时他们的属性或值等并不相互影响。在下面的简单的例程中,myTest这一标识符即用作了函数名,又用作了变量名、函数参数名、函数参数名、常量名。显然,WMLScript的这一特定为我们编写程序提供了很大的方便。

4.3.3 WMLScript程序的基本书写规则

WMLScript程序的基本书本写规则:

1.程序由若干语句或函数组成,函数有由若干语句组成;

2.每个完整的语句后面必须加上分号(;),语句关键词语操作数之间必须有空间;分号(;)是WMLScript程序的组成部分;

3.函数体之间必须使用成对的花括号({ })括起来,而且函数结束时在右花括号(})的后面还要加上分号(;);函数说明部分,如函数名、函数类型、函数参数等要放在花括号({})的前面;

  4.有些语句可能也需要实用花括号({ })办含内容,这类语句通常也可以放在函数中,所以花括号({ })是可以嵌套的。

当然,不同的语句、参数、变量等元素在声明和书写时可能还有一些更细的要求,具体我们后面介绍这些元素是再专门给出,

4.4 变量与数据类型

变量即数据类型是所有编程语言的概念和组成部分,WMLScript对此也不例外。它对其变量使用方法和数据类型定义方法给出了详细的规定。变量通常与某数据之相对应,我们可以给变量赋值,并可在程序执行中改变变量的值。下面我们讲解WMLScript有关变量与数据类型的详细规定。

4.4.1变量及其声明

变量是在WMLScript脚本程序中具有值的符号名,或说标识符。使用变量可以存储和改变程序中需要的数据。与C语言不同的是,WMLScript仅支持函数内定义的变量或用于传送数的参变量。

变量使用前必须进行声明,也就是定义变量,即指定变量的名字。声明变量的关键字是var,它的后面根上作为变量名的合法的标识符,并于最后加上分号(;),即完成一个量的声明。声明变量是可以使用var一次声明多个变量名,相邻变量之间使用都号(,)间隔。

一般情况下,我们在给变量命名的时候,都希望能够使用有意义的变量名。例如,当需要使用一个变量表示一本书的价格时,虽然将变量命名为j或book都没有什么错误,但若能命名为bookPrice则会是的WMLScript脚本程序具有更好的可读性,可以方便编程人员进行脚本的编写和调试工作。而且,由于 WMLScript在给变量命名是不能使用保留字,所以考虑到避免由于一时的疏忽时变量名欲保留字发生冲突,我们建议使用多个单词组合在以其作为一个变量的名称,这是一个比较好的解决办法。例如,如果要定义一个变量来存储的、一本书的价格,那我们可以不妨使用bookPrice或者book_price作为变量的名称,这样,一方面可以时变量显得更加清晰,另一方面也可以避免变量与保留字的冲突问题。

以上只是我们对于变量命名的建议,并不是强制性的要求,用户完全可以不按照我们的要求来做,只要遵守WMLScript对于标识符命名的要求就可以了,但养成良好的编程风格不论是对编程人员还是对脚本编写人员来说,都是十分有意义的。

4.4.2 变量的作用域与生命期

一个变量的作用域是指在程序中能够引用这个变量的一段代码。由于WMLScript仅支持函数内定义的变量,所以WMLScript变量的作用与通常就是定义它们的那个函数。在该函数之外,变量不再发挥直接作用。

变量的生命起始值从变量声明开始到失效为止。变量的生命期也被称为变量的持久期、存活期。一个变量在定义它的整个函数内都是有效的,函数内的任何语句块都不会削减变量的生命期或限制变量的作用域。

如果一个变量未经生命就直接使用,或声明过后再次声明,都会破坏变量的生命期。前一种情况会导致变量没有开始声明期,即没有“生命”;而后一种情况则导致变量声明期没有结束以前就重新赋予声明期,即让它多次“降生”。这都会导致变量无效使用。下面函数中的变量使用就说明了这一问题:

function foo(){

x=1;//错误:变量使用前没有声明,改变量还没有“声明”。

var x,y,z;

y=x+3;

var zd =invalid

if(x){

var(y);//错误:这一变量已经声明,这里是重复声明。

};

};

4.4.3 变量的使用

WMLScript的变量只能在定义它的函数内使用。使用时需要声明变量,声明变量是可以同时对变量赋值,甚至对变量进行运算。例如,下面的简单函数就说明了变量的这种灵活的使用方法:

function ourAge(){

var myAge=38;

var yourAge=26;

var ourAge=myAge+yourAge;

return ourAge;

};

使用变量时可通过调用变量名字的形式来实现。上面例子中的“var ourAge=myAge+yourAge;”一句,通过调用变量名,变量ourAge对变量myAge和变量yourAge实行了求和操作。

4.4.4 变量类型与数据类型

WMLScript 是一种“弱类型”的语言,及其变量没有确定的类型。WMLScript变量的类型有改变量所赋数据的类型决定,并根据数据类型的改变而改变。 WMLScript只支持内部定义的数据,因此我们编写程序是无需指定WMLScript变量的类型,WMLScript减根据变量而赋数据的类型自动进行匹配。由于WMLScript的数据类型共有整数、浮点数、字符串、布尔型和“无效型”五种类型,所以WMLScript变量的类型所能匹配的也就是这五种类型。

4.4.5 变量值域

由于变量类型尤其所赋数据的类型决定,所以变量值与域其所赋数据的可取范围等价的。下面的我们就给出整数、浮点数、字符串和布尔型的区值范围,以参照确定应类型变量的值域。 1.整数的范围。WMLScript支持的整数是32位的,也就是说整数的区值范围是从2147483648到+2147483647。我们可以在程序运行期是用Lang函数来取得这些值,如:

Lang.maxInt(); //获取最大的整数

Lang.maxInt(); //获取最小的整数

2.浮点数的范围。它是指WMLScript浮点数的精度所能表示的最小和最大数值WMLScript支持32为的单精度浮点数,其最大至时3.40282347E+38,最小的非零的数是1.17549435E-38或更小(按照正常的精度)。

我们可以使用浮点Float函数库在程序运行其取得这些数值:

Float.maxFloa(); //获得WMLScript所支持的最大浮点值

Float.maxFloa(); //获得WMLScript所支持的最小浮点值
对于运行期出现的一些特殊的浮点数,WMLscript将按照下述规则处理:

其一,如果操作结果是一个不能被单精度浮点数所能表示的数值,那么该结果将被认为是invalid,即无效值;

其二,如果操作结果发生下溢出,那么结果将作为0.0处理:

其三,负的零和正的零是完全相等的。

3.字符串的范围。任何由于字母、数字或特殊字符组成的符号串都是WMLScript中定义的有关字符串的操作或String库中的函数控制字符串。

4.布尔型数据的范围。布尔型数据只有ture和flase两个取值,这也是布尔型变量的两种数值。我们可以使用布尔型数据取初始化或指定某一变量的数值,或将布尔值变量写入一个需要布尔值作为参数的语句。布尔值可以是数值运算的结果,也可以是逻辑运算的结果。

下面就是定义布尔型变量并赋初值的例句:

var truth=truth;

var lie=!truth;


4.5 操作符与表达式

在WMLScript中,表达式可以把变量、常量与操作符结合起来,经过运算能够产生一定的运算结果。表达式运算后产生的结果可以是整数型、浮点数型、字符串型或布尔型的数据。其实,对于表达式我们并不陌生,例如,1+2就是一个简单的表达式。

WMLScript 的表达式主要有两种类型。一种是赋值表达式,即把数据赋给变量的一种表达式,例如,myBook=3,在这个表达式中,将3 赋给变量myBook,同时,这个表达式本身也有一个运算结果,那就是3。另外一种是运算表达式,它是指产生一个运算结果而不进行赋值操作的表达式,例如 1+2就是一个运算表达式,在这个表达式运算产生的结果是3, 但这个表达式并没有把运算结果赋给变量。

在表达式运算的过程中,表达式中操作一个或这两个数据产生运算的符号做操作符,被操作符操作的数据称作操作数,在WMLScript中我们会使用到各种操作符,下面就对操作符及有关的表达式进行详细讲解。

4.5.1 赋值操作符

赋值操作符用于赋值操作,即给变量指定所需的数值,它能把有操作数的运算结果给做操作数,最简单的赋值操作符就是“=”,例如x=2,就是将2赋值给变量x。在如以下几行语句都是赋值操作:

var="abc";

var b=a;

b="def";

赋值操作符不需要指定使用对象,也不会改变赋值操作符右边变量的数值。WMLScript的赋值操作符主要包括以下几种:

1.=。用于赋值操作,将有操作数赋给左操作。

2 +=。将有操作数与左操作数进行相见运算,然后把运算结果赋值给左操作数。例如,假设x=3,那么x+=2运算后的结果为x=5。

+=是比较特别的操作符,因为它可以将两个字符串相连,所以+=操作符也可以对字符串进行操作,然后将连接后的字符串赋给左操作数。例如,假设x="Happy",那么x+="new Year"运算后结果是x="Happy New Year"。

3.-=。将左操作数简取有操作数,然后把运算结果赋值给左操作数。例如,假设x=3那么x-=运算后的结果为x=1。

4*=。将左操作属于有操作符进行相乘运算,然后把运算结果赋值给左操作数。例如,假设x=6,那么x*=2运算后的结果为x=6。

5/=。将右操作属于右操作符进行相乘运算,然后把运算结果赋值给左操作数。例如,假设x=6,那么x*=2运算后的结果为x=6。

6div=。拥有操作数处理左操作数,然后把运算结果中的整数部分赋值给左操作数,例如x=7,那么xdiv=2运算后的结果为x=3。

7%=。功能是求余数并赋值,用右操作数除以做操作数,最后把运算得到的余数值给操作数。例如,假设x=7,那么x%=3运算后的结果为x=1。

8<<=。功能是带符号左位移并赋值,即将左操作和右操作数进行左位移操作,在将结果赋给左操作数。

9>>=。可将左操作和右操作进行右操作进行补零右位移操作,在将结果赋给左操作数。

4.5.2 数学运算操作符

数学运算操作符可以对数值类型的操作数进行运算,然后返回一个数值类型的运算结果。

1+。这是加运算操作等,它对应着数学运算中的加法运算,例如表达式1+2的运算结果为3。

加操作符还可以对字符串类型的操作数进行运算,然后将两个字符串相连起来作为运算

2- 。即检操作符,对应着速学运算中的减法运算,例如表达式2-1的运算结果为1。

同时,“-”还是一个取负操作符,当它作为取负操作符的是一个操作数,取负操作符的功能使返回操作数的相反数。

3*。这是乘操作符,它对应着数学运算中的乘法运算,例如表达式2*3的运算结果为6。

4/。即除操作符,对应着数学运算中的除法运算,但WMLScript中的除法运算有些特别,在WMLScript中,除法运算后的结果是一个浮点数,而不想C 语言或者Java语言那样在整数进行除法运算式井运算结果强行转化整数。在WMLScript中,1/2=0.5,而在Jave中,1/2=0。

5div。这是整除操作符,对应着数学运算中的整数运算,运算后的结果一个整数,这一点与C语言或者Java语言中的情况是一样的,可以在整数进行除法运算式将运算结果强行转换整数。

6%。即取模操作符,它对应着数学运算中的取莫运算,也就是将两个操作相除,返回相除后的余数。

取模操作符主要用于判断一个数字是否能被另一个数字整除。

((the Year%3==0))&&(the Year%100!=0))||(the Year%400==0)

其中&&代表的是逻辑运算中的与运算,||代表的是逻辑运算中的或运算,关于逻辑运算,我们后面会详细介绍。

7++。这是递增操作符,它只有一个操作数,操作可以在操作符的左边,也可以在操作符的右边,它所完成的运算操作是将操作数加1。假设操作数名称为j,值为2,那么++j加1,然后返回j的值3;而j++则实现返回j的值2,然后将j加1。

在循环中,我们常常会用到递增操作符的作用正好相反。递减操作完成的运算操作是经操作数减1。例如,假设操作数名称为j,值为2,那么--j先将j减1,然后返回的值1;而j--是先返回j的值2,然后将j减1。

4.5.3 位操作符

为操作符在运算实现将操作转化32位的二进制数,然后对每个操作数分别按位进行运算,运算后在将二进制的结果按照标准WMLScript数值类型返回运算结束。

1&。这是为与操作符,它可以对两个操作数按位进行于操作,其运算规则是:

0&0=0,0&1=0,1&0=0,1&1=1

2|。这是位或操作符,它可以对两个操作数按位进行或操作,运算规则是:

0|0=0 ,0|1=1,1|0=1,1|1=1

3^。这是唯一或操作符,它可以对两个操作按位进行异或操作,其运算规则是:0^0=0,0^1=1,1^0=1,1^1=0

4~。这是位非操作符,它只有一个操作数,可对操作数按位进行非操作,运算规则是:~0=1,~=0

5<<。这是左移操作,它可以对左操作数进行向左一位的操作,由操作数给定了要移动的位数,在移动过程中,左操作数的最低为补充0。

6>>。这是右移操作符,它可以对左操作数进行向右移位的操作,由操作数给定要移动的位数,在移位的过程中,丢弃向右移的位。

7> >>。这是填0右移操作符,它与右移操作符相似。当对证正数进行操作时,它们的效果完全相同;不同之处在于,当进行负整数右移操作时,因为负责转化为二进制后,最高为1,所以在进行右移操作后,最高位仍然补充1,而在进行填0右移操作时,最高为补充的是0,因此,这是负数将转化为正数。

4.5.4 逻辑操作符

逻辑操作符可以将布尔类型的表达式组合起来,完成逻辑运算操作,然后返回逻辑运算的结果——真或假,这样就可以完成比较复杂的逻辑判断工作。逻辑操作共有3种;

1&&。即逻辑与操作符它只有在两个操作数都为ture的时候,返回结果为ture,在其他情况下,返回结果为false或者invalid。

2||。这是或操作符,它在两个操作数至少有一个为ture的时候,返回结果为ture,在其他情况下,返回结果为false或者invalid。

3!。即非操作符,它只有一个操作数。当操作数为ture时,返回结果为flase;返回结果为ture.

4.5.5 比较操作符

比较操作符可以把操作数进行比较,然后返回一个逻辑值,表明这个比较操作的结果是否为真。比较操作的操作数可以是数值类型或者字符串类型的数据。比较操作符也常被称为关系运算符。

WMLScript支持的比较操作符共有6种,下面被介绍一下。

1. ==。即等于操作符,它可以比较两个操作数是否相等。如果两个操作数相等,则返回ture,否则返回false

2. !=。即不等操作符。它可以比较两个操作数是否相等。如果两个操作数相等,则返回false,否则返回ture。

3. >。即大于操作等。其运算规则时,如果左操作数大于右操作数,则返回ture。
posted on 2006-09-01 20:25 伊峰 阅读(5193) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航: