Visual Foxpro 7全新登场之XML在COM组件数据传递中的意义

说在前面

记得我第一次接触 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>

<birthdate>1948-12-08T00:00:00</birthdate>

<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>bmp/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="bmp/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="bmp/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里,融入了大量的将关增强技术,这里介绍的就是一个很关键的东西。

时间: 2024-10-04 01:05:56

Visual Foxpro 7全新登场之XML在COM组件数据传递中的意义的相关文章

visual foxpro 7全新登场-数据安全

说在前面 一直想写一些关于Visual FoxPro 7 的东西,但下不了笔.原因有二:一是工作繁忙,懒得动笔,再就是Visual FoxPro 7的新特性并不浮于表面,一时很难体会,更谈不上写成文章了. 困难重重,还是要写.我不是专业的Visual FoxPro 的程序员,我是一个爱好者,所以我没有专业程序员的种种顾虑:版本问题.兼容性问题.可靠性问题:Visual FoxPro 7作为Visual FoxPro 3以来最重要.变化最深刻的版本,是值得我们深入研究的.从这次起我将分专题与大家讨

Visual Foxpro漫谈(五)-Visual FoxPro 7 的特性

前面已经提到多次,Visual FoxPro 7 已经在2001年5月中旬正式发布的,6月份在美国上市.现在不少网友已经得到了Visual FoxPro 7的英语正式版,使用之后,产生了种种评判.在美国人们认为,Visual FoxPro 7是继 Visual FoxPro 3以后 Fox 发展史上最具有"革命意义"的版本,评价是很高的:而在国内,不少尝鲜者感叹:这是微软不好意思说SP的产品,简直就是Visual FoxPro 6+SP6--两种评价相差这么大,谁是谁非呢? 笔者在20

Visual FoxPro 7与Web Service

说在前面 本文的实验必须在连接Internet的前提下进行! 本文关于Web Service的定义部分参阅了台湾基峰资讯股份有限公司的<C# & ASP.NET>一书. Visual FoxPro 7全面支持Web Service Visual FoxPro 7对Web Service有特别的支持,这是Visual FoxPro 7的一大卖点,也是Visual FoxPro 作为微软.Net构架下的一种高效开发工具的显著标志(注意:Visual FoxPro不是.Net 语言,但它是.

Visual Foxpro漫谈(二)

Visual FoxPro 已经过时了吗 恕我直言,这样的问题我真的听腻了.这个问题我听了好几年了.从谣言出现到今天Visual FoxPro的版本已经生了两次变化,就是Visual FoxPro 6.0 与2001年春天推出的Visual FoxPro 7.0.根据微软的官方消息,Visual FoxPro 8(可能是这个名称吧)已经在研发之中了.我不敢保证是否会有Visual FoxPro 9.0(这就像我不敢保证微软是否在那时还存在一样).可以这样认为,只要不出意外情况(比如微软倒闭.业界

visual foxpro 7.0漫谈

今年是开发工具集中更新版本的一年:微软的Visual Studio.Net,Borland 的Delphi 6.Sybase的Power Builder 8都相继推出正式版或是测试版,我们的Visual FoxPro 当然也不会放过这业界大比武的好时机,今年5月微软发布了Visual FoxPro 7,它是继1995年Fox家族第一个可视化成员Visual FoxPro 3以来最具革命意义的版本. "革命意义"这个词可不是我信口开河.随便使用的,这是国外的Fox社区对Visual Fo

在.NET里使用Visual FoxPro资源-vfp编写的COM组件

第二部分:在.NET里使用vfp编写的COM组件 Fox能够灵活.直观.快速处理数据,使得它非常适合应用在业务逻辑层次.从Visual FoxPro 5开始,微软不断加强Visual FoxPro 的COM组件开发上能力.简单归纳一下Visual FoxPro 在COM组件编写的特点: 全新的运行时刻库:VFPnT.DLL(n代表版本号).在这个运行库中,删除了大量老式的和界面控制元素,更小巧.更稳定.更快速. 全新的SESSION对象.在多线程状态下提供很好的隔离性. 内置对XML的支持,方便

在.NET里使用Visual FoxPro资源-前言

这篇文章是我为<程序员>杂志写的,发表在该杂志 2002 年第 9 期,应该是<程序员>杂志有史以来首篇有关于 Visual FoxPro 的文章,这里真的要感谢编辑先生-- 写这篇东西十分吃力,因为涉足的领域太新了,几乎没有资料可以借鉴,即便是原版的.还好,从去年开始我就断断续续的看了一点有关C#..Net的东西,近来也对有关"Visual FoxPro 与 .NET"有一些思考,虽然吃力,总算不辱使命. Visual FoxPro 对于 .NET 的支持应该

Visual Foxpro漫谈(四)

Visual FoxPro 从Visual Studio中分离出来了 2001年2月26日,微软宣布将Visual FoxPro 7从Visual Studio 中分离出来,这是一个好消息还是坏消息呢?我们来分析一下: 我们失去了什么 我们先来观察,Visual FoxPro不成为.Net语言,在技术上损失的是:不能开发基于.Net的Web应用程序. Visual Studio.Net 是一种擅长于开发Web应用程序的工具,过去与现在微软霸占着"桌面应用程序"应用市场,现在微软要吞噬现

Visual Foxpro漫谈(一)

前言 这篇文章可以说是 BOE 数据网络工作室的开山之作了.它的动工是从2000年国庆节开始的,写写停停,直到那年的农历春节才完成初稿-- 后来我有几次修改,算在2002年4月的这个版本,应该是第四版了! 当初,我写这篇文章的动机是:平静的表达我的观点.作为一名 Visual FoxPro 的程序员经常受到别人的质疑.甚至是批驳.挖苦,我不是一个擅长口舌争斗的人,更不敢冒犯"众怒".于是我就用键盘陆续敲击一些文字,表达我对 Visual FoxPro 的认识,同时表达对各类问题的看法-