XML和現代CGI應用程式

2021-03-31 08:56:30 字數 4967 閱讀 8376

出處: http://.ccid***.***/tech/web/2002/01/07/92_3901.html

簡介 perl的普及與網際網路的蓬勃發展有直接的關係。在網際網路發展的早期,人們發現僅僅使用靜態的html文件不能生成有效的互動式環境,於是引進了公用閘道器介面(cgi)的概念。perl強大的功能和容易擴充的特性使得它成為開發cgi應用最自然的選擇,並由此迅速地成為cgi指令碼的首選語言。cgi本身並非十全十美。但由於得到了眾多開發商的青睞,cgi的應用至今仍然十分廣泛,而且沒有跡象表明在近期會「退休」。

例1:cgi xslt閘道器

為了重點說明這種分離,我們的第乙個例子不是傳統意義上的web應用,而是乙個通用的xslt閘道器,它可以新增到伺服器的cgi-bin中,將整個xml內容的目錄樹轉化為符合請求的瀏覽器的格式,而這一切對於使用者、樣式表和文件的作者而言也都是透明的。

第一步是建立連線客戶端的請求和應用的cgi指令碼。我們希望xml文件能夠方便地通過url瀏覽,並使建立這些文件間的超連結非常直觀。因此,我們將建立乙個沒有副檔名的cgi指令碼,以便將它作為url路徑中的乙個節點,節點右邊的所有內容將在包含xml內容的虛擬文件環境中進行解釋。在這種情況下,我們將cgi稱作是樣式表選擇者。

use strict;

use xslgateway;

use cgi qw(:standard);my $q = cgi->new();

my %context = ();

my $gateway_name = 'stylechooser';

在載入合適的模組和設定一些在整個指令碼範圍內有效的變數後,我們開始向被傳遞給處理該應用邏輯的類的%context中新增一些域。在這個應用軟體中,我們只傳輸要求的指向指令碼檔案路徑右邊的url(request條目)和包含有儲存在查詢引數style中的資料的style關健字。

$context = $q->url(-path => 1);

$context =~ s/^$gateway_name//?//;

$context ||= 'index.xml';

$context = $q->param('style') if $q->param('style');

最後,我們建立了xslgateway邏輯類的乙個例項,並通過呼叫其run方法處理請求,將%context作為唯一的引數。

cgi指令碼就完成了。下面我們建立完成大部分工作的xslgateway模組:

package xslgateway;

use strict;

use vars qw(@isa);

use xml::libxml;

selectstylesheet返回有關的xslt樣式表的全檔案系統路徑。為了簡單起見,我們假定樣式表將儲存在乙個單一的目錄中。我們可以通過$context->域提供其他的樣式表,從而增加系統的靈活性。

sub selectstylesheet || 'default';

my $style_path = '/opt//htdocs/stylesheets/';

return $style_path . $style . '.xsl';

} 下一步,我們需要建立requestdom方法,該方法將返回被傳輸的xml文件的xml::libxml dom表示式。由於我們的閘道器只適用於靜態檔案,我們需要使用xml::libxml對文件進行解析,並返回結果樹。

sub requestdom || 'index.xml';

my $doc_path = '/opt//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//htdocs/xmldocs/目錄中選取mydocs/somefile.xml檔案,使用/opt//htdocs/stylesheets/中的樣式表default.xsl對該檔案進行轉換,並將它傳輸給客戶。

如果需要,我們可以擴充這一基本的框架,例如,可以在樣式表選擇cgi指令碼程式新增一些查詢元件,選擇合適的樣式表,可以設定或讀取http cookies,對**進行修飾。

例2:乙個簡單的購物系統

與上個例子相同,這個應用程式中與cgi-bin有關的部分仍然非常地少。我們所需要作的只不過是初始化customerorder應用類並呼叫它的run()方法。這次,我們將cgi.pm中vars作為%context的params域:

use strict;

use cgi qw(:standard);

use customerorder;

my $q = cgi->new();

my %context = ();

$context = $q->vars;

在這個例子中,我們假定該應用中的產品資訊儲存在關聯式資料庫中,產品清單不是太長,使我們在應用中不會出現多屏才能顯示相關資訊的麻煩:使用者輸入訂購的產品數量的主要資料輸入屏,顯示訂購單內容和所選物品總**的確認屏,顯示訂單已經處理的提示。為了簡單起見,我們在這裡沒有涉及送貨和財務資料的輸入等問題。

package customerorder;

use strict;

use vars qw(@isa);

use xml::libxml::sax::builder;

use xml::generator::dbi;

use dbi;

在載入必要的模組和定義從cgi::xmlaplication中繼承的類後,我們開始建立應用中與各種狀態有關的事件呼叫。首先,我們必須通過建立registerevents()方法註冊這些事件。在本例中,我們將註冊order_confirm 和order_send方法,這二個方法設定%context中的screenstyle域。稍後,我們將利用該屬性定義在顯示客戶端的資料時應該使用三個xslt樣式表中的哪乙個。

# 事件的註冊和事件呼叫

sub registerevents

sub event_order_confirm = 'order_confirm.xsl';

} sub event_order_send = 'order_send.xsl';

} 如果沒有請求執行其他的事件,則預設地執行event_default。在本例中,我們只使用它將screenstyle域設定為乙個合適的值。

sub event_default = 'order_default.xsl';

} 每次請求都會執行event_init方法,而且總是在其他方法之前執行它,這使得它非常適合對應用中被其他事件使用的部分進行初始化。在本例中,我們使用它返回利用fetch_recordset()方法從資料庫中獲取的產品資訊的、最初的dom樹。

sub event_init = $self->fetch_recordset();

} state-handler方法完成後,我們需要執行必需的selectstylesheet和requestdom方法。

與在第乙個例子中一樣,我們假設所有的應用的樣式表都儲存在伺服器上相同的目錄中。我們所需要作的是返回$context->的值所指定的路線,並新增到末尾。

sub selectstylesheet ;

my $style_path = '/opt//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

fetch_recordset方法完成了另一項很重要的任務,但它返回的dom樹只包含我們想向客戶傳送資訊的一部分,我們還必須獲取使用者輸入的產品數量,另外,還需要提供乙個訂購產品的總計。

sub requestdom ->getdocumentelement();

my $grand_total = '0';

為了將當前的訂貨數量作為更大的文件的一部分,我們將遍歷所有的產品元素,並在每行中新增和子元素。的值可以從$context->域獲得。

foreach my $row ($root->findnodes('/document/productlist/product')) -> || '0';

my $item_total = $quantity * $cost;

$grand_total += $item_total;

# add the order quantity and item totals to the tree.

} 最後,我們將增加一些有關訂單的元資訊,方法是在具有元素的根元素中新增乙個元素,該元素中包含有當前所選貨物的總價值。

$grand_total ||= '0.00';

my $info = xml::libxml::element->new('instance-info');

return $context->;

} 細心的讀者可能已經注意到,我們這個非常簡單的應用程式在order_send方法中沒有作任何實際的事。決定如何處理這些資料是產品訂購應用程式中與具體的購物**最有關的部分。

結束語

應用程式現代化

本篇文章版權由 ecf和 hp所有 john dodge,ecf社群經理 應用程式現代化是大多數cio頭腦中最關注的,但實施的節奏及其優先性取決於幾個不同的因素。換言之,應用程式現代化很重要,但根據三位cio 他們同時也是enterprise cio forum ecf council 成員 的看法...

ios應用程式和應用程式委託

其實說白了,就是乙個類將自己不願意實現的方法以協議的方式定義,同時在這個類中包含有乙個型別為id 泛型類 的例項變數,如果另乙個類實現了這個協議,那麼另外的這個類就可以作為第乙個類的委託物件,前乙個類將自己不願意實現的類委託給後乙個類。因為第乙個類擁有第二個類的引用,所有第乙個類的例項可以直接呼叫第...

python啟動應用程式和終止應用程式

每天上班,工作需要,電腦上需要每天開機啟動一些軟體,下班時候,需要關掉一些軟體。乙個乙個開啟和關閉貌似是很繁瑣的,於是乎,這個指令碼產生了。系統環境 win7 32位 python 2.7.9 你還需要安裝pywin32。pip install pywin32 啟動應用程式指令碼 coding ut...