Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2010-01

OOP and XML usage

17 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Graeme Geldenhuys

Hi,

The small project I am working on requires reading a XML file and using that data for various things, including building a GUI interface.

Most of my projects are database driven and uses the tiOPF framework to do my load/saving work (plus a lot of other things).

As the title says, all my applications are normally object driven. This new project I am working on should not be any different. One big difference though is that it is not database driven and I don't want to bind it to tiOPF framework.

So at the moment I reading the xml file and building my own object model based on the various elements and attributes in the XML file.

Example:

-----
<?xml version="1.0" standalone="yes"?>
<install desc="my description" version="0.9">
text for install element
<eula>xxxx</eula>
<eula lang="af">xxxxx</eula>
</install>
----

...would translate to classes as follows: elements become classes and attributes become properties...

TSetupFile
TInstall
TEULAList
TEULA

Interfaces section of TInstall might look like this....

  TInstall = class(TObject)
  public
    property Text: string...      // 'text for install element'
    property Desc: string...      // 'my description'
    property Version: string      // '0.9'
    property EulaList: TEULAList .....
  end;

This makes sense to me, and this is the design I am used to following with tiOPF based projects. But like I said, I am not using tiOPF this time and I am working with a XML file, which I haven't worked with before.

Am I taking the right OOP approach here, or should I rather be working with the dom unit and TXMLDocument, TXMLElement etc classes directly. At the moment I do not require writing to the XML file, only reading. At a much later date, I'll be writing to the XML file though.

I feel my approach of using my own specialized classes is a better fit compared to the generic TXMLElement classes. But I just want to confirm my thoughts and also ask...

How do other developers use XML files?

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/
Michael Van Canneyt
to Graeme Geldenhuys
Graeme Geldenhuys wrote 61 lines
Hi, The small project I am working on requires reading a XML file and using that data for various things, including building a GUI interface. Most of my projects are database driven and uses the tiOPF framework to do my load/saving work (plus a lot of other things). As the title says, all my applications are normally object driven. This new project I am working on should not be any different. One big difference though is that it is not database driven and I don't want to bind it to tiOPF framework. So at the moment I reading the xml file and building my own object model based on the various elements and attributes in the XML file. Example: ----- <?xml version="1.0" standalone="yes"?> <install desc="my description" version="0.9"> text for install element <eula>xxxx</eula> <eula lang="af">xxxxx</eula> </install> ---- ...would translate to classes as follows: elements become classes and attributes become properties... TSetupFile TInstall TEULAList TEULA Interfaces section of TInstall might look like this.... TInstall = class(TObject) public property Text: string... // 'text for install element' property Desc: string... // 'my description' property Version: string // '0.9' property EulaList: TEULAList ..... end; This makes sense to me, and this is the design I am used to following with tiOPF based projects. But like I said, I am not using tiOPF this time and I am working with a XML file, which I haven't worked with before. Am I taking the right OOP approach here, or should I rather be working with the dom unit and TXMLDocument, TXMLElement etc classes directly. At the moment I do not require writing to the XML file, only reading. At a much later date, I'll be writing to the XML file though. I feel my approach of using my own specialized classes is a better fit compared to the generic TXMLElement classes. But I just want to confirm my thoughts and also ask... How do other developers use XML files?

Yes.
I use DOM to read the file, and then translate the found TDOMElement nodes to the actual business classes.

Michael.

Graeme Geldenhuys
to Michael Van Canneyt
Michael Van Canneyt wrote
Yes. I use DOM to read the file, and then translate the found TDOMElement nodes to the actual business classes.

Thanks for the quick response. I'm glad I am on the right track and my idea is not totally dumb founded. :)

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/
Leonardo M. Ramé
to Graeme Geldenhuys: The small project I am working on requires reading a XML file and using that data for…

I use a similar approach in a systems integration product for a hospital, it communicates different systems by XML files. The app receives an XML with data related to an radiology study, then parses the file and convert it to an object, do some checkings and transformations, and store the object to a database or reject the message.

Most tags are parsed automatically because them have a one-to-one relation to the object's properties, and with others we had to create custom associations.

How it works:
1) Create an instance of FCL-XML's TXMLFile class, let's call it lXMLDoc, and use ReadXMLFile to parse the file.

2) Create a method called, for example ProcessChildNode, as follows:

procedure TMyClass.ProcessChildNode(ANode: TDomNode);
begin
  while Assigned(ANode) do
  begin
    case ANode.NodeType of
      ELEMENT_NODE: begin
        if ANode.ParentNode.ParentNode  nil then
          NodeEvent(ANode);
      end;
      ATTRIBUTE_NODE:;
      TEXT_NODE, CDATA_SECTION_NODE: begin
        if ANode.ParentNode.ParentNode  nil then
           NodeEvent(ANode);
      end;
    end;
    if ANode.HasChildNodes then
      ProcessChildNode(ANode.FirstChild);
    ANode := ANode.NextSibling;
  end;
end;

3) Create the NodeEvent method:

procedure TMyClass.NodeEvent(ANode: TDomNode);
begin
  case ANode.NodeType of
    TEXT_NODE,
    CDATA_SECTION_NODE:
       { using RTTI set properties of FMyObject }
       SetPropValue(FMyObject, ANode.NodeName, ANode.NodeValue);
    // ...
    // more types
  end;
end;

4) After loading the XML file, let's call ProcessChildNode(lXMLDoc.FirstChild) this is a recursive method which will traverse all the XML tree, and it will call the NodeEvent method on only certain types of nodes (look at ProcessChildNode method). In NodeEvent, the value of the node is set to the PUBLISHED!!!! object's properties by using RTTI, of course, if your XML file doesn't match one-to-one with your object, you can avoid using RTTI and do the assignments by hand.

A side note, if your target object, apart from having plain types, it includes properties of type Object, you can adapt the NodeEvent method, and check for ANode.ParentNode.NodeName = 'MyInnerObject', then set FMyObject.MyInnerObject.SomeProperty. That's the way we use to populate an object from an XML file.

Leonardo M. Ramé
http://leonardorame.blogspot.com

Graeme Geldenhuys wrote 99 lines
From: Graeme Geldenhuys Subject: [fpc-pascal] OOP and XML usage To: "FPC-Pascal users discussions" Date: Wednesday, January 27, 2010, 6:47 AM Hi, The small project I am working on requires reading a XML file and using that data for various things, including building a GUI interface. Most of my projects are database driven and uses the tiOPF framework to do my load/saving work (plus a lot of other things). As the title says, all my applications are normally object driven. This new project I am working on should not be any different. One big difference though is that it is not database driven and I don't want to bind it to tiOPF framework. So at the moment I reading the xml file and building my own object model based on the various elements and attributes in the XML file. Example: ----- <?xml version="1.0" standalone="yes"?> <install desc="my description" version="0.9">   text for install element   <eula>xxxx</eula>   <eula lang="af">xxxxx</eula> </install> ---- ...would translate to classes as follows: elements become classes and attributes become properties... TSetupFile TInstall TEULAList    TEULA Interfaces section of TInstall might look like this....   TInstall = class(TObject)   public     property Text: string...      // 'text for install element'     property Desc: string...      // 'my description'     property Version: string      // '0.9'     property EulaList: TEULAList .....   end; This makes sense to me, and this is the design I am used to following with tiOPF based projects. But like I said, I am not using tiOPF this time and I am working with a XML file, which I haven't worked with before. Am I taking the right OOP approach here, or should I rather be working with the dom unit and TXMLDocument, TXMLElement etc classes directly. At the moment I do not require writing to the XML file, only reading. At a much later date, I'll be writing to the XML file though. I feel my approach of using my own specialized classes is a better fit compared to the generic TXMLElement classes. But I just want to confirm my thoughts and also ask...    How do other developers use XML files? Regards,   - Graeme - -- fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/ _______________________________________________ fpc-pascal maillist  -  http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Jorge Aldo G. de F. Junior
to Leonardo M. Ramé

i dont like this way of working with XML files...

im creating my own model using an Class factory and RTTI properties.

you register your classes in the class factory and the XML loader uses a class function to select wich one to create for a given node. This lets you have a lot more control over the process.

the same objects can save theyselves into another XML file thru a property called AsXML.

Class Function XMLTag: String; Virtual;
and
Function AsXML : String; Virtual;

im using this to develop a Component system for Powtils... (But can be used wherever needed)

Anthony Walter
to Jorge Aldo G. de F. Junior

I've written some XML classes which expose themselves as interfaces. Usage goes something like this:

procedure SaveSettings(const Settings: string);
var
  Document: IDocument;
  Filer: IFiler;
begin
  Document := CreateDocument;
  Filer := Document.ForceRoot('test') as IFiler;
  Filer.WriteTime('time', Now);
  Filer.WriteString('application', Application.ExeName);
  Document.SaveToFile(Settings);
end;

<test><time>21:11:17</time><application>test.exe</application></test>

procedure ShowPerson;
var
  Document: IDocument;
  Root: INode;
begin
  Document := CreateDocument;
  Filer := Document.ForceRoot('data');
  Root.ForceNode('person/age').Value = 17;
  Root.FindNode('person[age = 17]').Filer.Write('Jason');
  Root.Filer.Write('person/salary', 10000);
  ShowMessage(Document.Text);
end;

<data><person><age>17</age><name>Jason</name><salary>10000</salary></person><data>

Jorge Aldo G. de F. Junior
to Anthony Walter

with my system would be simply something like

Type
   TMyClass = Class(TXMLNode)
   Private
     fSomething : String;
   Public
     Constructor Create(Const aInstanceName : String); Override;
     Class Function XMLTag: String; Override;
   Published
     Property Something : String Read fSomething Write fSomething;
   End;
Constructor Create(Const aInstaceName  : String);
Begin
  Inherited Create(aInstanceName);
End;
Class Function XMLTag: String;
Begin
  Result := 'MyTag';
End;
Factory.Register(TMyClass);

Whenever the xml loader finds a <mytag something="test"/> it will create an instance of TMyClass and set the published properties accordingly (Using RTTI)...

Theres another procedure (wich is virtual and can be overriden if needed) that triggers events across the three... (wich are basically dotted notation names...)

MyClass1.MyClass2.Test <-

Finds instance MyClass1,
Finds instance MyClass2 that is a child of MyClass1

then issues a DispatchStr in MyClass1 with Test as the message string... (The pointer can be passed as to hold properties, values, etc)...

(Im using this message system to allow brower events to be sent to server side objects)

2010/1/27 Anthony Walter :

Show quoted text 36 lines
I've written some XML classes which expose themselves as interfaces. Usage goes something like this: procedure SaveSettings(const Settings: string); var  Document: IDocument;  Filer: IFiler; begin  Document := CreateDocument;  Filer := Document.ForceRoot('test') as IFiler;  Filer.WriteTime('time', Now);  Filer.WriteString('application', Application.ExeName);  Document.SaveToFile(Settings); end; <test><time>21:11:17</time><application>test.exe</application></test> procedure ShowPerson; var  Document: IDocument;  Root: INode; begin  Document := CreateDocument;  Filer := Document.ForceRoot('data');  Root.ForceNode('person/age').Value = 17;  Root.FindNode('person[age = 17]').Filer.Write('Jason');  Root.Filer.Write('person/salary', 10000);  ShowMessage(Document.Text); end; <data><person><age>17</age><name>Jason</name><salary>10000</salary></person><data> _______________________________________________ fpc-pascal maillist  -   http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Jorge Aldo G. de F. Junior
to Jorge Aldo G. de F. Junior

im actually needing better RTTI as to allow easier method invocation...

But generally i feel my way of doing XML is better than FPC defaults (Too generic, tries to solve too many problems with the same code)

Michael Van Canneyt
to Jorge Aldo G. de F. Junior
Jorge Aldo G. de F. Junior wrote
im actually needing better RTTI as to allow easier method invocation... But generally i feel my way of doing XML is better than FPC defaults (Too generic, tries to solve too many problems with the same code)

What exactly do you mean by FPC defaults ?

Michael.

Graeme Geldenhuys
to Jorge Aldo G. de F. Junior: with my system would be simply something like Type TMyClass = Class(TXMLNode) Private…
Jorge Aldo G. de F. Junior wrote
Whenever the xml loader finds a <mytag something="test"/> it will create an instance of TMyClass and set the published properties accordingly (Using RTTI)...

I like that idea, but how flexible is? By that I mean, I have nested tags (using the same element name) that I need to load. Something like a dependency tree. My custom object model can handle this without problems, but I'm still curious about your solution.

Example XML, and there isn't a limit to the nesting of options.

<install>
<option>Option 1</option>
<option>Base database support
<option>Firebird drivers
<option>Windows</option>
<option>Linux</option>
</option>
<option>MySQL drivers</option>
</option>
</install>

Regards, - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://opensoft.homeip.net/fpgui/
Jorge Aldo G. de F. Junior
to Graeme Geldenhuys

each tag generates a new instance of the class

you can add a property (that all objects have) called InstanceName

<option instancename="blabla">something</option>

using the instance name the class factory can differentiate from other instances (factory.instance['blabla'] retrieves the correct instance, or, factory.dotnotation['roottag.nexttag.blabla'] retrieves by dotted notation..

or

if you dont specify an instance name the factory will generate one randonly...

and actually i prefer to setup properties of objects using xml properties instead of xml text

<tcpserver ip="192.168.1.1" port="80"/> instead of <tcpserver><ip>192.168.1.1</ip><port>80</port></tcpserver>

2010/1/28 Graeme Geldenhuys :

Show quoted text 37 lines
On 28 January 2010 16:10, Jorge Aldo G. de F. Junior wrote: > > Whenever the xml loader finds a <mytag something="test"/> it will > create an instance of TMyClass and set the published properties > accordingly (Using RTTI)... I like that idea, but how flexible is? By that I mean, I have nested tags (using the same element name) that I need to load. Something like a dependency tree. My custom object model can handle this without problems, but I'm still curious about your solution. Example XML, and there isn't a limit to the nesting of options. <install>  <option>Option 1</option>  <option>Base database support    <option>Firebird drivers      <option>Windows</option>      <option>Linux</option>    </option>    <option>MySQL drivers</option>  </option> </install> -- Regards,  - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://opensoft.homeip.net/fpgui/ _______________________________________________ fpc-pascal maillist  -   http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Jorge Aldo G. de F. Junior
to Michael Van Canneyt: What exactly do you mean by FPC defaults ? Michael.

i mean that FPC-XML tries to be too general and this leads to too cumbersome code in various situations (FPC-XML is clearly overkill for my needs).

2010/1/28 Michael Van Canneyt :

Show quoted text 16 lines
On Thu, 28 Jan 2010, Jorge Aldo G. de F. Junior wrote: > im actually needing better RTTI as to allow easier method invocation... > > But generally i feel my way of doing XML is better than FPC defaults > (Too generic, tries to solve too many problems with the same code) What exactly do you mean by FPC defaults ? Michael. _______________________________________________ fpc-pascal maillist  -   http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Jorge Aldo G. de F. Junior
to Jorge Aldo G. de F. Junior

but theres a flaw in my model (that doesnot means much in what im doing):

the properties in the XML file must match exactly the properties each object has.

else the properties are lost..

(the xml file can have less properties than the object but not the other way around: the xml loader cannot force an object to have a published -rtti- property that it doesnt have in code).

Jorge Aldo G. de F. Junior
to Jorge Aldo G. de F. Junior

"Example XML, and there isn't a limit to the nesting of options."

no theres no limit for nested tags, they are stored in a tree plus a linear list indexed by instance names

(nodes without instance names will receive a random instance name - and be basically out of reach by the linear list - but will be still reachable by walking the tree)

sorry for so much emails, im in a hurry.

Michael Van Canneyt
to Jorge Aldo G. de F. Junior: i mean that FPC-XML tries to be too general and this leads to too cumbersome code in…
Jorge Aldo G. de F. Junior wrote
i mean that FPC-XML tries to be too general and this leads to too cumbersome code in various situations (FPC-XML is clearly overkill for my needs).

But FPC-XML is not meant for storing objects. It is meant to read any correctly formed XML file that you may find.

FPC-XML is not something we invented. It is an implementation of an official W3 specification. (www.w3.org)

Having this specification available means that we can read/write any XML document out there that conforms to this spec, in a standard manner. Since the programmer does not always control the XML he/she gets, sticking to the specifications means we're sure we'll we able to handle any XML is why we implement FCL-XML. Sooner or later the day comes when you'll need it's features, trust me :-)

Michael.

Show quoted text 21 lines
2010/1/28 Michael Van Canneyt : > > > On Thu, 28 Jan 2010, Jorge Aldo G. de F. Junior wrote: > >> im actually needing better RTTI as to allow easier method invocation... >> >> But generally i feel my way of doing XML is better than FPC defaults >> (Too generic, tries to solve too many problems with the same code) > > What exactly do you mean by FPC defaults ? > > Michael. > _______________________________________________ > fpc-pascal maillist  -   > http://lists.freepascal.org/mailman/listinfo/fpc-pascal > _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Graeme Geldenhuys
to Jorge Aldo G. de F. Junior: each tag generates a new instance of the class you can add a property (that all objects…
Jorge Aldo G. de F. Junior wrote 5 lines
and actually i prefer to setup properties of objects using xml properties instead of xml text <tcpserver ip="192.168.1.1" port="80"/> instead of <tcpserver><ip>192.168.1.1</ip><port>80</port></tcpserver>

Both examples are valid XML, so I don't see any issue the way I am using it. My previous example was just that, an example. My actual XML uses both tag attributes and element text. The later is mainly used for longer text in my xml file.

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/
Jorge Aldo G. de F. Junior
to Graeme Geldenhuys

using my system you can retrieve the text by a typecast

mytag.first;
mytag.findofclass(TXMLText); <- will stop the search at the first object of specified class
If mytag.child is TXMLText Then <- to guarantee that we have found something WriteLn((mytag.child as TXMLText).Content); <- will print the contents of the text

or if you know the text position between the child tags

writeln((mytag.childs[0] As TXMLText).Content);

but this is a way quite harder than a simple

WriteLn(mytag.properties['ip']); <- will return the property or '' if not set (the object constructor can setup defaults)

thats why i prefer tag properties instead of xml text...

later you can save the objects with

Var F : Text;
Begin
  Assign(F, 'myfile.xml');
  Rewrite(F);
  WriteLn(F, MyTag.AsXML);
  Close(F);
End;

2010/1/29 Graeme Geldenhuys :

Show quoted text 25 lines
Jorge Aldo G. de F. Junior wrote: > and actually i prefer to setup properties of objects using xml > properties instead of xml text > > <tcpserver ip="192.168.1.1" port="80"/> instead of > <tcpserver><ip>192.168.1.1</ip><port>80</port></tcpserver> Both examples are valid XML, so I don't see any issue the way I am using it. My previous example was just that, an example. My actual XML uses both tag attributes and element text. The later is mainly used for longer text in my xml file. Regards,  - Graeme - -- fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/ _______________________________________________ fpc-pascal maillist  -   http://lists.freepascal.org/mailman/listinfo/fpc-pascal