`
isiqi
  • 浏览: 16558344 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

XML和现代CGI应用程序

阅读更多
作者: 刘彦青
出处: http://www.ccidnet.com/tech/web/2002/01/07/92_3901.html

简介
Perl的普及与互联网的蓬勃发展有直接的关系。在互联网发展的早期,人们发现仅仅使用静态的HTML文档不能生成有效的交互式环境,于是引进了公用网关接口(CGI)的概念。Perl强大的功能和容易扩充的特性使得它成为开发CGI应用最自然的选择,并由此迅速地成为CGI脚本的首选语言。CGI本身并非十全十美。但由于得到了众多开发商的青睐,CGI的应用至今仍然十分广泛,而且没有迹象表明在近期会“退休”。

CGI::XMLApplication提供了一个基于XML、可以作为传统CGI脚本的模块。典型的CGI::XMLApplication脚本包括三部分:一个很小的提供对该应用程序访问支持的可执行脚本、实现各种管理者方法的逻辑模块、根据应用状态可能有一个或多个XSLT样式表,XSLT样式表能够将模块返回的结果转化成浏览器可以向用户显示的格式。

下面我们通过例子来简要地介绍CGI::XMLApplication的应用。

例1:CGI XSLT网关
CGI::XMLApplication假定,参与一个项目的设计和开发人员使用XSLT样式表分离应用的逻辑和表示,这样可以使这种分离显得非常直接,也不会对项目带来影响。开发人员只要能够使setStylesheet返回符合当前应用状态的XSLT样式表的位置即可。应用建立的DOM树的转换、XSLT参数向转换引擎的传递、转换后内容向浏览器的传输对用户而言都是透明的。

为了重点说明这种分离,我们的第一个例子不是传统意义上的Web应用,而是一个通用的XSLT网关,它可以添加到服务器的cgi-bin中,将整个XML内容的目录树转化为符合请求的浏览器的格式,而这一切对于用户、样式表和文档的作者而言也都是透明的。

第一步是建立连接客户端的请求和应用的CGI脚本。我们希望XML文档能够方便地通过URL浏览,并使创建这些文档间的超链接非常直观。因此,我们将创建一个没有扩展名的CGI脚本,以便将它作为URL路径中的一个节点,节点右边的所有内容将在包含XML内容的虚拟文档环境中进行解释。在这种情况下,我们将CGI称作是样式表选择者。

use strict;
use lib '/path/to/secure/webapp/libs';
use XSLGateway;
use CGI qw(:standard);my $q = CGI->new();
my %context = ();
my $gateway_name = 'stylechooser';

在加载合适的模块和设置一些在整个脚本范围内有效的变量后,我们开始向被传递给处理该应用逻辑的类的%context中添加一些域。在这个应用软件中,我们只传输要求的指向脚本文件路径右边的URL(REQUEST条目)和包含有存储在查询参数style中的数据的STYLE关健字。

$context{REQUEST} = $q->url(-path => 1);
$context{REQUEST} =~ s/^$gateway_name\/?//;
$context{REQUEST} ||= 'index.xml';
$context{STYLE} = $q->param('style') if $q->param('style');

最后,我们创建了XSLGateway逻辑类的一个实例,并通过调用其run方法处理请求,将%context作为唯一的参数。

my $app = XSLGateway->new();
$app->run(%context);

CGI脚本就完成了。下面我们创建完成大部分工作的XSLGateway模块:

package XSLGateway;

use strict;
use vars qw(@ISA);
use CGI::XMLApplication;
use XML::LibXML;

@ISA = qw(CGI::XMLApplication);

象我在简介中提到的那样,CGI::XMLApplication通过事件调用起作用:应用程序类中一个给定的方法的执行依赖于一个指定域的输入(一般情况下是用来提交表格的按钮的名字。),必须执行二种调用方法:selectStylesheet和requestDOM方法。

selectStylesheet返回有关的XSLT样式表的全文件系统路径。为了简单起见,我们假定样式表将保存在一个单一的目录中。我们可以通过$context->{STYLE}域提供其他的样式表,从而增加系统的灵活性。

sub selectStylesheet {
my $self = shift;
my $context = shift;
my $style = $context->{STYLE} || 'default';
my $style_path = '/opt/www/htdocs/stylesheets/';
return $style_path . $style . '.xsl';
}

下一步,我们需要创建requestDOM方法,该方法将返回被传输的XML文档的XML::LibXML DOM表达式。由于我们的网关只适用于静态文件,我们需要使用XML::LibXML对文档进行解析,并返回结果树。

sub requestDOM {
my $self = shift;
my $context = shift;
my $xml_file = $context->{REQUEST} || 'index.xml';
my $doc_path = '/opt/www/htdocs/xmldocs/';
my $requested_doc = $doc_path . $xml_file;

my $parser = XML::LibXML->new;
my $doc = $parser->parse_file($requested_doc);
return $doc;
}

至此,我们的CGI脚本已经可以安全地在服务器的cgi-bin目录中安全地运行了,并在一些适当的目录中上载一些XML文档和一个或二个XSLT样式表。下面我们就可以开始检验我们的工作成果了。对http://localhost/cgi-bin/stylechooser/mydocs/somefile.xml的请求将会使互联网服务器从/opt/www/htdocs/xmldocs/目录中选取mydocs/somefile.xml文件,使用/opt/www/htdocs/stylesheets/中的样式表default.xsl对该文件进行转换,并将它传输给客户。

如果需要,我们可以扩充这一基本的框架,例如,可以在样式表选择CGI脚本程序添加一些查找组件,选择合适的样式表,可以设置或读取HTTP cookies,对网站进行修饰。

例2:一个简单的购物系统
在该例子中,我们将使用CGI::XMLApplication创建一个简化的Web应用程序,购物系统。

与上个例子相同,这个应用程序中与CGI-BIN有关的部分仍然非常地少。我们所需要作的只不过是初始化CustomerOrder应用类并调用它的run()方法。这次,我们将CGI.pm中Vars作为%context的PARAMS域:

use strict;
use CGI qw(:standard);
use lib '/path/to/secure/webapp/libs';
use CustomerOrder;
my $q = CGI->new();
my %context = ();
$context{PARAMS} = $q->Vars;

my $app = CustomerOrder->new();
$app->run(%context);

在这个例子中,我们假定该应用中的产品信息存储在关系数据库中,产品清单不是太长,使我们在应用中不会出现多屏才能显示相关信息的麻烦:用户输入订购的产品数量的主要数据输入屏,显示订购单内容和所选物品总价格的确认屏,显示订单已经处理的提示。为了简单起见,我们在这里没有涉及送货和财务数据的输入等问题。

package CustomerOrder;

use strict;
use vars qw(@ISA);
use CGI::XMLApplication;
use XML::LibXML::SAX::Builder;
use XML::Generator::DBI;
use DBI;

@ISA = qw(CGI::XMLApplication);

在加载必要的模块和定义从CGI::XMLAplication中继承的类后,我们开始创建应用中与各种状态有关的事件调用。首先,我们必须通过创建registerEvents()方法注册这些事件。在本例中,我们将注册order_confirm 和order_send方法,这二个方法设置%context中的SCREENSTYLE域。稍后,我们将利用该属性定义在显示客户端的数据时应该使用三个XSLT样式表中的哪一个。

需要注意的是,这些事件将被映射到实现它们的实际的子程序中,子程序的命名规则是event_<事件名>,例如,order_confim事件是由event_order_confim执行的。另外,还需要注意的是,各种事件的选择是由CGI::XMLApplication根据其查找一个与注册事件同名的表格参数的能力进行的。例如,要执行order_confirm事件,表格组件中必须包含一个提交非空值的名字为order_confirm的表格域。
# 事件的注册和事件调用

sub registerEvents {
return qw( order_confirm order_send );
}

sub event_order_confirm {
my ($self, $context) = @_;
$context->{SCREENSTYLE} = 'order_confirm.xsl';
}

sub event_order_send {
my ($self, $context) = @_;
$context->{SCREENSTYLE} = 'order_send.xsl';
}

如果没有请求执行其他的事件,则缺省地执行event_default。在本例中,我们只使用它将SCREENSTYLE域设定为一个合适的值。

sub event_default {
my ($self, $context) = @_;
$context->{SCREENSTYLE} = 'order_default.xsl';
}

每次请求都会执行event_init方法,而且总是在其他方法之前执行它,这使得它非常适合对应用中被其他事件使用的部分进行初始化。在本例中,我们使用它返回利用fetch_recordset()方法从数据库中获取的产品信息的、最初的DOM树。

sub event_init {
my ($self, $context) = @_;
$context->{DOMTREE} = $self->fetch_recordset();
}

state-handler方法完成后,我们需要执行必需的selectStylesheet和requestDOM方法。

与在第一个例子中一样,我们假设所有的应用的样式表都存储在服务器上相同的目录中。我们所需要作的是返回$context->{SCREENSTYLE}的值所指定的路线,并添加到末尾。

# app config and helpers
sub selectStylesheet {
my ($self, $context) = @_;
my $style = $context->{SCREENSTYLE};
my $style_path = '/opt/www/htdocs/stylesheets/cart/';
return $style_path . $style;
}

在研究requestDOM处理程序之前,我们先来详细地研究fetch_recordset helper方法。

需要记住的是,我们要做的工作是从一个关系数据库中选择所订购产品的有关信息,但传递给XSLT处理器的数据必须是DOM树。在本例中,我们不通过编程的方法,而是利用XML::Generator::DBI,它能够从执行SQL SELECT语句得到的数据中生成SAX数据。创建要求的DOM树就是建立XML::LibXML::SAX::Builder(它从SAX事件中创建XML::LibXML DOM树)的实例。

sub fetch_recordset {
my $self = shift;
my $sql = 'select id, name, price from products';

my $dbh = DBI->connect('dbi:Oracle:webclients',
'chico',
'swordfish')
|| die "database connection couldn't
be initialized: $DBI::errstr \n";

my $builder = XML::LibXML::SAX::Builder->new();
my $gen = XML::Generator::DBI->new(Handler => $builder,
dbh => $dbh,
RootElement => 'document',
QueryElement => 'productlist',
RowElement => 'product');

my $dom = $gen->execute($sql) || die "Error Building DOM Tree\n";
return $dom;}


fetch_recordset方法完成了另一项很重要的任务,但它返回的DOM树只包含我们想向客户发送信息的一部分,我们还必须获取用户输入的产品数量,另外,还需要提供一个订购产品的总计。

sub requestDOM {
my ($self, $context) = @_;
my $root = $context->{DOMTREE}->getDocumentElement();
my $grand_total = '0';

为了将当前的订货数量作为更大的文档的一部分,我们将遍历所有的产品元素,并在每行中添加和子元素。的值可以从$context->{PARAMS}域获得。

foreach my $row ($root->findnodes('/document/productlist/product')) {
my $id = $row->findvalue('id');
my $cost = $row->findvalue('price');
my $quantity = $context->{PARAMS}->{$id} || '0';
my $item_total = $quantity * $cost;
$grand_total += $item_total;

# add the order quantity and item totals to the tree.
$row->appendTextChild('quantity', $quantity);
$row->appendTextChild('item-total', $item_total);
}

最后,我们将增加一些有关订单的元信息,方法是在具有元素的根元素中添加一个元素,该元素中包含有当前所选货物的总价值。

$grand_total ||= '0.00';
my $info = XML::LibXML::Element->new('instance-info');
$info->appendTextChild('order-total', $grand_total);
$root->appendChild($info);

return $context->{DOMTREE};
}

细心的读者可能已经注意到,我们这个非常简单的应用程序在order_send方法中没有作任何实际的事。决定如何处理这些数据是产品订购应用程序中与具体的购物网站最有关的部分。

结束语
CGI::XMLApplication在CGI脚本程序的编程中提供了一种清晰的、模块化的隔离系统的内容和表示的方法,单就这一点,就值得我们对它进行一番研究。此外,它还可以使我们避免纠缠于一些细节问题,而集中精力解决主要的问题。
user="netbei";tbbg="EFEFEF";tbbd="999999";fclo="66666";dn=6;rn=5;tali="center";tbh=100;tbw=583;chtyp=2;listop=3;ltyp=1;
分享到:
评论

相关推荐

    HTML-XML-CGI.zip_UP_cgi_cgi xml_html cgi_xml CGI

    CGI(通用网关接口)是Web服务器与外部应用程序交互的一种标准。当用户提交表单或请求动态内容时,CGI脚本被调用,处理数据并返回结果。CGI脚本可以用多种编程语言编写,如Perl、Python、C++等。然而,由于CGI有性能...

    用REST Client 通过cgi接口测试网页前后端数据交互

    首先,REST(Representational State Transfer)是一种设计网络应用程序的风格和原则,它基于HTTP协议,使得客户端和服务器之间的交互变得简单且直观。REST Client是模拟这些HTTP请求的工具,允许开发者测试API或...

    Ajax 与CGI

    1. **接口规范**:CGI定义了Web服务器与外部应用程序之间的通信协议,即如何传递请求参数和接收响应。 2. **环境变量**:CGI程序通过环境变量获取HTTP请求的信息,如HTTP头、请求方法(GET、POST等)和URL。 3. **...

    cgi.rar_cgi

    这个概念在互联网发展初期起着至关重要的作用,它是Web服务器与外部应用程序之间的一种通信标准。通过CGI,Web服务器能够处理用户提交的表单数据,执行动态脚本,然后返回结果到用户的浏览器。在物理层面上,CGI程序...

    cgi ajax js 刷新 html1

    首先,CGI是一种标准,允许Web服务器与外部应用程序进行交互,从而提供动态内容。当用户通过浏览器发送请求到服务器时,CGI脚本被调用,处理数据并返回结果。这些脚本通常用Perl、Python、C或其它编程语言编写。CGI...

    cgi ajax js 刷新 html

    CGI (Common Gateway Interface)、AJAX (Asynchronous JavaScript and XML) 和 JavaScript 是Web开发中的关键技术,它们在构建动态和交互式的网页应用中扮演着重要角色。这些技术各有其特点和用途,通常一起使用以...

    计算器cgic

    CGI的核心思想是作为Web服务器与外部应用程序之间的桥梁。当用户通过浏览器发送HTTP请求到服务器时,CGI程序会被调用,接收这些请求并生成动态内容。这个内容可以是HTML、XML或其他任何格式,然后由服务器返回给...

    一种基于XML和ADO技术的异构数据库访问中间件的设计与实现.pdf

    【中间件】是一种软件,它位于应用程序和操作系统之间,提供了一种抽象层,使得应用程序可以独立于底层操作系统和硬件进行数据访问。中间件扮演着桥梁的角色,简化了跨平台的数据交互,增强了系统的可扩展性和互操作...

    cgi基础网络脚本教程

    ### CGI基础网络脚本教程详解 #### CGI脚本概述 CGI(Common Gateway Interface)是一种标准接口,允许Web服务器执行外部程序(通常是脚本)...掌握CGI脚本的基本原理和技术对于理解和构建动态Web应用程序至关重要。

    第10章应用CICSWebService实现CICS程序Web服务封装.ppt

    综上所述,CICS Web Service 的实现旨在利用 Web 服务的特性,克服传统桌面应用程序的发布和通信难题,实现 CICS 交易的现代化和互操作性,适应不断演进的 IT 环境。通过这种方式,企业可以更好地整合现有资产,提高...

    Flash+xml四屏焦点图代码.zip_Flash+xml四屏焦点图代码

    在这个项目中,“Flash+xml四屏焦点图代码”意味着Flash应用程序利用了XML文件来存储和管理焦点图的元数据,如图片路径、描述等。XML文件(data.xml)可能包含以下结构: ```xml &lt;src&gt;images/1.jpg 图片1描述 ...

    C Sharp Developer's Guide To Asp Net, Xml, And Ado Net.pdf

    ### C# 开发者指南:ASP.NET、XML与ADO.NET ...以上介绍的是 ASP.NET 的一些核心概念和优势,接下来的部分将深入探讨如何使用 C# 开发 ASP.NET 应用程序,以及如何有效地利用 XML 和 ADO.NET 进行数据管理和操作。

    javaweb应用基础(ppt)

    JavaWeb应用基础是Web开发领域中的重要组成部分,它涉及到如何构建和部署可以在互联网或局域网上通过浏览器访问的应用程序。Web应用通常由一系列相互关联的网页组成,这些网页可以是静态的,也可以是动态的,根据...

    Java Web应用开发模式研究.pdf

    Java Web应用开发模式是利用Java技术进行Web应用程序构建的方法,其在提高系统稳定性和开发效率方面具有显著优势,因此在IT领域备受关注。本文将深入探讨Java Web应用的基本概念、常用开发模式及其工作原理。 首先...

    XML HTTP资料

    XML HTTP资料主要涉及的是在MSXML库中使用的Microsoft.XMLHTTP对象,它允许开发人员通过HTTP协议发送异步或同步请求,获取服务器上的数据...这种方法在现代Web开发中非常常见,特别是在构建富互联网应用程序(RIA)时。

    web服务器.docx

    所有这些复杂的业务逻辑都在应用程序服务器内部处理,而Web服务器则负责将最终的结果以合适的格式(如JSON或XML)返回给用户界面,使得客户端能够显示和交互。 综上所述,Web服务器和应用程序服务器在互联网服务中...

    编程设计Web Library

    ASP.NET是微软公司推出的用于构建动态网站、Web应用程序和Web服务的框架。它基于.NET Framework,提供了丰富的服务器控件、内置的安全机制和高效的数据绑定,使得开发者能够快速地创建功能强大的Web应用。ASP.NET的...

    互联网项目的技术选择与应用.pdf

    SGML(Standard Generalized Markup Language)是XML的前身,随着技术发展,XML和HTML5成为现代Web开发的标准,为互联网项目提供了更丰富的结构和语义化标记。 9. 网站选择 选择技术时要考虑项目规模、团队技能、...

    fastcgiqt:使用 Qt 和 C++ 编写 Web 应用程序的库

    **FastCGIQt:利用Qt和C++构建Web应用程序的库** FastCGIQt是一个针对Qt框架和C++编程语言的库,旨在帮助开发者高效地创建Web应用程序。FastCGI(Fast Common Gateway Interface)是一种协议,它允许Web服务器与...

    报表开发中的应用iw

    **与ASP.NET Web Forms模式相似**:IntraWeb借鉴了ASP.NET Web Forms的设计理念,支持服务器端事件处理,如Button的OnClick事件,使得从Windows应用程序过渡到Web应用的学习曲线变得平滑,无需掌握复杂的HTML、XML、...

Global site tag (gtag.js) - Google Analytics