木子屋 Dnawo's BLOG

让ASP也支持动态include文件

👤 dnawo 📅 2008-04-09 👁 6179 👍 0 💬 2 🔄 本站原创
一直觉得ASP的include非常的别扭,一是它不能放在"<%"和"%>"之间,感觉很独特,很格格不入,二是它不能像PHP的include那样可以动态的随意包含文件!以前也有人试图解决过这个问题,但总是不尽完美,今天在pscode.com又看到有人写了个类来解决这个问题,可以说它是在我所见过的解决方法中最好的了。由于原类中存在一些不足,我稍做了修改,下边为修改后的代码:

<%
public include, include_vars
set include = new cls_include

class cls_include

	private sub class_initialize()
		set include_vars = server.createobject("scripting.dictionary")
	end sub

	private sub class_deactivate()
		arr_variables.removeall
		set include_vars = nothing
		set include = nothing
	end sub

	public default function include(byval str_path)
		dim str_source
		if str_path <> "" then
			str_source = readfile(str_path)
			if str_source <> "" then
				processincludes str_source
				convert2code str_source
				formatcode str_source
				if str_source <> "" then
					if request.querystring("debug") = 1 then
						response.write str_source
						response.end
					else
						executeglobal str_source
						include_vars.removeall
					end if
				end if
			end if
		end if
	end function

	private sub convert2code(str_source)
		dim i, str_temp, arr_temp, int_len
		dim str_separator
		str_separator = "$|"
		if str_source <> "" then
			if instr(str_source,"%" & ">") > instr(str_source,"<" & "%") then
				str_temp = replace(str_source,"<" & "%",str_separator & "%")
				str_temp = replace(str_temp,"%" & ">",str_separator)
				if left(str_temp,1) = str_separator then str_temp = right(str_temp,len(str_temp) - len(str_separator))
				if right(str_temp,1) = str_separator then str_temp = left(str_temp,len(str_temp) - len(str_separator))
				arr_temp = split(str_temp,str_separator)
				int_len = ubound(arr_temp)
				if (int_len + 1) > 0 then
					for i = 0 to int_len
						str_temp = trim(arr_temp(i))
						str_temp = replace(str_temp,vbcrlf & vbcrlf,vbcrlf)
						if left(str_temp,2) = vbcrlf then str_temp = right(str_temp,len(str_temp) - 2)
						if right(str_temp,2) = vbcrlf then str_temp = left(str_temp,len(str_temp) - 2)
						if left(str_temp,1) = "%" then
							str_temp = right(str_temp,len(str_temp) - 1)
							if left(str_temp,1) = "=" then
								str_temp = right(str_temp,len(str_temp) - 1)
								str_temp = "response.write " & str_temp
							end if
						else
							if str_temp <> "" then
								include_vars.add i, str_temp
								str_temp = "response.write include_vars.item(" & i & ")" 
							end if
						end if
						str_temp = replace(str_temp,chr(34) & chr(34) & " & ","")
						str_temp = replace(str_temp," & " & chr(34) & chr(34),"")
						if right(str_temp,2) <> vbcrlf then str_temp = str_temp
						arr_temp(i) = str_temp
					next
					str_source = join(arr_temp,vbcrlf)
				end if
			else
				if str_source <> "" then
					include_vars.add "var", str_source
					str_source = "response.write include_vars.item(""var"")"
				end if
			end if
		end if
	end sub

	private sub processincludes(str_source)
		dim int_start, str_path, str_mid, str_temp
		str_source = replace(str_source,"<!-- #","<!--#")
		int_start = instr(str_source,"<!--#include")
		str_mid = lcase(getbetween(str_source,"<!--#include","-->"))
		do until int_start = 0
			str_mid = lcase(getbetween(str_source,"<!--","-->"))
			int_start = instr(str_mid,"#include")
			if int_start >  0 then
				if instr(str_mid,chr(34))=0 then
					str_temp = replace(replace(str_mid,"#include",""),"file=","")
				else
					str_temp = lcase(getbetween(str_mid,chr(34),chr(34)))
				end if
				str_temp = trim(str_temp)
				str_path = readfile(str_temp)
				str_source = replace(str_source,"<!--" & str_mid & "-->",str_path & vbcrlf)
			end if
			int_start = instr(str_source,"#include")
		loop
	end sub

	private sub formatcode(str_code)
		dim i, arr_temp, int_len
		str_code = replace(str_code,vbcrlf & vbcrlf,vbcrlf)
		if left(str_code,2) = vbcrlf then str_code = right(str_code,len(str_code) - 2)
		str_code = trim(str_code)
		if instr(str_code,vbcrlf) > 0 then
			arr_temp = split(str_code,vbcrlf)
			for i = 0 to ubound(arr_temp)
				arr_temp(i) = ltrim(arr_temp(i))
				if arr_temp(i) <> "" then arr_temp(i) = arr_temp(i) & vbcrlf
			next
			str_code = join(arr_temp,"")
			arr_temp = vbnull
		end if
	end sub

	private function readfile(str_path)
		dim objfso, objfile
		if str_path <> "" then
			if instr(str_path,":") = 0 then str_path = server.mappath(str_path)
			set objfso = server.createobject("scripting.filesystemobject")
			if objfso.fileexists(str_path) then
				set objfile = objfso.opentextfile(str_path, 1, false)
				if err.number = 0 then
					readfile = objfile.readall
					objfile.close
				end if
				set objfile = nothing
			end if
			set objfso = nothing
		end if
	end function

	private function getbetween(strdata, strstart, strend)
		dim lngstart, lngend
		lngstart = instr(strdata, strstart) + len(strstart)
		if (lngstart <> 0) then
			lngend = instr(lngstart, strdata, strend)
			if (lngend <> 0) then
				getbetween = mid(strdata, lngstart, lngend - lngstart)
			end if
		end if
	end function
	
end class
%>

修改说明:

1.原类convert2code函数中使用"|"做为分隔符,一旦包含文件中存在Response.Write("mzwu|com")类似的语句将导致出错,用"|"做为分隔符更是大大提高了出错的机率!修改后增加了一个变量str_separator,可自由定义分隔符,降低出错率。

2.原类要求include语句中文件名必须使用双引号,否则<!-- #include file=file2.asp -->这样语句将导致file2.asp不能被包含到当前页面中,修改后无论文件名是否使用双引号都能被正常包含。

仍存在问题:

被包含文件不能含有"Option Explicit"和"<%@ ... %>"这样的语句,否则将会出错!

参考文章:

1.http://pscode.com/vb/scripts/ShowCode.asp?txtCodeId=7651&lngWId=4

评论(2)

mzidea 2009-01-11 10:33
木子好,请问一下具体怎样include文件呢?可否示例一下?谢谢!
dnawo 2009-01-11 17:52
使用cls_include对象的include方法即可动态调用
上边例子中已经声明了一个对象include,调用示例:
<%
include.include("other.asp")
%>
计算题
评论需审核通过后显示
← 上一篇 个人从事设计行业40句观感 下一篇 → 已经CheckUser了为什么还出错?