Monday, April 13, 2009

Hitsoft XML Object Library. General Description

Destination



HitXML - library designed for working with XML files. It allows succesfully solve following tasks:



  • Load\Save XML file in the program with one function call;

  • Represent XML document as object class model;

  • Save model object as XML file, or string;

  • Possibility to use previously saved XML files after tne models expansion;

  • Automatical creation of child model objects;

  • Modify object model creation ways on load;




Functions for loading and saving of XML are placed in the XmlFile.pas unit. This unit using AElfred2 parser for the SAX, you are free to use any XML SAX parser that suit your needs more.



XML Structure



After adding XMLFile into your project, you need to create special unit where you will describe model classes corresponding to the proper XML structure. Every XML node syould have proper delphi model class using following rules:



  • Model class must be inherited from the TRttiEnabled class from the RttiClasses unit.

  • Fileds should be placed into the published section as properties, so that program could use RTTI about them;

  • Properties names must correspond to the sub-xml-node. But camelized names in Delphi will be replaced with dash separated in XML. For example: property SubNode corresponds to <sub-node/> in XML.

  • Properties types selected according to the needs. Simple type properties like Double, Real, Integer, String and so on will be represent as XML attributes of proper node. Class type properties will correspond to the XML nodes.

  • The order of properties in Delphi is not depend of the XML attributes and sub-nodes order.




In our example the model class hierarchy is following:




unit XMLModel;

interface
uses
RttiClasses;

type
TRealEnabled = class(TRttiEnabled)
private
FValue: Real;
published
property Value : Real read FValue write FValue;
end;
TRealEnabledArray = array of TRealEnabled;

TSubNode = class(TRttiEnabled)
private
FHello: string;
published
property Hello : string read FHello write FHello;
end;

TDemoModel = class(TRttiEnabled)
private
FNumber: Integer;
FCaption: string;
FBirthday: TDateTime;
FPrice: Currency;
FIntervals: TRealEnabledArray;//array of real
FSubNode: TSubNode;
public
procedure InsertInterval(Value: Real);
published
property Number : Integer read FNumber write FNumber;
property Caption : string read FCaption write FCaption;
property Birthday : TDateTime read FBirthday write FBirthday;
property Price : Currency read FPrice write FPrice;
property Intervals : TRealEnabledArray read FIntervals write FIntervals;
property SubNode : TSubNode read FSubNode write FSubNode;
end;

implementation

{ TDemoModel }

procedure TDemoModel.InsertInterval(Value: Real);
begin
SetLength(FIntervals, Length(FIntervals) + 1);
FIntervals[Length(FIntervals) - 1] := TRealEnabled.Create;
FIntervals[Length(FIntervals) - 1].Value := Value;
end;

end.



As you can see, model classes could be wider than needed for XML marshaling only. The only rule you need to remember is that all Published properties will be saved to XML and will be tried to loaded from XML. But you are free to use Public or Private properties and methods for your models needs.



Saving data to XML



Now to save the object into the XML you need to use the SaveToFile procedure of the XMLFile unit;





procedure SaveToFile( FileName: string; RootObj: TRttiEnabled; ClassResolver: TRttiClassResolver = nil);



In following example we fullfill the model object with data and save it into the file demo.xml:





procedure TForm1.Button1Click(Sender: TObject);
var
Model: TDemoModel;
begin
Model := TDemoModel.Create;
Model.Number := 1;
Model.Caption := 'Hello';
Model.Birthday := Now;
Model.Price := 235.04;
Model.SubNode.Hello := '2008 Year';
Model.InsertInterval(12.5);
Model.InsertInterval(12.5 * 2);
Model.InsertInterval(12.5 * 3);
Model.InsertInterval(12.5 * 4);
Model.InsertInterval(12.5 * 5);
SaveToFile('demo.xml', Model);
end;



As result we'll receive following XML file:





<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<demo-model number="1" caption="Hello" birthday="39716,5820528472" price="235,04">
<intervals value="12,5"/>
<intervals value="25"/>
<intervals value="37,5"/>
<intervals value="50"/>
<intervals value="62,5"/>
<sub-node hello="2008 Year"/>
</demo-model>



Loading data from XML





procedure TForm1.Button2Click(Sender: TObject);
var
Model: TDemoModel;
begin
Model := TDemoModel.Create;
if FileExists('demo.xml') then
LoadFromFile('demo.xml', Model);
end;



While loading XML file in the Delphi IDE you may receive the IOFileException exception - you may ignore it. In the application runtime it will be worked out by SAX for Pascal library. This is SAX for Pascal library specifics.



Organization



The downloads split in three parts:



HitXML.1.0.17.zip with folders src and demo in it with HitXML sources and demo project accordingly.




  • XMLFile.pas this unit contain procedures and functions for XML saving and loading

  • RttiClasses.pas this one is for work with RTTI

  • RttiUtils.pas these are some utilities for work with RTTI classes;

  • SAX2Rtti.pas this is intermediate link between SAXVendor and RTTI units;

  • SAXCustomWriter expands the SAX for Pascal for writing the XmL




For proper work of HitXML library you will also need a couple of external modules:



  • SAX - SAX for Pascal, project homepage http://sourceforge.net/projects/saxforpascal/ or you may use version we provide in our downloads HitXML.Required.SAX.zip

  • AElfred2 - XML parser for the SAX for Pascal library. Unfortunatelly we do not know it's current web-site, the one specified in sources is not working anymore. But you may use the sources from our downloads HitXML.Required.AElfred2.zip




Good luck with HitXML. Please let us know about any recommendations, feature requests or anything.

No comments: