ASP将XML模拟为RS的类

XML是个很好的东西,ASP本身很弱,但配合上一些强大的服务器对象,几乎可以无所不能。就比如我之前遇到的问题,ASP base64编码和解码,原生函数出来的结果总是有误差,但使用XML对象上的功能,就完美地解决问题了。

还有二进制内容的生成,ASP本身也是无法实现的(只能读取)。XML的很多优势,用在ASP中给ASP的效率和优美度都增添了光彩。

但这一次,我却想把XML模拟成ASP中另外的一个强大的对象 Recordset

对了,ASP缺了ADODB组件,基本上就瘫痪了。ADODB中的connection,recordset,stream都是ASP离不开的对象。深入查看下手册,会发现很多有用的东西。

下面这个,我就想把XML的读取,写入,筛选机制模拟成Recordset来操作。虽然功能上不是很理想,但基本操作流程都走通了。

这个XML用来作数据缓存很不错

本代码同步发表在开源中国:将XML数据模拟成Recordset对象的类

测试截图:

先帖测试代码(里面假定打开了一个数据库连接,conn,并有一个分类表news_class):

Dim Rs, tmp, i
Set Rs=New xmlRs
'Set tmp=Server.Create0bject("MSXML.DOMDocument")
'tmp.async=False
'tmp.load(Server.MapPath("/cache/News/newsclass.xml"))
'从DOMList打开
'Rs.Open tmp.documentElement.childNodes,True

'从记录集打开
'如果要直接保存xml文件,必须先指定路径
Rs.Path="a.xml"
Rs.Open conn.Execute("SELECT * FROM news_class"),True

'从文件打开
'Rs.Open "class.xml",True

Rs.Find "id>0"
Response.Write "本次查询到的记录数:"
Response.Write rs.Count&"<br />"

'注意.xpath中不可使用 <> 表示不等于,只能用 !=
'xPath运算符:http://www.w3school.com.cn/xpath/xpath_operators.asp
Dim startTime
startTime = Timer
For i = 0 To 100
	Rs.Exec "SELECT * FROM table WHERE Id>0 AND className!='22' And lang='cn'"
Next
Response.Write "100次查询所耗时间:"& CCur(Timer - startTime)&" s<br />"

startTime = Timer
For i = 0 To 100
	Rs.Exec "SELECT * FROM table WHERE Id>0 AND className!='22' And lang='cn' Order by classname asc, ID DESC"
Next
Response.Write "100次查询排序所耗时间:"& CCur(Timer - startTime)&" s<br />"
Response.Write "本次查询到的记录数:"
Response.Write rs.Count&"<br />"

'删除该行
'Rs.Delete

'Rs.Update

'call FindTest( rs)
'call OrderTest( rs)
call ReadTest( rs)

'call WriteTest( rs)

'call UpdateTest( rs)

'call ReadTest( rs)


'//=======测试函数==================//
Sub FindTest( rs)
	Rs.Find "id>=2"
End Sub

Sub OrderTest( rs)
	Rs.Order "id desc,classname desc"
End Sub

Sub ReadTest( rs)
	rs.MoveFirst
	Do Until Rs.EOF
		Response.Write Rs("id")&";"
		Response.Write Rs("classname")&";"
		Response.Write Rs("enname")
		Response.Write "<br />"
		Rs.MoveNext
	Loop
End Sub

Sub WriteTest( rs)
	Dim i
	i=0
	Response.Write Rs.RecordCount &"<br />"
	rs.MoveFirst
	Do Until Rs.EOF
		i  = i + 1
		Response.Write "原值:"
		Response.Write Rs("id")&";"
		Response.Write Rs("classname")&";"
		Response.Write Rs("enname")
		Response.Write "<br />"
		Rs("id") = i
		Rs("classname") = Rs("classname") & i
		Rs("enname") = Rs("enname") &i
		Response.Write "新值:"
		Response.Write Rs("id")&";"
		Response.Write Rs("classname")&";"
		Response.Write Rs("enname")
		Response.Write "<br />"
		Rs.MoveNext
	Loop
	Rs.Update
End Sub

Sub UpdateTest( rs)
	Rs.Exec "UPDATE   [TABLE]   SET [id]=1 , [classname]=222,[enname]='<我是 , 一个兵>'"
End Sub

Sub InsertTest( rs)
	Rs.Exec "INSERT INTO [TABLE] ([id],[classname],[enname]) VALUES(1,'as''dddd','asd<>asdn')"
End Sub
'//=======测试函数 END==============//

 

下面是类原码(友情提示:代码中部分字符作了替换,使用时需要替换回原英文字符,原因是服务器有特殊字符过滤)

'====================================
' 类名: xmlRs
' 用途: 将XML数据模拟成Rs数据操作
' 作者: shirne
' 网址: http://www.shirne.com
' 说明: 操作完成调用update才可以更新到文件
' 		1.字段筛选的功能暂未实现
'		2.排序效率不太好,一般不要用
'		3.更新或插入语句中只支持简单赋值
' 更新: 2012/12/20
'====================================
Class xmlRs
	Private DOM			'XML文档对象
	Private DOMList		'数据列表
	Private pPosition	'指针位置
	Private pCount		'记录数
	Private pBOF		'是否超出开始
	Private pEOF		'是否超出结尾
	Private pState		'状态
	
	Private pPath		'对应的文件路径
	Private xPath		'查询条件的xPath格式
	
	Public	IDStr		'创建的DOM类型,默认为MSXML2.DOMDocument,可以设定为其它类型
	Public	DBName		'根节点的名称
	Public	TblName		'行节点的名称
	Public	Charset		'编码
	
	Public	currentNode	'当前节点,如果调用了AddNew,则是新创建的节点
	
	Private Field		'字段(一个XML节点对象)
	Private ph			'字符串占位符
	
	Public	SQLMode		'SQL语句解析模式(True 严格解析)
	
	Private Sub Class_Initialize
		pCount	= 0
		pBOF	= True
		pEOF	= True
		pState	= 0
		pPosition= 0
		
		DBName	= "data"
		TblName	= "table"
		
		Charset	= "utf-8"
		
		ph	= Chr(0)
		
		SQLMode= True
		
		xPath  = ""
		
		'MSXML3.DOMDocument
		'MSXML2.FreeThreadedDOMDocument
		IDStr	= "MSXML2.DOMDocument"
	End Sub
	
	Private Sub Class_Terminate
		Set DOM=Nothing
		Set currentNode=Nothing
		If IsArray(DOMList) Then Erase DOMList
	End Sub
	
	'xml对象或路径,是否创建文件
	Public Function Open(xml, create)
		Set DOM = Server.Create0bject(IDStr)
		DOM.async	= False
		Select Case TypeName(xml)
		Case "String"
			If InStr(xml,"<")>0 Then
				If Not DOM.LoadXML(xml) Then
					ErrRaise 5,"xmlRs.Open:错误的XML代码"
				End If
			Else
				Path	= xml
				If Not DOM.Load(pPath) Then
					If create Then
						DOM.LoadXML("<?xml version=""1.0"" encoding="""& Charset &"""?><"& DBName &" />")
					Else
						ErrRaise 5,"xmlRs.Open:错误的文件路径"
					End If
				Else
					create=False	'从文件打开的,不用再次保存
				End If
			End If
			Call setList
		Case "DOMDocument"
			Set DOM	= xml
			Call setList
		Case "IXMLDOMElement"
			DOM.LoadXML("<?xml version=""1.0"" encoding="""& Charset &"""?><"& DBName &" />")
			DOM.documentElement.appendChild(xml)
			Call setList
		Case "IXMLDOMNodeList"
			DOM.LoadXML("<?xml version=""1.0"" encoding="""& Charset &"""?><"& DBName &" />")
			DOM.documentElement.appendChild(xml)
			Call setList
		Case "Recordset"
			DOM.LoadXML("<?xml version=""1.0"" encoding="""& Charset &"""?><"& DBName &" />")
			Call DataToXML(xml)
		Case Else
			ErrRaise 5,"xmlRs.Open:不支持的初始化数据类型:"& TypeName(xml)
		End Select
		
		If create Then
			Call Update
		End If
		
		Call setProp
		
		pState	= 1
		
		If pCount>0 Then TblName	= currentNode.nodeName
	End Function
	
	'//获取和设置字段值,一律转换为小写
	Public Default Property Get Item(key)
		If pBOF Or pEOF Then Exit Property
		Set Field=currentNode.selectSingleNode(LCase(key))
		If Field Is Nothing Then
			Item = Empty
		Else
			Item = Field.Text
		End If
	End Property
	Public Property Let Item(key, val)
		If pBOF Or pEOF Then Exit Property
		Set Field=currentNode.selectSingleNode(LCase(key))
		If Field Is Nothing Then
			Set Field = DOM.createElement(LCase(key))
			currentNode.appendChild(Field)
		End If
		If Not IsNull(val) Then
			Field.Text = CStr(val)
		End If
	End Property
	
	'//是否到达头部或尾部
	Public Property Get BOF
		BOF	= pBOF
	End Property
	Public Property Get EOF
		EOF	= pEOF
	End Property
	
	'//获取和设定路径
	Public Property Get Path
		Path	= pPath
	End Property
	Public Property Let Path(val)
		If InStr(val,":")<1 Then
			val = Server.MapPath(val)
		End If
		pPath	= val
	End Property
	
	'//状态
	Public Property Get State
		State	= pState
	End Property
	
	'//获取记录数
	Public Property Get Count
		Count	= pCount
	End Property
	'//别名
	Public Property Get RecordCount
		RecordCount	= pCount
	End Property
	
	'//获取记录集位置
	Public Property Get Position
		Position	= pPosition
	End Property
	'//别名
	Public Property Get AbsolutePosition
		AbsolutePosition	= pPosition
	End Property
	
	'//设置记录集位置
	Public Property Let Position(val)
		If val>0 And val<=pCount Then
			pPosition	= val
			Set currentNode=DOMList(pPosition-1)
			If pEOF Then
				pEOF = False
			End If
			If pBOF Then
				pBOF = False
			End If
		Else
			ErrRaise 9,"xmlRs.Position:超出记录集"
		End If
	End Property
	'//别名
	Public Property Let AbsolutePosition(val)
		Position	= val
	End Property
	
	'//移动指定的行数
	Public Sub Move( iNum)
		If pBOF And iNum<0 Then
			ErrRaise 5,"xmlRs.Move:指针已经超出记录头"
		End If
		If pEOF And iNum>0 Then
			ErrRaise 5,"xmlRs.Move:指针已经超出记录尾"
		End If
		
		If iNum=0 Then Exit Sub
		
		pPosition = pPosition+iNum
			
		Call ChkProp
	End Sub
	'//移动到第一条记录
	Public Sub MoveFirst
		If pCount>0 Then pPosition = 1
		Call ChkProp
	End Sub
	'//移动到最后一条记录
	Public Sub MoveLast
		pPosition = pCount
		Call ChkProp
	End Sub
	'//移动到前一条记录
	Public Sub MovePrevious
		If pBOF=False Then
			pPosition = pPosition-1
		End If
		Call ChkProp
	End Sub
	'//移动到下一条记录
	Public Sub MoveNext
		If pEOF=False Then
			pPosition = pPosition+1
		End If
		Call ChkProp
	End Sub
	
	'//添加一条新的记录
	Public Sub AddNew
		Set currentNode = DOM.createElement(TblName)
		DOM.documentElement.appendChild(currentNode)
		pCount	= pCount + 1
		pPosition = pCount
		pBOF	= False
		pEOF	= False
	End Sub
	
	'//保存,对于已经指定路径的xml文件
	Public Sub Update
		If pPath = "" Then ErrRaise 5,"xmlRs.Update:路径设定不正确"
		DOM.Save pPath
	End Sub
	
	'//可以指定路径保存
	Public Sub Save( savePath)
		If savePath<>"" Then Path = savePath
		Call Update
	End Sub
	
	Public Function DataToXML( rs)
		If rs.State<>1 Then ErrRaise 5,"xmlRs.DataToXML:记录集尚未打开"
		Dim f
		Do Until rs.EOF
			AddNew
			For Each f In rs.Fields
				Item(f.Name) = f.Value
			Next
			rs.MoveNext
		Loop
		pPosition = 1
		Call setList
	End Function
	
	'//执行sql
	Public Function Exec( sql)
		Dim objSQL, j
		Set objSQL = SplitSQL(sql, SQLMode)
		
		If objSQL("table")<>"" Then TblName = objSQL("table")
		
		'测试分解后的sql
'		Dim Fld,j
'		For Each Fld In objSQL
'			If IsArray(objSQL(Fld)) Then
'				Response.Write Fld&":"
'				For j=0 To UBound(objSQL(Fld))
'					Response.Write objSQL(Fld)(j)&";"
'				Next
'				Response.Write "<br />"
'			Else
'				Response.Write Fld&":"& objSQL(Fld)&"<br />"
'			End If
'		Next
		
		Select Case LCase(objSQL("type"))
		Case "select"
			Find objSQL("where")
			Order objSQL("order")
		Case "update"
			Find objSQL("where")
			Do Until pEOF
				For j=0 To UBound(objSQL("field"))
					Item(objSQL("field")(j))=objSQL("value")(j)
				Next
				MoveNext
			Loop
			Update
		Case "insert"
			AddNew
			For j=0 To UBound(objSQL("field"))
				Item(objSQL("field")(j))=objSQL("value")(j)
			Next
			Update
		Case "delete"
			Find objSQL("where")
			Do Until pEOF
				Call Delete
				MoveNext
			Loop
		Case Else
			ErrRaise 5,"xmlRs.Exec:SQL语句类型不正确"
		End Select
	End Function
	
	'//查找,使用xPath原生方法查找,所以where语句仅支持xPath语法
	Public Sub Find( wre)
	
		If wre<>"" Then
			
			xPath = "/"& DBName &"/"& TblName &"["& wre &"]"
		Else
			xPath = ""
		End If
		
		Call setList
		
		Call setProp
	End Sub
	
	'//对结果进行排序,支持多个字段
	Public Sub Order( odr)
		If pCount<2 Then Exit Sub
		If odr = "" Then Exit Sub
		Dim prevVal, arrSort, i
		
		If InStr(odr,"[")>0 Then
			odr = Replace(Replace(odr,"[",""),"]","")
		End If
		arrSort = Split(odr,",")
		
		'开始排序
		'主排序
		Dim sField, subField, objA, objB, a,b,j,k
		sField = Split(Trim(arrSort(0))," ")
		If UBound(sField)<1 Then
			ReDim Preserve sField(1)
			sField(1) = "ASC"
		Else
			sField(1) = UCase(sField(1))
		End If
		'字段名转换为小写
		sField(0) = LCase(sField(0))
		For j=0 To pCount-1
			For k=j+1 To pCount-1
				Set objA = DOMList(j).selectSingleNode(sField(0))
				Set objB = DOMList(k).selectSingleNode(sField(0))
				If objA Is Nothing Then
					a = "0"
				Else
					a = objA.Text
				End If
				If objB Is Nothing Then
					b = "0"
				Else
					b = objB.Text
				End If
				
				Select Case Compare(a,b)
				Case 1
					If sField(1) = "ASC" Then
						Call Swap(j,k)
					End If
				Case -1
					If sField(1) = "DESC" Then
						Call Swap(j,k)
					End If
				Case 0
					'主排序相等时启动副排序
					For i=1 To UBound(arrSort)
						If IsArray(arrSort(i))=False Then
							subField = Split(arrSort(i)," ")
							If UBound(subField)<1 Then
								ReDim Preserve subField(1)
								subField(1) = "ASC"
							Else
								subField(1) = UCase(subField(1))
							End If
							'字段名转换为小写
							subField(0) = LCase(subField(0))	
							arrSort(i) = subField
						End If
						subField = arrSort(i)
						
						Set objA = DOMList(j).selectSingleNode(subField(0))
						Set objB = DOMList(k).selectSingleNode(subField(0))
						If objA Is Nothing Then
							a = "0"
						Else
							a = objA.Text
						End If
						If objB Is Nothing Then
							b = "0"
						Else
							b = objB.Text
						End If
						
						'副排序有结果则退出,无则进行下一轮副排序
						Select Case Compare(a,b)
						Case 1
							If subField(1) = "ASC" Then
								Call Swap(j,k)
							End If
							Exit For
						Case -1
							If subField(1) = "DESC" Then
								Call Swap(j,k)
							End If
							Exit For
						End Select
					Next
				End Select
			Next
		Next
		
		'重设属性
		Call setProp
	End Sub
	
	Public Sub Delete
		If pBOF Or pEOF Then Exit Sub
		DOM.documentElement.removeChild(currentNode)
		Call setList
		Call setProp
	End Sub
	
	'解析SQL语句
	'Param:sql 要解析的sql语句
	'Param:sMode	是否执行严格解析,暂未支持
	'允许有字符串的位置: 更新的值中
	Public Function SplitSQL( oSql, sMode)
		Dim L, i, ii, iA, iB, Rst, sql
		
		oSql = Trim(oSql)
		
		'清除与占位符冲突的字符,这里使用了两种占位符
		If InStr(oSql,ph) Then oSql =  Replace(oSql,ph,"")
		If InStr(oSql,Chr(1)) Then oSql =  Replace(oSql,Chr(1),"")
		
		L = Len(oSql)
		sql = oSql
		
		If L < 6 Then ErrRaise 5,"xmlRs.SplitSQL:SQL语句错误"
		Set Rst = Server.Create0bject("Scripting.Dictionary")
		Rst.CompareMode = 1
		
		'严格模式下将字符串替换为占位符
		If sMode Then
			For i=1 To L
				i = InStr(i,sql,"'")
				If i>0 Then
					ii = InStr(i+1,sql,"'")
					Do Until Mid(sql,ii+1,1)<>"'"
						ii = InStr(ii+2,sql,"'")
						If ii<1 Then
							ErrRaise 5,"xmlRs.SplitSQL:SQL语句语法错误:"& Mid(oSql,i,20)
						End If
					Loop
					sql = Left(sql, i) & String(ii-i-1,ph) & Mid(sql, ii)
					i = ii
				Else
					Exit For
				End If
			Next
		End If
		
		'//规范化sql	去除多余空格,去除,两边的空格
		'//严格模式下不会影响字符串中的内容
		Call ClearSQL(sql, oSql)
		
		L = Len(sql)
		
		
		Rst.Add "type",Left(oSql,InStr(oSql," ")-1)
		
		'查找各关键字的位置
		Dim iTop, iWhere, iOrder, iSet, iValue, iTmp, iEnd, iFrom, iInto
		'//前面加一个空格防止字段名有相同的(字段名是关键字就用[top])
		iTop = InStr(1,sql," top",1)
		iSet = InStr(1,sql," set",1)
		iValue=InStr(1,sql," values",1)
		iWhere=InStr(1,sql," where",1)
		iOrder=InStr(1,sql," order by",1)
		iFrom =InStr(1,sql," from",1)
		iInto = InStr(1,sql," into",1)
		
		Dim strFld, strVal, arrVal, iVal
		Select Case LCase(Rst("type"))
		Case "select"
			If iTop>0 Then
				iTmp = InStr(sql,iTop+4," ")
				iEnd = InStr(iTmp+1,sql," ")
				If iTmp<1 Or iEnd<1 Then
					ErrRaise 5,"xmlRs.SplitSQL:SQL语句语法错误,"& Mid(oSql,iTop,40) &" 附近有语法错误"
				End If
				Rst.Add "top",Mid(oSql,iTop+4,iTmp-iTop-4)
				Rst.Add "field",Mid(oSql,iTmp,iEnd-iTmp)
			Else
				iTmp = InStr(sql," ")+1
				iEnd = InStr(iTmp+1,sql," ")
				Rst.Add "field",Mid(oSql,iTmp,iEnd-iTmp)
			End If
			Rst.Add "table",Mid(oSql,iFrom+6,InStr(iFrom+6,sql," ")-iFrom-6)
		Case "update"
			Rst.Add "table",Mid(oSql,8,InStr(8,sql," ")-8)
			If iSet<1 Then
				ErrRaise 5,"xmlRs.SplitSQL:SQL语句语法错误,"& Mid(oSql,1,30) &" 缺少 SET"
			End If
			
			'取出字段及值
			If iWhere>0 Then
				arrVal = Split(Mid(sql, iSet+5,iWhere-iSet-5),",")
				strVal = Mid(oSql, iSet+5,iWhere-iSet-5)
			Else
				arrVal = Split(Mid(sql, iSet+5),",")
				strVal = Mid(oSql, iSet+5)
			End If
			
			Dim iEqal
			iTmp = 1
			For iVal=0 To UBound(arrVal)
				iEnd = Len(arrVal(iVal))
				arrVal(iVal)=Mid(strVal,iTmp,iEnd)
				iTmp = iTmp + iEnd + 1
				
				iEqal = InStr(arrVal(iVal),"=")
				
				If iEqal<1 Then
					ErrRaise 5,"xmlRs.SplitSQL:SQL语句语法错误,"& Mid(arrVal(iVal),1,30) &" 缺少 ="
				End If
				
				strFld = strFld& Mid(arrVal(iVal), 1, iEqal-1) & ","
				
				arrVal(iVal)=Mid(arrVal(iVal),iEqal+1)
				If InStr(arrVal(iVal),"'")=1 Then
					arrVal(iVal)=Mid(arrVal(iVal),2,Len(arrVal(iVal))-2)
					If InStr(arrVal(iVal),"''")>0 Then
						arrVal(iVal) = Replace(arrVal(iVal),"''","'")
					End If
				End If
			Next
			
			strFld = Left(strFld,Len(strFld)-1)
			If InStr(strFld,"[")>0 Then strFld=Replace(Replace(strFld,"[",""),"]","")
			Rst.Add "field",Split(strFld,",")
			
			Rst.Add "value",arrVal
		Case "insert"
			'取出表名
			If iInto<1 Then ErrRaise 5,"xmlRs.SplitSQL:SQL语句语法错误,"& Mid(oSql,1,30) &" 缺少 INTO"
			iTmp = InStr(iInto+6,sql,"(")
			If iTmp<1 Then ErrRaise 5,"xmlRs.SplitSQL:SQL语句语法错误,"& Mid(oSql,iInto,30) &" 缺少 “(“ "
			Rst.Add "table",Mid(oSql,iInto+6,iTmp-iInto-6)
			
			'取出字段列表
			iEnd = InStr(iTmp+2, sql, ")")
			If iEnd<1 Then
				ErrRaise 5,"xmlRs.SplitSQL:SQL语句语法错误,"& Mid(oSql,iInto+6,30) &" 缺少 “)”"
			End If
			strFld	= Mid(sql,iTmp+1,iEnd-iTmp-1)
			If InStr(strFld,"[")>0 Then strFld=Replace(Replace(strFld,"[",""),"]","")
			Rst.Add "field",Split(strFld,",")
			
			'取出值列表
			If iValue<1 Then
				ErrRaise 5,"xmlRs.SplitSQL:SQL语句语法错误,"& Mid(oSql,iEnd,30) &" 缺少 “VALUES”"
			End If
			iTmp = InStr(iValue, sql, "(")
			iEnd = InStr(iTmp, sql, ")")
			If iTmp<1 Or iEnd<1 Then
				ErrRaise 5,"xmlRs.SplitSQL:SQL语句语法错误,"& Mid(oSql,iValue,30) &" 缺少 “(” 或 “)”"
			End If
			strVal = Mid(oSql, iTmp+1, iEnd-iTmp-1)
			arrVal = Split(Mid(sql, iTmp+1, iEnd-iTmp-1),",")
			If UBound(arrVal)<>UBound(Rst("field")) Then
				ErrRaise 5,"xmlRs.SplitSQL:SQL语句语法错误,"& Mid(oSql,iTmp,30) &" 字段与值不对应"
			End If
			
			iTmp = 1
			For iVal=0 To UBound(arrVal)
				iEnd = Len(arrVal(iVal))
				arrVal(iVal)=Mid(strVal,iTmp,iEnd)
				iTmp = iTmp + iEnd + 1
				If InStr(arrVal(iVal),"'")=1 Then
					arrVal(iVal)=Mid(arrVal(iVal),2,Len(arrVal(iVal))-2)
					If InStr(arrVal(iVal),"''")>0 Then
						arrVal(iVal) = Replace(arrVal(iVal),"''","'")
					End If
				End If
			Next
			
			Rst.Add "value",arrVal
		Case "delete"
			If iFrom<1 Then ErrRaise 5,"xmlRs.SplitSQL:SQL语句语法错误,"& Mid(oSql,1,30) &" 缺少 FROM"
			iTmp = InStr(iFrom+6,sql," ")
			If iTmp<1 Then ErrRaise 5,"xmlRs.SplitSQL:SQL语句语法错误,"& Mid(oSql,iFrom,30) &" 附近有语法错误"
			Rst.Add "table",Mid(oSql,iFrom+6,iTmp-iFrom-6)
		Case Else
			ErrRaise 5,"xmlRs.SplitSQL:SQL语句语法错误,错误的操作类型:"& Rst("type")
		End Select
		
		If InStr(Rst("table"),"[")=1 Then
			Rst("table") = Mid(Rst("table"),2,Len(Rst("table"))-2)
		End If
		
		If iWhere>0 Then
			If iOrder>0 Then
				strFld = Mid(sql, iWhere + 7, iOrder - iWhere - 7)
				strVal = Mid(oSql, iWhere + 7, iOrder - iWhere - 7)
			Else
				strFld = Mid(sql, iWhere + 7)
				strVal = Mid(oSql, iWhere + 7)
			End If
			
			'兼容sql中的不等号
			If InStr(strFld,"<>")>0 Then strFld = Replace(strFld,"<>","!=")
			
			'主要是将字段名转换为小写
			strFld = LCase(strFld)
			iTmp = InStr(strFld,ph)
			If iTmp>0 Then
				Do Until iTmp<1
					iEnd = InStr(iTmp,strFld,"'")
					iVal = Mid(strVal,iTmp,iEnd-iTmp)
					strFld = Left(strFld,iTmp-1) & Replace(strFld,Mid(strFld,iTmp,iEnd-iTmp),iVal,iTmp,1,0)
					iTmp = InStr(iEnd,strFld,ph)
				Loop
			End If
			
			Rst.Add "where",strFld
		End If
		
		If iOrder>0 Then
			'排序的规则化将在排序功能内实现,这里只作取出
			Rst.Add "order",Mid(sql, iOrder + 9)
		End If

		Set SplitSQL = Rst
	End Function
	
	Private Sub ClearSQL(sql, osql)
		Dim Re, mth, m, l, v, i
		Set Re = New RegExp
		Re.Global = True
		
		'清除多余空格
		Re.Pattern = "\s+"
		Set mth = Re.Execute(sql)
		For Each m In mth
			v = m.Value
			i = m.FirstIndex
			l = m.Length
			If v<>" " Then
				sql = Left(sql,i-1) & Replace(sql,v,String(l,Chr(1)),i,1,0)
				osql = Left(osql,i-1) & Replace(oSql,v,String(l,Chr(1)),i,1,0)
			End If
		Next
		Re.Pattern = "[\x01]+"
		sql = Re.Replace(sql," ")
		osql = Re.Replace(osql," ")
		
		'清除逗号两边的空格
		Re.Pattern = "\s*,\s*"
		Set mth = Re.Execute(sql)
		For Each m In mth
			v = m.Value
			i = m.FirstIndex
			l = m.Length
			If v<>" " Then
				sql = Left(sql,i-1) & Replace(sql,v,String(l,Chr(1)),i,1,0)
				osql = Left(osql,i-1) & Replace(oSql,v,String(l,Chr(1)),i,1,0)
			End If
		Next
		Re.Pattern = "[\x01]+"
		sql = Re.Replace(sql,",")
		osql = Re.Replace(osql,",")
	End Sub
	
	'重新设定属性值
	Private Sub setProp
		If pCount>0 Then
			pEOF	= False
			pBOF	= False
			If pPosition<1 Then
				pPosition=1
			ElseIf pPosition>pCount Then
				pPosition=pCount
			End If
			Set currentNode=DOMList(pPosition-1)
		Else
			pEOF	= True
			pBOF	= True
			pPosition=0
			Set currentNode=Nothing
		End If
	End Sub
	
	'检查属性
	Private Sub ChkProp
		If pPosition<1 Then
			pBOF	= True
		ElseIf pPosition>pCount Then
			pEOF	= True
		Else
			pBOF	= False
			pEOF	= False
			Set currentNode=DOMList(pPosition-1)
		End If
	End Sub
	
	Private Sub setList
		Dim DL, i
		If xPath<>"" Then
			Set DL = DOM.documentElement.selectNodes(xPath)
		Else
			Set DL = DOM.documentElement.childNodes
		End If
		pCount = DL.length
		ReDim DOMList(pCount-1)
		For i=0 To DL.length-1
			Set DOMList(i) = DL(i)
		Next
	End Sub
	
	'交换,用于排序
	Private Sub Swap(a, b)
		Dim tmp
		Set tmp = DOMList(a)
		Set DOMList(a) = DOMList(b)
		Set DOMList(b) = tmp
	End Sub
	
	'比较,用于排序
	Private Function Compare(a, b)
		Compare = 0
		If IsNumeric(a) And IsNumeric(b) Then
			If CDbl(a)>CDbl(b) Then
				Compare = 1
			ElseIf CDbl(a)<CDbl(b) Then
				Compare = -1
			End If
		ElseIf IsBool(a) And IsBool(b) Then
			If a And Not b Then
				Compare = 1
			ElseIf b And Not a Then
				Compare = -1
			End If
		Else
			Compare = StrComp(a,b,1)
		End If
	End Function
	
	'判断是否布尔值,并进行转换
	Private Function IsBool(v)
		IsBool = False
		If StrComp(v,"true",1)=0 Then
			v = True
			IsBool = True
		ElseIf StrComp(v,"false",1)=0 Then
			v = False
			IsBool = True
		End If
	End Function
	
	Private Sub ErrRaise(code, Desc)
		Err.Raise code, Desc
		'Response.End()
	End Sub
	
End Class