baserunner

模板

baserunner 模板是一个包含指令与标记的HTML文件,它用来分析与产生给用户的输出。标记将会被数据或其他值替换。而指令是包含在HTML代码文件的注释之中的,它设置了一些需要进行特殊处理设置HTML代码块。模板文件可以使用任意的后辍。当标记与指令被处理完成之后,模板文件必须生成一个标准的HTML文件。

任何HTML编辑器都可以用来编辑模板文件,但你必须进入HTML代码编辑之中去增加标记与指令。如果你使用的是所见即所得的编辑器,当你在模板中增加表达式时应特别注意,很多编辑器会自动修正这些表达式,因此而改变表达式的意义。特别要注意的是当表达中有">"或"<"或双引号或者是表达式中有空格时,尤其应注意这个问题。因此一种较好的选择是你选用所见即所得的编辑器进行初步的编辑,使整个页面达到你所需要的效果,然后用文本编辑进行更进一步的工作。FrontPage中有一个选项“HTML Markup",可以使它不对HTML代码不进行检查与格式化,但它不能很好在工作。其他编辑器也可能有类似的特性。Notepad总是一个较好的选择。

baserunner模板允许以各种方法与显示数据或其他变量。可以显示数据列表、单行或多行记录、数据值的汇总等。还可以根据表达式的值使一段HTML代码块被显示或不显示。

由于模板可以存在于任何目录之中,因此当baserunner处理之后发给用户时,在用户看来它们就像来自于WEB根目录一样。

标记Tags

缺省情况下,在模板文件中使用的所有标记都包含在一对大括号之中,由baserunner对它们进行转换。但你可以通过修改_tagstart与_targend变量的值来改变它,或者是通过命令行或表单给出这两个变量的值,从而使得这种变量只在一个文件中有效。这两个变量的值必须具有相同的长度,而且必须是不同的字符。一般来说你没有必要改变它,除非是你的模板文件中使用了这两个字符做其他用途,如你使用JavaScript或样式标志。

 

多数标记由数据表达式组成,这些标记将被替换为数据库中当前记录中的相关字段的值。最简单的数据表达式就是字段名{field_name}。表达式是标准的xBase语言表达式,可以相当复杂。不能被替的标记将被自动去掉。具体的表达式语法请参见xBase参手册中的表达式部分

用于显示数据的最常用的表达式有:

备注字段 {memo_field}

备注字段内容,系统自动去掉尾随的空格。

字符型字段 {chr_field}
{trim(chr_field)}

通常情况下字段字段尾随的空格需要去掉,但系统不会自动将它去掉。

数值型字段 {str(num_field, 10, 2)},
{str(num_field)}

数值型字段必须使用STR函数将它转换为字符型字段才能显示。如果不转换,数值型字段不能被显示。

逻辑型字段 {logic_field},
{IIF(logic_field=.T.,"True ","False")},
<input type="checkbox" {IIF(logic_field=.T.,"checked","       ")}>

如果为真则其内容为T,否则为F或者没有值。如果直接使用字段名,则显示的是它本身的内容(T或F或没有值)。可以使用iif()函数来根据逻辑字段的内容来显示其他的值,需要注意的是:在iif()函数中的第二个参数与第三个参数内容的长度必需是相同的。如上面的例子中,True后需要带一个空格。

日期型字段 {date_field}
{dtoc(date_field)}

日期型字段以CCYYMMDD格式的字符串存储于数据库之中。直接使用字段名将会以通过用日期格式进行显示。如果使用dtoc()函数,将会以配置文件中的指定的_dateformat变量规定的格式进行显示。

还包含其他的标记:

{count} 显示当前数据库中的记录数或者是根据当前过滤条件过滤之后的记录数。
{rand} 显示一个随机数
{setdisplay} 显示当前的_display值
{session} 用户会话的名称
{filterexp} 当前过滤(查询)表达式
{sortexp} 当前使用的排序表达式
{longtime} 以长整型格式显示当前时间。在某些环境下这可能比time函数更有用!
{server_variable} 在baserunner系统中可以显示的WEB服务器中的变量
{HTTP_USER_AGENT}
{QUERY_STRING}
{CONTENT_LENGTH}
{CONTENT_TYPE}
{SERVER_SOFTWARE}
{GATEWAY_INTERFACE}
{SERVER_NAME}
{SERVER_PROTOCOL}
{SERVER_PORT}
{REQUEST_METHOD}
{HTTP_ACCEPT}
{HTTP_REFERER}
{PATH_INFO}
{PATH_TRANSLATED}
{SCRIPT_NAME}
{QUERY_STRING}
{REMOTE_HOST}
{REMOTE_ADDR}
{AUTH_TYPE}
{REMOTE_USER}
{REMOTE_IDENT}
{SERVER_NAME}

其返回值与WEB服务器的设置有关!

{_variable} 配置文件(或命令行或表单)中定义的变量,需要注意的是这些变量必须以下划线打头。

 

baserunner在处理其他标记之前首先处理变量标记,因此,标记表达式中可以嵌套变量标记,但不能嵌套表达式。例如,假设你有一个数字型变量,可以使用下面的表达式:

{str(field+{_variable},10,0)}

在这个例子中,_variable的值首先与field的值相加然后进行显示。首先处理内部变量{_variable},然后再进行其他的处理。{str(field+200,10,0)}

(当然我们假设_variable的值是200).这种嵌套只能有一层。

显示单个记录

任何没有包含在列表块或唯一性列表块或重复性块中的数据表达式,都将被数据库中当前记录的值替换。如果在baserunner启动时打开一个模板文件,则将显示数据库中的第一个记录的内容(或当前查询中的第一个记录)。每个Naviation操作将会使记录指针移动一个。

例子:

The current record is: {ltrim(str(recno()))}
Field 1: <h1>{trim(chr_field)}</h1>
Field 2: {dtoc(date_field)}
Field 3: {memo_field}
<form method="GET" action="/cgi-bin/baserun.exe">
<input type="hidden" name="_ses" value="{session}">
<table>
<tr>
   <td><input type="submit" name="_act" value="Top"></td>
   <td><input type="submit" name="_act" value="Back"></td>
   <td><input type="submit" name="_act" value="Next"></td>
   <td><input type="submit" name="_act" value="End"></td>
</tr>
</table>

这个简单的例子显示当前记录的三个字段与记录号。Navigation操作的表单如下:

The current record is: {ltrim(str(recno()))}
Field 1: <h1>{trim(chr_field)}</h1>
Field 2: {dtoc(dat_field)}
Field 3: {mem_field}
<a href="/cgi-bin/baserun.exe?_ses={session}&_act=top">[ Top ]</a>

<a href="/cgi-bin/baserun.exe?_ses={session}&_act=back">[ Back ]</a>
<a href="/cgi-bin/baserun.exe?_ses={session}&_act=next">[ Next ]</a>
<a href="/cgi-bin/baserun.exe?_ses={session}&_act=end">[ End ]</a>

这个例子为Navigation操作使用普通的链接。由于对每记录都使用相同的模板,因此上面的两个例子都没有使用_tar变量。如果你将应用程序使用的多个模板放在一起,使用_tar是一种较好的方法。如果用户使用浏览器上的回退按钮来返回上一个记录,则应使用下面的方法:

<a href="/cgi-bin/baserun.exe?_ses={session}&_tar=[this template]&_act=top">
[ Top ]</a>

当然,并非一定要使用naviation操作。对于上面的例子,如果显示的内容来自于多个表,你可能只按以下的方法提供一个简单的后退即可:

<a href="/cgi-bin/baserun.exe?_ses={session}&_tar=[calling template]">
[ Go Back ]</a>

指令

如果你需要显示多个记录,数据列表或按条件显示数据,就需要增加baserunner指令。指令是以HTML注释的方式输入的:

<!--directive-->
   HTML code
<!--enddirective-->

指令总是成对使用。系统对所有注意都会检查它是否是baserunner的指令,因此在模板中不应该包含不必需的注释。下表中当一个指令以X结尾时,表达指令必须以X以前的部分开始,并且每个指令都必需唯有一个唯一的名称。例如listX,在使用时需要将X换掉,如list1,list2等。

指令 描述
<!--repeat-->
<!--alternate-->
<!--endrepeat-->
包含在本指令对中的代码用显示X条记录的内容(X的值由_display变量决定)。alternate指令是可选的,如果使用了它,其他的记录将按照alternate之后的代码进行显示。
<!--listX-->
<!--endlist-->
包含在本代码块的代码用于将数据库中的记录以列表的形式显示。每个列表必须具有唯一的名称。
<!--uniqueX-->
<!--endunique-->
包含在本代码块的代码用于将数据库中的记录以列表的形式显示(不显示重复的数据)。每个列表必须具有唯一的名称。
<!--totalX-->
<!--endtotal-->
显示记录中的数值型字段的总计值。
<!--averageX-->
<!--endaverage-->
显示记录中的数值型字段的平均值。
<!--expression-->
<!--else-->
<!--endcondition-->
条件块,开始的表达式为一逻辑值,如果它为真,则显示它后面的代码,否则显示else之后的代码。
<!--filter-->
<!--endfilter-->
当数据库中的过滤表达式起作用时才显示。
<!--nofilter-->
<!--endnofilter-->
当数据库未过滤过时显示本块内的内容。

条件显示指令

基于过滤状态的条件显示

包含在<!--filter-->与<!--endfilter-->指令对中的HTML代码块令当过滤条件起作用时才被显示。同样,包含在<!--nofilter-->与<!--endnofilter-->指令对中的HTML代码块令当过滤条件不起作用时才被显示 。 当前数据库很大时 ,这 两对指令显得尤为重要。过滤块在标忘与其他指令之前被处理的。

 

例子:

<!--filter-->
    The current query is: {filterexp}
<!--endfilter-->

This code would display the current query statement only if a filter was in effect. Otherwise, the entire block would be deleted from the display.

基于xBase逻辑表达式的条件显示

还可以使用基于逻辑表达式的条件显示(在<!--expression--> <!--endcondition-->对之间,而且它还可以使用<!--else-->)条件表达式与数据标志在同一个时间进行计算,条件表达式与iif()表达式类似,但前者更灵活。

在条件表达式中还可能使用命名变量(以下划线打头), 当然变量必须在配置文件或命令行或表单中定义才能使用。使用变量使得动态更新条件成为可能。

表达式中还可以使用 baserunner的标记,如{_variable},在表达式中不能使用其他的标记。例如,你可以像这样使用表达式:

<!--field="{_variable}"-->

在表达式计算之前,首先计算{_variable}标记的值。如果需要使用其他的信息,需要将将这些信息首先赋值一个变量,例如,如果你需要在表达式中使用会话名,首先需要定义一个变量来保存会话名的值_sname={session},然后在表达式中使用_sname这个变量。

不要混淆条件指令中条件表达式与条件块中对变量的使用方法,前者只是一个为了计算表达式的值而用到变量名,后者是一个在条件块中使用的变量标记。

条件显示块不能嵌套使用。

例子:

<!--log_field=.T.-->
HTML code that is only displayed if the logical field "log_field" is set to true.

<!--endcondition-->

<!--"@"$chr_field-->
HTML code that is only displayed if the character field "chr_field" contains the character "@".
<!--else-->
HTML code that is only displayed if the expression is not true.
<!--endcondition-->

In the configuration file: _variable=dat_field=date()

<!--_variable-->
HTML code that is only displayed if the date field "dat_field" equals today's date. The expression is contained in the variable _variable in the application configuration file.
<!--endcondition-->


显示多个记录

可以使用<!--repeat-->, <!--endrepeat-->指令来显示记录的集合。显示的记录数由_display的值决定。这个值一般在配置文件中确定,但也可以通过传递一个_display变量来改变它。为了设置新的值,传递_display变量时必须发送display操作。一般来说可以使用以下的程序来实现:

<form action="/cgi-bin/baserun.exe?_ses={session}&_act=display&_tar=template.htm" method="GET">
<p><input type="text" size="3" name="_display" value="{setdisplay}">
<input type="submit" value=" Show "></p>
</form>

在repeat块中,还可以使用<!--alternate-->指令。此时,第一个记录以<!--alternate-->指令之前的代码格式显示,其他的记录以<!--alternate-->指令之后的格式显示。

在显示多个记录时Navigation操作将会移个与显示的记录数相当数量的记录数。

例子:

<table>
<tr>
   <th>Record Number</th>
   <th>Heading</th>
   <th>Heading</th>
   <th>Num Heading</th>
</tr>
<!--repeat-->
<tr>
   <td>
   <a
href="/cgi-bin/baserun.exe?_ses={session}&_tar=target.htm&_act={ltrim(str(recno()))}"
   Details</a>
   <td>{trim(chr_field)}</td>
   <td>{dtoc(dat_field)}</td>
   <td>{str(num_field, 10, 2)}</td>
</tr>
<!--endrepeat-->
</table>
<table>
<tr>
   <th>Heading</th>
   <th>Heading</th>
   <th>Num Heading</th>
</tr>
<!--repeat-->
<tr>
   <td>{trim(chr_field)}</td>
   <td>{dtoc(date_field)}</td>
   <td>{str(num_field, 10, 2)}</td>
</tr>
<!--alternate-->
<tr>
   <td bgcolor="XXXXXX">{trim(chr_field)}</td>
   <td bgcolor="XXXXXX">{dtoc(date_field)}</td>
   <td bgcolor="XXXXXX">{str(num_field, 10, 2)}</td>
</tr>
<!--endrepeat-->
</table>

列表

列表用于显示当前记录集合中的每个记录。每个列表必须具有以list打头的唯一名称。列表通过<~--list--><!--endlist-->指令来创建。名称只要以list打头就行,你可以随意取,如<!--list1-->,<!--list2-->,<!--list3-->等,这可能是最简单的了。<!-----endlist-->不需要修改。对每一个匹配的记录都将重复使用代码段中的代码。List中的数据被存入cache之中,因此仅在过滤条件改变时才改变它。List不能嵌套。

列表可以排序。为了排序,你需要在配置文件中定义一个与列表名相同的变量(当然需要在变量名之前加上下划线),如_list1等。变量的值就是排序的字段或表达式。如,"field_name"或alltrim(last_name)+alltrim(first_name)。 如果需要使用多个排序表达式,可以通过命令行或表单传递排序表达式。排序仅仅是对显示有效,对数据库不会进行排序的。排序表达式不能是逻辑表达式。

当处理大数据库时,在产生列表时你就特别注意。具有几千个记录的列表(或唯一列表)可能会化费很多的时间来生成列表并发送给用户。因此,在大多数情况下,应该在过滤起作用时来建立列表。

列表,包含唯一列表,在处理方法上与单个或多个记录的显示的处理方法是不同的。列表不使用当前记录指针也不影响当前记录指针。所有的列表都从数据库或当前过滤集中的第一个记录开始,一个一个的处理直到最后一个记录。如果在repeat指令中你使用一个很大的_display值(比如说比数据库中的记录还多),所产生的结果与列表是一样的,但他们的处理是不同的,repeat会影响当前的记录指针。

列表、唯一列表与汇总与普通的记录显示在baserunner内部也是不一样的,前者可能使用 cache,而后者不使用。

当然 ,也有在不 适合使用cache机制的情况,此时你可以定义_nocache变量,让baserunner不使用cache机制。

 

例子:

<table>
<tr>
   <th>Heading</th>
   <th>Heading</th>
   <th>Num Heading</th>
</tr>
<!--list1-->
<tr>
   <td>{trim(chr_field)}</td>
   <td>{dtoc(date_field)}</td>
   <td>{str(num_field, 10, 2)}</td>
</tr>
<!--endlist-->
</table>
 
<form action="cgi-bin/baserun.exe" method="GET">
    <input type="hidden" name="_ses" value="{session}">
    <input type="hidden" name="_tar" value="record.htm">
    <select name="_act" size="1">
        <!--list2-->
        <option value="{ltrim(str(recno()))}">{trim(chr_field)}
        </option>
        <!--endlist-->
    </select>
    <input type="submit" value=" Look up ">
</form>

唯一性列表

唯一列表与普通列表一样,显示当前当前记录集中的每个记录。但它只对每个值只显示一次,不显示重复的值。每个唯一列表都必须具有以unique打头的唯一的名称。唯一性列表通过<!--uniqueX--> 与 <!--endunique-->来创建。你可以随意使用你想用的名字,如<!--unique1-->, <!--unique2--> <!--unique3-->, 等,可能是最简单的了。<!--endunique--> 指令不需要修改。同列表一样,它也使用cache机制,因此只有当过滤条件改变后它支会改变。

对于每一个唯一列表,在配置文件中必须有一个与列表名称相同的变量(当然需要以下划线打头),如_unique1。 这个变量必须包含着用于确定数据是否唯一的表达式,如字段名或更复杂的表达式alltrim(last_name)+alltrim(first_name)。当然也可以通过命令行与表单来传递这个变量。同排序表达式一样,这个变量也不能是逻辑表达式。

Examples:

<UL>
<!--unique1-->
<LI>{trim(chr_field)}
<!--endunique-->
</UL>

In the application configuration file:

_unique1=chr_field


<!--Filter-->
<form action="/cgi-bin/baserun.exe?_ses={session}&_act=refine&_tar=target.htm" method="POST">
<select name="_chr_field1" size="1">
<!--unique2-->
<option>{trim(chr_field1)}</option>
<!--endunique-->
</select>
<input type="submit" value="Refine Query"></p>
</form>
<!--endfilter-->

In the application configuration file:

_unique2=descend(chr_field1)

 

汇总与平均值

插入一个汇总块,将显示出汇总块中包含标记的任何表达式的汇总值。使用<!--totalX--> 与 <!--endtotal-->指令创建汇总块。你可以按你的需要改变汇总块的名称,如<!--total1-->, <!--total2--> <!--total3-->, 等,可能是最简单的名称了。<!--endtotal-->指令不需要改变。一般说来表达式应返回数字数据,但如果是包含数字的字符串也可以,而且,在某些情况下,特别是需要做计算时,使用字 符可能会更加灵活,如, {str(num_field/60,10,2))}. 不能被转换为数字的表达式将被忽略。汇总块也使用cache,因此只有当过滤条件改变后它支会改变。

<!--averageX--> 与 <!--endaverage--> 同 <!--totalX-->以相同的方式工作,只是它求的是平均值。

缺省情况下,数据显示两位小数。但你可以改变小数位数,可以通过在块名称后加上数字来改变(当然需要加一对括号),如不显示小数,可以使用 <!--averageX(0)-->;显示三位小数可以使用<!--total1(3)-->。

Example:

<table>
<tr>
   <th>Heading</th>
   <th>Heading</th>
   <th>Num Heading</th>
</tr>
<!--list1-->
<tr>
   <td>{trim(chr_field)}</td>
   <td>{dtoc(date_field)}</td>
   <td>{str(num_field, 10, 2)}</td>
</tr>
<!--endlist-->
<!--total1-->
<tr>
    <td>Total:</td>
    <td>&nbsp;</td>
    <td>{str(num_field*1.4),10,2))}</td>
</tr>
<!--endtotal-->
<!--average1-->
<tr>
    <td>Average:</td>
    <td>&nbsp;</td>
    <td>{num_field}</td>
</tr>
<!--endaverage-->
</table>

 

欧洲语言

在某些情况下, baserunner(与HTML)使用欧洲语言显示扩展字符时会遇到困难。如果在你的应用程序中遇到这个问题,你可以在配置文件中增加一个_translatehtml逻辑变量,如果定义了这个变量,baserunner将会把扩展字符转换为HTML代码。这就就不存在扩展代码,使用的代码全部都基本字符集中的字 符,显示就会正常了。