If ( Assigned( tmpObj ) AND ( tmpObj Is TPersistent ) ) Then
LoadObjFromXML( aNode.ChildNodes[WideString(pInfo^.Name)],
tmpObj As TPersistent );
End
Else If ( pInfo^.PropType^.Kind In DefaultFilter ) Then
SetPropValue( aObj, pInfo^.Name,
String( aNode.ChildNodes[WideString( pInfo^.Name )].Text ) );
End;
Finally
pList.Free;
End;
End;
end;
class procedure TMXMLPersistent.SaveObjToXML(aNode: IXMLNode;
aObj: TPersistent);
Var
i : Integer;
pList : TMPropList;
pInfo : PPropInfo;
tmpObj: TObject;
begin
If ( aObj Is TMDataSetProxy ) Then
( aObj As TMDataSetProxy ).SaveToXML( aNode )
Else
Begin
pList := TMPropList.Create( aObj );
Try
For i := 0 To pList.PropCount - 1 Do
Begin
pInfo := pList.Props[i];
If ( pInfo^.PropType^.Kind = tkClass ) Then
Begin
tmpObj := TObject( Integer( GetPropValue( aObj, pInfo^.Name ) ) );
If ( Assigned( tmpObj ) AND ( tmpObj Is TPersistent ) ) Then
SaveObjToXML( aNode.AddChild( WideString( pInfo^.Name ) ),
tmpObj As TPersistent );
End
Else If ( pInfo^.PropType^.Kind In DefaultFilter ) Then
aNode.AddChild( WideString( pInfo^.Name ) ).Text :=
GetPropValue( aObj, pInfo^.Name );
End;
Finally
pList.Free;
End;
End;
end;
http://www.mscto.com
这个实现应该说是很简单的。主要是三个部分(Load和Save的结构是相似的): 软件开发网
一是对TMDataSetProxy作特别处理,委托给这个类自己去处理它的实现,因为它与一般的类不同,需要通过ForEach遍历全部记录,这其实就是同时实现数据集的XML持久化。
二是对Class作递归处理,当然只支持从TPersistent派生的class。
三是一般的Field简单地转成String保存,其中借鉴了lexlib的Filter,只处理那些能简单地转成String的数据类型,过滤掉那些可能造成转换出错的类型。
上面的代码中用到的TMPropList见《用DELPHI的RTTI实现数据集的简单对象化》中的实现。
http://www.mscto.com
下面是用TMDataSetProxy实现的数据集的XML持久化。免去了需要通过TClientDataSet进行的麻烦,并且采用的是用Node记录字段的方式,.net也是采用这样的方式,与TClientDataSet所用的用Attribute记录字段的方式不同。虽然这样生成的 XML文件将会略大一些,但是好处也是显而易见的,特别是我是准备用在Web应用中的,用Node方式记录的XML,在用XSLT时会方便很多。
procedure TMDataSetProxy.LoadFromXML(aNode: IXMLNode);
Var
i, j : Integer;
pInfo : PPropInfo;
pRow : IXMLNode;
begin
For j := 0 To aNode.ChildNodes.Count - 1 Do
Begin
&