Body\....">
ThereasonforthisisthatDelphi'sXMLTransformproviderdoesnotlikethe"soap:
"inthefirstelementofthe"from"attribute.Thatmightgetfixedinsomeupdatepack,sothispointmightnotapply
6.We'renearlythere.DropaTClientDataset,aTXMLTransformProviderandaTDatasourceontheform.Here'swhattheformlookslikenow:
LinktheGrid,theDatasourceandtheClientDataset,andsettheClientDataset'sProviderNametopointtotheXMLTransformProvider.7.SettheTransformRead.TransformationFileoftheXMLTransformProvidertoZiptrans.XTR.
8.NowweneedtosetthedataoftheXMLTransformProvideratruntime.Here'ssomeadditionalcodeintheHTTPRio'sOnAfterExecute:
procedureTForm1.HTTPRIO1AfterExecute(constMethodName:
String;
SOAPResponse:
TStream);
var
XMLDoc:
IXMLDocument;
begin
SOAPResponse.Position:
=0;
Memo1.Lines.LoadFromStream(SOAPResponse);
ClientDataset1.Active:
=FALSE;
SOAPResponse.Position:
=0;
XMLDoc:
=NewXMLDocument;
XMLDoc.Encoding:
=SUTF8;
SOAPResponse.Position:
=0;
XMLDoc.LoadFromStream(SOAPResponse);
XMLTransformProvider1.TransformRead.SourceXmlDocument:
=XMLDoc.GetDOMDocument;
ClientDataset1.Active:
=TRUE;
end;
You'llnoticethatwe'vecreatedanXMLDocument,loadeditfromtheReceivedSOAPstream,andappliedthetransformtoit.Theclientdatasetgetsdatafromtheprovideranddisplaysthedata:
That'sit!
Amazing.
Thankyou.
What'snext?
ThistransformationisveryspecifictothisparticularserviceandXMLschema.SOifyouknowwhatXMLisgoingtobereturned(theformat)thenyoucanuseXMLmappertogenerateatransformationforit.
Ihaven'tbeenabletowritea"general"transformthatcanbeappliedtoANY.NETreturnedXML,butifanyonedoesI'dlovetohearaboutit.
Also,whyhaveIusedtheHTTPRio'sOnAfterExecute,ratherthanmanipulatingthethes_schemaparameter?
There'sanotherbuginDelphithatdoesn'tlikeparametersreturnedasXML.Morerevealedinthisthread.
Youcandownloadallthecodeforthisprojectatorat
DeepakShenoy(shenoy@)isaDirectoratAgniSoftware,asoftwarecompanyinIndiathatoffersconsultancyandoffshoredevelopmentsolutions.Itmightbeawhilebeforehishairgetspointysohe'sallowedtounderstandsometechnology.
在微软中国找到了一个官方的说法------不建议将DataSet直接作为返回值传送,因为里面含有大量复杂的schema以及更改等信息,大部分非.NET语言在解析上有困难。
建议使用DataSet.WriteXML方法将简化后的XML版本作为一个WideString回传。
经过试验,已经在Delphi下轻松通过,Delphi中还需要使用XMLMapper工具事先生成Transfomation(XTR)文件。
Delphi7客户端代码
----------------------------------------------------------------------------------------------------------------------------
unitWSTestMain;
interface
uses
Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,
Dialogs,InvokeRegistry,StdCtrls,Rio,SOAPHTTPClient,Grids,DBGrids,
DB,DBClient,DBTables,Provider,xmldom,Xmlxform,XMLIntf,XMLDoc,SOAPConst;
type
TForm1=class(TForm)
HTTPRIO1:
THTTPRIO;
Button1:
TButton;
Memo1:
TMemo;
XMLTransformProvider1:
TXMLTransformProvider;
ClientDataSet1:
TClientDataSet;
DataSource1:
TDataSource;
DBGrid1:
TDBGrid;
procedureButton1Click(Sender:
TObject);
private
{Privatedeclarations}
public
{Publicdeclarations}
end;
var
Form1:
TForm1;
implementation
usesWSTestDefine;
{$R*.dfm}
procedureTForm1.Button1Click(Sender:
TObject);
var
A:
Service1Soap;
B:
WideString;
XMLDoc:
IXMLDocument;
begin
A:
=HTTPRIO1asService1Soap;
B:
=A.GetPersonTable;
Memo1.Lines.Add(B);
ClientDataset1.Active:
=FALSE;
XMLDoc:
=NewXMLDocument;
XMLDoc.Encoding:
=SUTF8;
XMLDoc.LoadFromXML(B);
XMLTransformProvider1.TransformRead.SourceXmlDocument:
=XMLDoc.GetDOMDocument;
ClientDataset1.Active:
=TRUE;
end;
end.
---------------------------------------------------------------------------------------
.NETWebService代码
---------------------------------------------------------------------------------------
System.Text.StringBuilderstrbuilder=newSystem.Text.StringBuilder();
StringWriterwriter=newStringWriter(strbuilder);
dataset.WriteXml(writer,System.Data.XmlWriteMode.IgnoreSchema);
returnstrbuilder.ToString();
classXmlDatasetConvert
{
//将xml对象内容字符串转换为DataSet
publicstaticDataSetConvertXMLToDataSet(stringxmlData)
{
StringReaderstream=null;
XmlTextReaderreader=null;
try
{
DataSetxmlDS=newDataSet();
stream=newStringReader(xmlData);
//从stream装载到XmlTextReader
reader=newXmlTextReader(stream);
xmlDS.ReadXml(reader);
returnxmlDS;
}
catch(System.Exceptionex)
{
throwex;
}
finally
{
if(reader!
=null)
reader.Close();
}
}
//将xml文件转换为DataSet
publicstaticDataSetConvertXMLFileToDataSet(stringxmlFile)
{
StringReaderstream=null;
XmlTextReaderreader=null;
try
{
XmlDocumentxmld=newXmlDocument();
xmld.Load(xmlFile);
DataSetxmlDS=newDataSet();
stream=newStringReader(xmld.InnerXml);
//从stream装载到XmlTextReader
reader=newXmlTextReader(stream);
xmlDS.ReadXml(reader);
//xmlDS.ReadXml(xmlFile);
returnxmlDS;
}
catch(System.Exceptionex)
{
throwex;
}
finally
{
if(reader!
=null)
reader.Close();
}
}
//将DataSet转换为xml对象字符串
publicstaticstringConvertDataSetToXML(DataSetxmlDS)
{
MemoryStreamstream=null;
XmlTextWriterwriter=null;
try
{
stream=newMemoryStream();
//从stream装载到XmlTextReader
writer=newXmlTextWriter(stream,Encoding.Unicode);
//用WriteXml方法写入文件.
xmlDS.WriteXml(writer);
intcount=(int)stream.Length;
byte[]arr=newbyte[count];
stream.Seek(0,SeekOrigin.Begin);
stream.Read(arr,0,count);
UnicodeEncodingutf=newUnicodeEncoding();
returnutf.GetString(arr).Trim();
}
catch(System.Exceptionex)
{
throwex;
}
finally
{
if(writer!
=null)
writer.Close();
}
}
//将DataSet转换为xml文件
publicstaticvoidConvertDataSetToXMLFile(DataSetxmlDS,stringxmlFile)
{
MemoryStreamstream=null;
XmlTextWriterwriter=null;
try
{
stream=newMemoryStream();
//从stream装载到XmlTextReader
writer=newXmlTextWriter(stream,Encoding.Unicode);
//用WriteXml方法写入文件.
xmlDS.WriteXml(writer);
intcount=(int)stream.Length;
byte[]arr=newbyte[count];
stream.Seek(0,SeekOrigin.Begin);
stream.Read(arr,0,count);
//返回Unicode编码的文本
UnicodeEncodingutf=newUnicodeEncoding();
StreamWritersw=newStreamWriter(xmlFile);
sw.WriteLine("
xmlversion=\"1.0\"encoding=\"utf-8\"?
>");
sw.WriteLine(utf.GetString(arr).Trim());
sw.Close();
}
catch(System.Exceptionex)
{
throwex;
}
finally
{
if(writer!
=null)
writer.Close();
}}}