VFP 愛用者社區 首頁 VFP 愛用者社區
本討論區為 Visual Foxpro 愛用者經驗交流的地方, 請多多利用"搜尋"的功能, 先查看看有無前例可循, 如果還有不懂的再發問. 部份主題有附加檔案, 須先註冊成為社區居民才可以下載.
 
 常見問題常見問題   搜尋搜尋   會員列表會員列表   會員群組會員群組   會員註冊會員註冊 
 個人資料個人資料   登入檢查您的私人訊息登入檢查您的私人訊息   登入登入

XML 在 COM 組件數據集傳遞中的意義(轉貼)

 
發表新主題   回覆主題    VFP 愛用者社區 首頁 -> VFP 討論區
上一篇主題 :: 下一篇主題  
發表人 內容
Ruey



註冊時間: 2003-03-12
文章: 1698
來自: tunglo

第 1 樓

發表發表於: 星期六 三月 27, 2004 3:31 am    文章主題: XML 在 COM 組件數據集傳遞中的意義(轉貼) 引言回覆

XML 在 COM 組件數據集傳遞中的意義
文章標題: Visual FoxPro 7 全新登場--XML 在 COM 組件數據集傳遞中的意義

作品來源: BOE 數據網絡工作室

最後更新: 2001年11月18日

文字數量: 約字

作者姓名: 陳純

譯者姓名: --  

版權聲明: 版權屬於原作者  

相關下載:  

細節描述:
   

說在前面 

  記得我第一次接觸 COM 組件編程時,就有這樣的疑問:傳遞數據集有沒有好辦法。我們知道,Visual FoxPro 是最強大的數據處理系統,它的Cursor 的強大、靈活的支持是無有匹敵的。既然Visual FoxPro 對數據集的處理能力這麼強大,但是COM編程時,怎樣簡單的在各類客戶端程序與 Visual FoxPro 編寫的 COM 組件之間傳遞 Cursor ——只有來去容易,用的才方便舒心! 

  那個時候我們模仿ADO組件,使用 「屬性+循環」 的方法解決這個難題,記得 fbilo 翻譯的一篇文章中有過介紹: 

 

  總的來說,覺得那個時候 「活的」 很累,並且這個方案沒有解決客戶端往COM組件中傳遞Cursor 的問題! 

  在我撰寫的《Visual FoxPro 漫談》一文中,我承設想用XML來解決這個問題,並且在Visual FoxPro 6的時代也做過一些嘗試。我編寫過一個叫做:CursorToXML的小程序,解決了Cursor 到XML的轉變,但對於 XML 到 Cursor 的轉變我就很無奈,我們知道微軟等一些大公司專門開發瞭解析XML的組件,按理說只要是用這些東西就能夠完成XML 到Cursor的轉變,但實際操作起來很是麻煩。不信,你可以試試!這個時期,即使我成功的封裝了XML的解析器,意義也不大,因為:所有的開發工具對XML的支持都不好,我的COM組件支持又有何用,所謂孤掌難鳴! 

忽如一夜春風來 

  2000年初聽說了XML,2001年初買到了有關XML的參考書,開始瞭解了這個被稱為「可擴展的標記名語言」。本文不是專題的XML討論、本人亦不是此方面的專家,所以我不會在XML方面浪費筆墨。我對XML的理解就是用一定的規範格式,用文本的形式將數據表現出來。基於文本、基於規範的格式,於是XML天生的就具備了廣泛的適應性,這也就是我們說用 XML在各類客戶端與Visual FoxPro 開發的COM之間傳遞數據集的原因! 

微軟推出的Visual FoxPro 7 全面支持XML,具體體現在三個函數中: 

CursorToXML(nWorkArea | cTableAlias, cOutput [, nOutputFormat [, nFlags [, nRecords [, cSchemaName [, cSchemaLocation [, cNameSpace ]]]]]]) 

XMLTOCURSOR(XMLSource eExpression | cXMLFile [, cCursorName [, nFlags ]]) 

XMLUPDATEGRAM( [cAliasList [, nFlags]]) 

  真有 「忽如一夜春風來」的感覺,一是感慨:業界技術發展之快;二是感慨:我們的 Visual FoxPro 也迎頭趕上,適時推出了這項時髦而有意義的功能! 

  總的來說,Visual FoxPro 7對XML的支持是通過對 MSXML Parser 的封裝來實現的。記得嗎——在安裝Visual FoxPro 7之前,微軟會提示先安裝——「MSXML Parser 3.0 」! 

CursorToXML ()與XMLTOCURSOR() 

CursorToXML () 將Cursor 轉換成XML文件或字符串 

CursorToXML(nWorkArea | cTableAlias, cOutput [, nOutputFormat [, nFlags [, nRecords [, cSchemaName [, cSchemaLocation [, cNameSpace ]]]]]]) 

nWorkArea | cTableAlias--指定被轉換光標 

cOutput--指定輸出文件名稱或變量名 

nOutputFormat--指定XML文檔中數據的格式 

這裡有三種選擇: 

A.nOutputFormat=1:ELEMENTS 

- <employees>
<employeeid>1</employeeid>
<lastname>Davolio</lastname>
<firstname>Nancy</firstname>
<title>Sales Representative</title>
<titleofcourtesy>Ms.</titleofcourtesy>
1948-12-08T00:00:00
<hiredate>1992-05-01T00:00:00</hiredate>
<address>507 - 20th Ave. E. Apt. 2A</address>
<city>Seattle</city>
<region>WA</region>
<postalcode>98122</postalcode>
<country>USA</country>
<homephone>(206) 555-9857</homephone>
<extension>5467</extension>
<notes />
<reportsto>2</reportsto>
<photopath>http://accweb/emmployees/davolio.bmp</photopath>
</employees>
B.nOutputFormat=2:ATTRIBUTES 

<employees employeeid="1" lastname="Davolio" firstname="Nancy" title="Sales Representative" titleofcourtesy="Ms." birthdate="1948-12-08T00:00:00" hiredate="1992-05-01T00:00:00" address="507 - 20th Ave. E. Apt. 2A" city="Seattle" region="WA" postalcode="98122" country="USA" homephone="(206) 555-9857" extension="5467" notes="" reportsto="2" photopath="http://accweb/emmployees/davolio.bmp" />
C.nOutputFormat=3:ROW 

<row employeeid="1" lastname="Davolio" firstname="Nancy" title="Sales Representative" titleofcourtesy="Ms." birthdate="1948-12-08T00:00:00" hiredate="1992-05-01T00:00:00" address="507 - 20th Ave. E. Apt. 2A" city="Seattle" region="WA" postalcode="98122" country="USA" homephone="(206) 555-9857" extension="5467" notes="" reportsto="2" photopath="http://accweb/emmployees/davolio.bmp" />
nFlags--指定標記 

這個參數最為複雜,這裡要提請大家注意的是:如果想將XML輸出到文件中,請讓 nFlags=512+n(n為其他標記);如果想將XML輸出到內存變量,nFlags就不用為512; 

nRecords--輸出的記錄範圍 

一般我們會輸出Cursor 中所有的記錄,所以這個參數多用0代入! 

舉例: 

輸出實例數據庫的Employee的數據到C:Temp1.xml中: 

CURSORTOXML("employees","c:\temp1.xml",1,512+16,0,"1") 

輸出實例數據庫的Employee的數據到內存變量ABC中: 

CURSORTOXML("employees","ABC",3,512+16,0,"1") 

XMLToCursor () 將XML 文件或字符串轉換成Cursor 

XMLTOCURSOR(XMLSource eExpression | cXMLFile [, cCursorName [, nFlags ]]) 

XMLSource eExpression | cXMLFile--指定XML的來源,可以是文件也可以是內存變量 

cCursorName --新的Cursor的名稱 

舉例: 

將c:\temp1.xml 轉變成為cursor:T1 

XMLToCursor("c:\temp1.xml","T1") 

將內存變量轉變成為cursor:T2 

XMLToCursor("c:\temp2.xml","T2") 

XMLUPDATEGRAM() 函數與本文所介紹的內容無關,在此暫不作介紹。 

一個使用XML傳遞的實例 

編寫COM組件 

代碼: 

#define CL chr(13)+chr(10) 

DEFINE CLASS PowerVFP as Session olepublic
datasession=2 

PROCEDURE CreateCurosr(cXml as string,cCursorName as string)
XMLTOCURSOR(cXml,cCursorName) 

ENDPROC 

PROCEDURE ExecFoxCode(cCode as string)
EXECSCRIPT(cCode)
ENDPROC 

FUNCTION GetCursor(cCursorName as String) as String
LOCAL cXml as String
CURSORTOXML(cCursorName,"cXml",3,48,0,"")
RETURN cXml
ENDFUNC 

PROCEDURE Error(nError as Integer,cMethod as String, nLine as Integer)
LOCAL cText as String
cText=;
'出錯時間:'+transform(datetime())+CL+;
'錯誤代碼:'+str(nError,4)+CL+;
'錯誤提示:'+message()+CL+;
'錯誤方法:'+cMethod+CL+;
'錯誤行號:'+transform(nLine)+CL+CL
strtofile(cText,'c:\PowerFox.txt',.t.)
comreturnerror("PowerFox COM Service",cText)
ENDPROC 

ENDDEFINE 

我的思路 

寫這個組件是「有感而發」的,前一陣子用Delphi寫ERP系統,雖然很努力的將大量的工作交給後台的 SQL Server,多數情況下,Delphi端得到的是很簡單的數據集。然而,在一些涉及到複雜應用時,很多從經SQL Server處理的數據只是半成品,必須到客戶端加工,這種加工往往是異常複雜的,分組、排序、關聯、統計……在Delphi中實現這些功能是非常繁瑣的,除了使用一些第三方控件能解決一些問題之外,無一例外的是大量的「循環+條件」,真的是很麻煩,工作量很大。 

基於上述思考,加上經SQL Server處理過的數據量已不大,我嘗試著編寫一個COM來解決這個問題。除了Error方法之外,整個組件只有三個方法: CreateCurosr(cXml as string,cCursorName as string) 是將外部傳入的XML字串轉換成Visual FoxPro 的Cursor;GetCursor(cCursorName as String) as String是將Visual FoxPro 的Cursor 轉換成為XML字符串,向外傳遞;關鍵的是ExecFoxCode(cCode as string),它可一次執行多句符合Visual FoxPro 語法的語句,這樣就可以在外部任意享用Visuial FoxPro提供的絕大多數功能! 

應用實例 

編譯這個項目以後,我們做兩個簡單的實驗,感受一下這超級的功能! 

例一: 

LOCAL ox as "PowerFox.PowerVFP"
LOCAL cStr,cFoxCode as String
*建立COM對像實例
ox=CREATEOBJECT("PowerFox.PowerVFP")
*在客戶端得到XML的結果集
USE northwind!Customers IN 0 SHARED
CURSORTOXML("Customers","cStr",3,48,0,"")
USE IN Customers
*將XML語句傳遞到COM中,並建立Cursor
ox.CreateCurosr(cStr,"C1")
*產生符合 Visual FoxPro 語法的語句
cFoxCode="SELECT CustomerID,CompanyName FROM C1 WHERE Country like '%s%' INTO CURSOR T1"
cFoxCode=cFoxCode+CHR(10)+"SELECT CustomerID,CompanyName,ContactName,ContactTitle FROM C1 INTO CURSOR T2"
*傳遞語句到 COM 中執行
ox.ExecFoxCode(cFoxCode)
*讓 COM 組件將結果集以XML的形式傳回客戶端
XMLTOCURSOR(ox.GetCursor("T1"),"Result1")
XMLTOCURSOR(ox.GetCursor("T2"),"Result2") 

例二: 

LOCAL ox as "PowerFox.PowerVFP"
LOCAL cStr1,cStr2,cStr3,cFoxCode as String
*建立COM對像實例
ox=CREATEOBJECT("PowerFox.PowerVFP")
*在客戶端得到XML的結果集
USE northwind!Employees IN 0 SHARED
USE northwind!Orders IN 0 SHARED
USE northwind!Order_Details IN 0 SHARED
CURSORTOXML("Employees","cStr1",3,48,0,"")
CURSORTOXML("Orders","cStr2",3,48,0,"")
CURSORTOXML("Order_Details","cStr3",3,48,0,"")
USE IN Employees
USE IN Orders
USE IN Order_Details
*將XML語句傳遞到COM中,並建立Cursor
ox.CreateCurosr(cStr1,"Employees")
ox.CreateCurosr(cStr2,"Orders")
ox.CreateCurosr(cStr3,"Order_Details")
*產生符合 Visual FoxPro 語法的語句
cFoxCode="SELECT a.employeeid,ALLTRIM(LastName)+' '+ALLTRIM(FirstName) as Name,Title,sum(unitprice*Quantity)*(1-discount) as nJe "
cFoxCode=cFoxCode+"from orders a INNER JOIN order_details b ON a.orderid=b.orderid INNER JOIN employees c ON a.employeeid=c.employeeid GROUP BY a.employeeid into cursor T1 noFilter"
cFoxCode=cFoxCode+CHR(10)+"SELECT employeeid,Name,Title,MAX(nJe) as nJe FROM T1 INTO CURSOR T2"
*傳遞語句到 COM 中執行
ox.ExecFoxCode(cFoxCode)
*讓 COM 組件將結果集以XML的形式傳回客戶端
XMLTOCURSOR(ox.GetCursor("T1"),"Result1")
XMLTOCURSOR(ox.GetCursor("T2"),"Result2") 

後記 

好了,關於 「XML 在 COM 組件數據集傳遞中的意義」 已經大致討論完畢了。不知您有何感受,我是懷著興奮、驕傲的情緒做這個實驗的、寫這篇文章的。可能你對整個實驗不以為然——神經病一樣的將數據集導來導去,自找麻煩!但你設想一下:如果兩個Test程序不用Visual FoxPro來實現,情況會怎樣?那是一種多麼美好的事情啊!將Visual FoxPro 作為一個 Server 運行,這是微軟近年來努力的方向,在Visual FoxPro 7里,融入了大量的將關增強技術,這裡介紹的就是一個很關鍵的東西。

_________________
#############################
快樂媽咪系列幸福宅配,喝十全雞湯~原來幸福那麼簡單!!

學會VFP使用者社區的搜尋,Code才會更有趣~
#############################
回頂端
檢視會員個人資料 發送私人訊息
syntech



註冊時間: 2003-05-16
文章: 4249
來自: Taipei,Taiwan

第 2 樓

發表發表於: 星期一 三月 29, 2004 3:04 pm    文章主題: 引言回覆

這是配合這篇
大家使用SPT的時候...都是用什麼資料庫呢
http://vfp.sunyear.com.tw/viewtopic.php?t=1158
的嗎?

不過,若查詢時真的使用cursorTOxml交換資料,
會遇到 xml size 過大,
internet 環境下頻寬不足要傳很久的窘境.
變成要
0.cursorToxml
1.把xml 壓成 zip 檔
2.傳遞zip檔
3.zip檔解成 xml
4.xmltocursor

同作者在說明 web service 時,有提到這樣的做法.

_________________
如果公司有下列困擾:
1. 找不到便宜,快速,簡易的 生產排程軟體
2. 不知道如何快速排定 採購計劃
3. 成本抓不準,自己算比軟體算有用
4. 想學習系統規劃,想找系統架構的顧問

請聯絡我們,也許我們幫得上忙
回頂端
檢視會員個人資料 發送私人訊息 發送電子郵件 AIM Address
從之前的文章開始顯示:   
發表新主題   回覆主題    VFP 愛用者社區 首頁 -> VFP 討論區 所有的時間均為 台北時間 (GMT + 8 小時)
1頁(共1頁)

 
前往:  
無法 在這個版面發表文章
無法 在這個版面回覆文章
無法 在這個版面編輯文章
無法 在這個版面刪除文章
無法 在這個版面進行投票
無法 在這個版面附加檔案
無法 在這個版面下載檔案


Powered by phpBB © 2001, 2005 phpBB Group
正體中文語系由 phpbb-tw 維護製作