XMLAdapter类,提供了一种面向对象的方法来处理XML数据,并利用您对表和字段的熟悉程序来处理XML。
XML在Intranet/Internet上交换结构化数据,与平台无关,与语言无关。XML使VFP与其他语言程序集成相当容易,即使它们使用的平台和系统与您的完全不同。集成业务应用程序已成为一种基本需求。XML是这种集成的关键。
XMLAdapter类为使用XML提供了新的支持。这个新类的一个功能是支持分层XML。这意味着,一个XML文件表示一组不同且可能相关的表,如Windows.NET数据集,将呈现到单独的Visual FoxPro游标中。
通过能够控制创建的XML的模式,以及控制游标从模式的XML创建的数据类型,增强了对数据的灵活性和控制。这允许您加载XML,更改模式,然后生成游标。此外,您可以在内存中使用游标,控制模式,然后以不同的格式生成XML。
XMLAdapter类允许您从XML源加载XML,解析XML模式(如果存在),并将一个或多个XMLTable对象添加到其tables集合中。反过来,一个或多个XMLField对象被添加到每个XMLTable的fields集合中。
集成业务应用程序已成为一种基本需求。XML是这种集成的关键。
XMLAdapter类还可以创建一个XML文档,表示已填充的包含的表和字段。XMLAdapter类包括另外两个子成员类:XMLTable和XMLField。它们提供了以编程方式遍历模式并访问或设置信息的能力。
XMLAdapter类提供的主要功能是通过LoadXML()方法检索XML,然后根据需要通过包含的XML模式将XML解析为一个或多个XMLTable对象,这些对象又包含XMLField对象。
XMLTable类是XML中包含的所有表和函数的集合,允许您单步遍历表以对其执行过程。
XMLTable对象的集合将XML描述为一个或多个VisualFoxPro游标以及任何关系信息。XMLAdapter不存储实际的XML模式或内容,但存储对它们的对象引用。
然后,开发人员可以使用XMLTable.ToCursor()方法生成一个游标,其中包含子成员XMLField集合表示的所有字段的数据。
通过XMLAdapter.LoadXML()方法检索的XML和XML架构数据将保留在内存中,直到通过后续调用LoadXML()替换,或者通过调用ReleaseXML()方法专门释放。
XMLField类是为每个XMLTable创建的集合,包含表中的所有字段。开发人员可以遍历字段对象并进行任何必要的更改。没有与XMLField类关联的方法。
使用XMLAdapter将XML转换为VFP游标
现在让我们使用XMLAdapter类,看看获取XML文件并将其转换为VisualFoxPro光标是多么容易。我们将使用一个表示客户数据的XML文件,该文件包含一个表和四条记录,每个表包含两个字段。
使用XMLAdapter类读取XML并创建游标的代码如下:
cFile = "c:\XMLAdapter\CustomerXML.xml"
adapter = CREATEOBJECT("XMLAdapter")
adapter.LoadXML(cFile,.T.)
adapter.Tables(1).ToCursor()
首先,引用XML文件。接下来,创建XMLAdapter类的一个实例。然后调用LoadXML方法,将XML从文件加载到文档对象模型(DOM)文档中,并将其附加到XMLAdapter对象。第一个参数是XML文件的名称或包含XML的字符串。第二个参数确定第一个参数是否表示文件。
最后,访问XMLTable对象的集合。因为XMLAdapter对象中只包含一个表,所以我们可以直接访问XMLTable。最后,调用ToCursor方法将XML转换为visualfoxpro游标。有关创建的游标的示例,请参见图1。
图一:从XML创建游标
转换游标到XML
现在,我们已经看到了从XML创建Visual FoxPro游标是多么容易,让我们看看XMLAdapter类使执行相反操作变得多么容易:从游标创建XML文件。以下示例将从northwind数据库中的Employees表中选择一组记录,该数据库现在随Visual FoxPro 8.0一起提供,并从光标创建XML文件:
cFile = "c:\XMLAdapter\EmployeeXML.xml"
OPEN DATABASE (_samples+"\northwind\northwind")
SELECT employeeid, lastname ;
FROM Employees;
INTO CURSOR curEmployees
adapter = CREATEOBJECT("XMLAdapter")
adapter.AddTableSchema("curEmployees")
adapter.ToXML(cFile,,.T.)
在上面,定义了XML文件的名称并打开了数据库。创建游标是为了从Employees表中提取记录,并创建XMLAdapter类的实例。要将游标添加到XMLAdapter对象,将调用AddTableSchema方法,并传入游标的名称。最后,调用ToXML方法来创建XML文件。
第一个参数是XML文件所需的文件名。第二个参数允许您选择指定外部架构文件。在本例中,模式将在XML文件内部生成,称为“内联模式”;因此,跳过此参数。第三个参数作为“true”传递,以指定第一个参数是用于在外部文件中生成XML的文件名,而不是字符串。
XML模式是W3C(万维网联盟)基于标准的格式,用于定义XML数据的结构。模式是一个XML文档,它定义构成XML文档或其他XML文档中包含的数据的元素的结构、约束、数据类型和关系。
模式是用专门的语法编写的,只需指定特定文档中允许的元素和属性。您不仅可以使用模式定义文档的有效元素和属性,还可以指定数据类型。模式可以包含在XML文件中,称为内联模式。或者,它们可以是使用XSD或XDR扩展名的外部文件。
XMLAdapter类支持分层XML格式,这提高了VisualFoxpro与从Windows.NET数据集生成并写入到Windows.NET数据集的XML进行互操作的能力。
尽管在大多数情况下,您不需要直接使用模式,但重要的是要了解它们提供了有关数据类型的信息。正如您将在本文中进一步看到的,在VisualFoxPro中使用XML时,有时需要更改数据类型。有关架构的更多信息,请访问http://www.w3.org/XML/Schema.
XMLAdapter类至少需要MSXML4.0SP1。MSXML 4.0 SP1与Visual FoxPro 8.0一起安装。
XMLSchema对象模型(SOM)是一个丰富的API,允许您以编程方式创建、编辑和验证模式。SOM对模式文档的操作方式类似于文档对象模型(DOM)对XML文档的操作方式。使用XMLAdapter类的对象模型消除了直接使用SOM的需要,从而在使用模式时提供了粒度控制。
在调用XMLAdapter.ToCursor()方法生成Visual FoxPro游标之前,可以在XMLFields集合中更改数据类型。需要这种控制的一个实例是,XML文件包含一个元素,该元素将zipcode存储为数字,而您生成的游标需要数据作为字符类型。使用以下示例代码修改数据类型:
adapter = CREATEOBJECT("XMLAdapter")
cFile = "c:\XMLAdapter\EmployeeXML.xml"
adapter.LoadXML(cFile,.T.)
adapter.Tables(1).Fields(1).DataType = "C"
adapter.Tables(1).Fields(1).MaxLength = 10
adapter.Tables(1).ToCursor()
XMLAdapter类允许您创建自己的模式以手动自定义XML文件。此外,您可以使用XMLAdapter对象来读取模式,以便理解所包含数据的文件结构。
使用sqlXML的XMLAdapter类
XMLAdapter类支持使用sqlXMLSDK输出为XML的sqlServer2000查询(请参阅侧栏“sqlXMLSDK”)。以下是为结果集生成XML的T-SQL查询示例:
SELECT Customers.CustomerID,Customers.CompanyName,
Orders.OrderID,Orders.OrderDate,
Orders.ShipName,Order_details.ProductID,
Order_details.UnitPrice,Order_details.Quantity
FROM Customers
Inner Join Orders
On Customers.CustomerID = Orders.CustomerID
Inner Join [Order Details] Order_details
On Orders.OrderID = Order_details.OrderID
WHERE Customers.CustomerID = 'CACTU' AND
Orders.OrderID = 10521
FOR XML AUTO, ELEMENTS, XMLDATA
生成的XML从三个不同的表中提取数据,XML数据维护这些表之间的关系。这允许XMLAdapter对象通过填充XMLTable.ParentTable和XMLTable.ChildTable属性来维护父子关系。以下Visual FoxPro代码使用图4中的XML文件显示不同XMLTable对象之间的关系:
adapter = CREATEOBJECT("XMLAdapter")
cFile = "c:\XMLAdapter\sqlXML.xml"
adapter.LoadXML(cFile,.T.)
oTable1 = adapter.Tables(1)
oTable2 = oTable1.ChildTable
oTable3 = oTable2.ChildTable
oTable4 = oTable3.ChildTable
? oTable1.Alias && Customers
? oTable2.Alias && Orders
? oTable3.Alias && Order_details
? oTable4 && .NULL.
oParent1 = oTable1.ParentTable
oParent2 = oTable2.ParentTable
oParent3 = oTable3.ParentTable
? oParent1 && .NULL.
? oParent2.Alias && Customers
? oParent3.Alias && Orders
调用ToCursor()方法时,只会生成一个游标(称为Customers),表示所有三个表的联接。需要记住的一点是:上面创建的XML不会生成为字符串字段设置maxlength的模式。因此,Visual FoxPro将数据类型转换为备忘录,因为这是无限字符串长度的默认数据类型。为了解决这个问题,您需要在调用ToCursor()方法之前修改模式。代码如下:
oTable1.Fields(1).DataType = "C"
oTable1.Fields(1).MaxLength = 6
oTable1.Fields(2).DataType = "C"
oTable1.Fields(2).MaxLength = 40
oTable2.Fields(3).DataType = "C"
oTable2.Fields(3).MaxLength = 40
adapter.Tables(1).ToCursor()
sqlXML的一个用途是使用HTTP发布功能为基于Intranet和Internet的应用程序发布sql Server数据。通过HTTP发布数据的能力允许您构建高度以数据为中心的网站。此外,XMLAdapter类只需发出HTTP请求即可将数据检索为XML。请求可以是select语句或对XML模板的调用(请参阅侧栏“XML模板”)。
使用Windows.NET Framework
在Microsoft.NET Framework类中,用于操作数据的主要类是Windows.NET数据集(DataSet)。DataSet是一个将数据封装为XML的类。XML可以通过几种方式从数据集中返回:
将整个Windows.NET数据集返回给调用应用程序,该应用程序以DiffGram格式返回所有行,其中包含内联模式,并指示更新、插入和删除。
仅返回Windows.NET数据集(DataSet)更改,该更改仅返回已使用内联架构以Diffgram格式修改、添加或删除的行。
Windows.NET DataSet类支持将XML返回到.NET字符串类型的DataSet.GetXml和GetXmlSchema方法。
使用Windows.NET数据集(DataSet)时,必须在填充数据集(DataSet)之前设置DataAdapter类的属性MissingSchemaAction
Windows.NET DataSet类支持DataSet.WriteXml和WriteXmlSchema方法,这两种方法将数据集(DataSet)作为XML写入内联模式、无模式或单独使用模式。
大量的注意力集中在使XMLAdapter类与Windows.NET数据集(DataSet)兼容上。XMLAdapter类支持分层XML格式,这提高了VisualFoxpro与从Windows.NET数据集生成并写入到Windows.NET数据集(DataSet)的XML进行互操作的能力。将为数据集(DataSet)中包含的每个数据表创建单独的Visual FoxPro游标。
清单1(在本文末尾)显示了示例Visual Basic.NET代码,该代码将三个sql Server表中的数据检索到一个Windows.NET数据集(Dataset)中,然后将数据集(DataSet)作为XML导出到XML文件,并将模式导出到单独的XSD文件。在使用Windows.NET数据集(DataSet)时值得一提的一点是:在填充数据集(DataSet)之前,必须设置DataAdapter类的属性MissingSchemaAction;例如:
da_customers.MissingSchemaAction = _
MissingSchemaAction.AddWithKey
这是架构中包含所有长度信息所必需的。否则,在Visual FoxPro中,所有.NET Framework字符串字段都将修改为备注字段。这是因为备注字段是Visual FoxPro中长度不限字符串的默认类型。
(译者注:加了这个命令之后,VFP还原的每个表字段都是正确的,比如数值型,字符型等等。)
XMLAdapter类可以通过读入数据并生成三个不同的游标来使用此XML。代码如下:
adapter = CREATEOBJECT("XMLAdapter")
cFile = "c:\XMLAdapter\DotNET.xml"
cXSDFile = "c:\XMLAdapter\DotNET.xsd"
adapter.XMLSchemaLocation = cXSDFile
adapter.LoadXML(cFile,.T.)
FOR EACH oXMLTable IN adapter.Tables
oXMLTable.ToCursor()
ENDFOR
将创建三个不同的游标,如图2所示。此示例的架构信息是使用Visual Basic.NET作为外部文件创建的。当您有一个外部文件时,需要在读取XML之前将XMLAdapter对象的XMLSchemaLocation属性设置为XSD文件。
图2:从Windows.NET数据集创建的VisualFoxPro游标。
使用Windows.NET数据集时,XMLAdapter类的一个限制是,数据集中设置的关系不会导入XMLAdapter类。您需要手动设置生成的游标之间的任何关系。从要导入到Windows.NET数据集的XMLAdapter导出XML时也是如此。光标之间的关系将丢失。
使用Diffgrams(只保存有变动的数据)
XMLAdapter类支持Diffgrams,它提供了在应用程序之间来回传输数据的有效方法。Diffgram是一种特殊类型的XML文档,其格式仅包含更改数据的信息,而不是整个数据集。使用这种格式可以减少需要在应用程序之间发送的XML的大小。
开发人员将XML加载到Visual FoxPro中,将其转换为光标,对数据进行必要的更新,并将数据转换回XML文档Diffgram。只有更改后的数据才会返回给XML的接收者。此XML文档Diffgram不仅可以应用于Visual FoxPro中的另一个XMLAdapter类,还可以用于支持Diffgram格式数据的其他应用程序。这些XML格式与ADO.NET兼容,可在Windows.NET Framework应用程序中使用。
当数据集返回到Visual FoxPro时,Windows.NET数据集始终以Diffgram格式序列化为XML。下面的Visual Basic.NET代码示例返回Windows.NET数据集(DATASET):
Return MyDataSet
如果数据集包含更改,则将通过Diffgram:hasChanges=“modified”或Diffgram:hasChanges=“inserted”属性标记这些更改。对于“修改的”记录,以前的值将在diffgr:before部分中。删除的记录仅出现在diffgr:before部分中,而不出现在Diffgram的主部分中。可以返回整个Windows.NET数据集(原始查询中的所有行)或仅包含更改的数据集。
在返回所有行的情况下,未更改的行将没有diffgr:hasChanges属性。要将数据集加载到XMLAdapter对象中,需要使用Attach()方法而不是LoadXML()方法,因为数据集返回XML DOM对象。下面是Visual FoxPro代码示例:
adapter = CREATEOBJECT("XMLAdapter")
* Call a .NET Web Service to return a DataSet
DataSetadapter.Attach(MyWebService.FetchData())
您可以使用XMLAdapter类创建Diffgram格式的XML。下一个示例创建一个读写游标,其中包含来自新northwind数据库(随Visual FoxPro 8.0提供)的客户信息,并将更改后的记录导出到Diffgram XML文件:
cFile = "c:\XMLAdapter\DiffgramXML.xml"
OPEN DATABASE (_samples+"\northwind\northwind")
SELECT CustomerID, CompanyName ;
FROM Customers;
INTO CURSOR curCustomers READWRITE
CURSORSETPROP("Buffering", 5)
LOCATE FOR CustomerID = "AROUT"
REPLACE CompanyName WITH "Around the Corner"
adapter = CREATEOBJECT("XMLAdapter")
adapter.AddTableSchema("curCustomers")
adapter.IsDiffgram = .T.
adapter.ToXML(cFile,,.T.,.T.,.T.)
打开表缓冲以允许XMLAdapter对象检测更改记录的前后值。然后更改一条记录,用不同的字符串替换CompanyName字段。XMLAdapter对象被实例化,游标被添加到XMLTable集合中。属性IsDiffgram设置为“true”,以允许为DiffGram格式化导出的XML。
最后,调用ToXML()方法将XMLTable导出到XML文件。本例中使用了两个新参数:第四个参数指定是否在Diffgram中包含diffgr:before部分;第五个参数指定XML是否只包含更改。
使用XML Web服务(XML WebService)
XMLWeb服务是托管在Web服务器上的应用程序或可执行代码块,其方法通过HTTP上执行的标准XML协议公开。这些方法可以来自任何平台,任何一方的任何语言。XMLWeb服务是通过Intranet/Internet在应用程序之间进行通信的行业标准;XML是作为这些服务主干的元语言。
例如,您可以使用XMLAdapter通过XMLWeb服务从Windows.NETFramework应用程序检索数据。Windows.NET Framework应用程序使用Visual FoxPro COM对象获取数据,该对象使用XMLAdapter类准备以XML Diffgram格式导出的数据。然后,通过使用ASP.NET XML Web服务将XML格式的数据传递给调用应用程序,将数据公开给其他应用程序,如其他Visual FoxPro应用程序、移动设备、.NET Webforms和.NET Winforms。
VisualFoxpro应用程序使用XMLAdapter类接受XMLWeb服务使用者发送的XML,并使用更改更新数据库。对XMLTable对象调用ApplyDiffgram()方法,以将更改应用于光标,如它所应用的Alias属性中所述。下面显示了接受XML Diffgram文件并使用更改更新Customers表的代码:
OPEN DATABASE (_samples+"\northwind\northwind")
cFile = "c:\XMLAdapter\DiffgramXML.xml"
adapter = CREATEOBJECT("XMLAdapter")
adapter.LoadXML(cFile,.T.)
adapter.Tables(1).Alias = "Customers"
USE Customers IN 0
adapter.Tables(1).ApplyDiffgram()
使用新的CursorAdapter类
与仅使用CursorAdapter相比,将XMLAdapter类与新的CursorAdapter类一起使用可以更好地控制XML数据。可以在生成XML或填充游标之前更改数据类型。如果要导入的XML文件包含多个表,XMLAdapter将创建不同的XMLTable对象。
XMLAdapter类允许您指定有效的XMLTable对象作为CursorAdapter.SelectCmd属性的参数,从而为CursorAdapter对象提供了作为XML源的灵活性。下面的代码演示了如何使用游标适配器:
adapter = CREATEOBJECT("XMLAdapter")
cFile = "c:\XMLAdapter\CustomerXML.xml"
adapter.LoadXML(cFile,.T.)
MyCursorAdapter.SelectCmd="adapter.Tables(1)"
MyCursorAdapter.CursorFill()
如果计划使用CursorAdapter通过Visual FoxPro中的Soap工具包与XML Web服务通信,则需要使用XMLAdapter类从XML Web服务检索XML。通过使用XMLAdapter.Attach()检索Windows.NET数据集来实现这一点。
总结
XML提供了在Intranet/Internet上描述、交换和移动数据的通用方法。它是平台中性的。XML是Windows.NET技术的基础。Visual FoxPro 8.0支持和接受XML的战略价值在于,它使Visual FoxPro能够连接到其他Visual FoxPro应用程序和Windows.NET应用程序,以及支持XML的其他平台或系统?通用集成业务应用程序。
清单1:示例.NET代码
Dim cConnStr As String = _
"user id=sa;Initial Catalog=northwind;Server=(local)"
Dim strsql As String
Dim ds As New DataSet()
strsql = "SELECT CustomerID, CompanyName " & _
"FROM Customers " & _
"WHERE CompanyName LIKE 'A%'"
Dim da_customers As New sqlDataAdapter(strsql, cConnStr)
'Include all length information in this schema if a VFP client
'is consuming this data via an XMLAdapter otherwise all the client
'cursor fields will be memo fields. This is because the memo field
'is the default type in VFP for unlimited length strings.
da_customers.MissingSchemaAction = MissingSchemaAction.AddWithKey
da_customers.Fill(ds, "Customers")
strsql = "SELECT Orders.CustomerID, Orders.OrderId, " & _
"Orders.OrderDate, Orders.ShipName " & _
"FROM Orders INNER JOIN Customers " & _
"ON Orders.CustomerID = Customers.CustomerID " & _
"WHERE Customers.CompanyName LIKE 'A%'"
Dim da_orders As _
New sqlDataAdapter(strsql, cConnStr)
'Include all length information in this schema if a VFP client
'is consuming this data via an XMLAdapter otherwise all the client
'cursor fields will be memo fields. This is because the memo field
'is the default type in VFP for unlimited length strings.
da_orders.MissingSchemaAction = MissingSchemaAction.AddWithKey
da_orders.Fill(ds, "Orders")
strsql = "SELECT Order_details.OrderId, " & _
"Order_details.ProductID, " & _
"Order_details.UnitPrice, Order_details.Quantity " & _
"FROM [Order Details] Order_details " & _
"INNER JOIN Orders " & _
"ON Order_details.OrderID = Orders.OrderId " & _
"INNER JOIN Customers " & _
"ON Orders.CustomerID = Customers.CustomerID " & _
"WHERE Customers.CompanyName LIKE 'A%'"
Dim da_orders_details As _
New sqlDataAdapter(strsql, cConnStr)
'Include all length information in this schema if a VFP client
'is consuming this data via an XMLAdapter otherwise all the client
'cursor fields will be memo fields. This is because the memo field
'is the default type in VFP for unlimited length strings.
da_orders_details.MissingSchemaAction = _
MissingSchemaAction.AddWithKey
da_orders_details.Fill(ds, "Order_Details")
Dim strFileXML As String = "c:\XMLAdapter\DotNET.xml"
Dim strFileXSD As String = "c:\XMLAdapter\DotNET.xsd"
ds.WriteXmlSchema(strFileXSD)
ds.WriteXml(strFileXML)
有其他技术问题吗?
联系代码咨询techhelp@codemag.com.
在这里加菲猫提供了一些测试DEMO,大家可以试试看。点击查看原文也可以跳转下载链接。
https://share.weiyun.com/SZpbB3i8