對象|資料|資料庫
說非資料庫方式,有些託大,但在沒有資料庫的情況下,也算給了一個鍛煉的好機會,更何況本人對有事沒事就整資料庫玩的方式是深惡痛絕,有些時候,在資源有限及功能簡單的情況下,利用檔案管理本身就能很好的實現一個系統,又何必非用資料庫不可呢?
好的,開說 ASP 程式, ASP 程式強大的原因主要在於 COM 物件的擴充,所以在一陣的頭腦風暴後,打起了一套組合拳: Scripting.FileSystemObject , Scripting.Dictionary 以及 Msxml2.DOMDocument.4.0 。
下面就以檔案管理程式為例,對實現做簡要說明:
首先,是構思。
1. 管理的資料對象是檔案對象,而檔案對象可以對應到 XML 中的某個結點
2. 檔案對象的結構,可以自行定義
3. 檔案對象的增加、刪除、修改以及查詢
XML 中充分利用 Xpath ,實現查詢比較簡單,所以構思後問題主要應該歸結為 XML 結點的增刪改的問題,以及對象結構的定義。增刪改不必多說,關鍵是對象結構的自訂(在物件導向中就是類的聲明)。
接下來,是實現。
一是結構檔案
這裡結構包括:英文名字,中文顯示名,類型,顯示模版(或參照),預設值等
其實就是類似 schema 的東西,然後把這些結構儲存在一個檔案中,很多操作時就可以在迴圈中自動處理了,比如顯示一個檔案時,就可以按照這個結構來顯示所有屬性欄位。
如下為一個結構檔案 documentx.dna 的示範內容:
*/DOCS= 檔案
*/DOCS/@VERSION= 版本 %%STRING%%[NUM].[NUM].[NUM].[NUM]%% 1.0.0 .0
*/DOCS/DOC= 檔案
+/DOCS/DOC/@ID= 標識 %%STRING%%%%=UniqueID()
+/DOCS/DOC/@HOT= 人氣 %%NUM%%%%0
/DOCS/DOC/TITLE= 標題
/DOCS/DOC/DEPARTFROM= 來文單位 %%DICTIONARY%%department%%
/DOCS/DOC/@DONE= 是否處理完畢 %%BOOL%%%%
需要說明的是英文名稱採用 Xpath 的方式,是為了方便 XML 處理。
英文名稱前加 * 號表示為系統欄位,同時也是非檔案對象的屬性欄位
英文名稱前加 + 表示該欄位對使用者來說是唯讀,其值由系統指定。
另外前加 * 或者加 + 號也好,也有防止誤刪的原因,因為 * 號或 + 號是不會顯示給使用者的。
用 = 號分隔英文名稱與其他部分,而其他部分中用 %% 分隔,依次為中文顯示名,該項類型,顯示模版(或參照),預設值。
需要說明的是類型,如果類型為 DICTIONARY 的話,顯示模版(或參照)或參照的為具體的 DICTIONARY 檔案, DICTIONARY 的儲存形式,形同 Delphi 中 TstringList 的儲存形式,用 = 號把關鍵字與值分隔:
CS1= 測試單位 1
CS2= 測試單位 2
二是利用建立一個檔案,說明顯示的問題
先看示範檔案:
<% @LANGUAGE=VBSCRIPT %>
<%
Dim sKey, sValue, Sign, Pos, AttrID, Values, F, FName, Count
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta http-equiv="Content-Language" content="zh-cn">
</head>
<body>
<form method="POST" action="Documents!Save.asp">
<table border="0" width="100%" cellpadding="0" style="border-collapse: collapse">
<tr>
<td bgcolor="#C 0C 0C 0"><b> 建立 </b></td>
</tr>
<tr>
<td>
<table border="1" width="100%" cellspacing="0" cellpadding="0" style="border-collapse: collapse" bordercolor="#000000">
<tr>
<td width="10%"> 項 </td>
<td> 值 </td>
</tr>
<%
'Count = 0
'DOCUMENTX 為 Scripting.Dictionary 對象,為 documentx.dna 的內容
For Each sKey In DOCUMENTX
Sign = Left(sKey, 1)
If Sign<>"*" Then
sValue = DOCUMENTX.Item(sKey)
Values = Split (sValue & "%%%%%%", "%%")
Pos = InStrRev(sKey, "/")
AttrID = Right(sKey, Len(sKey) - Pos)
If Left(AttrID,1)="@" Then
AttrID = Mid(AttrID, 2) & "_INLINE" ' 也就是說 @ 為一般為內建屬性
End If
AttrID = "ATTR_" & AttrID
%>
<tr>
<td width="10%"><%=Values(0)%></td>
<td>
<%
If Sign="+" Then ' 如果為唯讀屬性
%>
<input type="hidden" name="<%=AttrID %>" value="" /> 系統計算: <%=Values(3) %>
<%
Else
' 按照類型進行顯示
If Values(1)="BOOL" Then
Response.Write "<input type=""checkbox"" name=""" & AttrID & """ value=""1"" />"
Else
If Values(1)="DICTIONARY" Then
'ENVIRONMENT 為 Scripting.Dictionary 對象
'ENVIRONMENT.Item(“ROOT”) 中儲存了該程式管理的根目錄
FName = ENVIRONMENT.Item("ROOT") & "\dictionary\" & Values(2) & ".dic"
%>
<select name="<%=AttrID %>">
<%
If FSO.FileExists(FName) Then
Set F = FSO.OpenTextFile(FName, 1, False)
Do While Not F.AtEndOfStream
sValue = F.ReadLine
Pos = InStr(sValue, "=")
If Pos>0 Then
Response.Write "<option value=""" & Left(sValue, Pos-1) & """>" & Right(sValue, Len(sValue)-Pos) & "</option>"
End If
Loop
F.Close
End If
%>
</select>
<%
Else
Response.Write "<input type=""textbox"" name=""" & AttrID & """ size=""30"" />"
End If
End If
End If
%>
</td>
</tr>
<%
'Count = Count + 1
End If
Next
%>
<tr>
<td width="10%"> </td>
<td> </td>
</tr>
<tr>
<td width="10%"> </td>
<td> </td>
</tr>
</table>
</td>
</tr>
<tr>
<td bgcolor="#C 0C 0C 0" align="right" valign="middle"><input type="submit" name="btnSave" value=" 儲存 " /> <input type="button" name="btnReset" value=" 重輸 " /></td>
</tr>
</table>
</form>
</body>
</html>
三是利用代碼說明 xml 儲存的實現
<% @LANGUAGE=VBSCRIPT %>
<!-- #include file="System.inc.asp" -->
<!-- #include file="Document.inc.asp" -->
<%
'System.inc.asp 中包含 UniqueID() 函數
' 首先,擷取使用者用戶端提交的資料資訊
Dim PostData
Set PostData = Server.CreateObject("Scripting.Dictionary")
Dim Values, Key, Value, AttrID, Pos, Sign
For Each Key I