[fpc-pascal] OOP and XML usage

Leonardo M. Ramé martinrame at yahoo.com
Wed Jan 27 14:18:32 CET 2010


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


--- On Wed, 1/27/10, Graeme Geldenhuys <graemeg.lists at gmail.com> wrote:

> From: Graeme Geldenhuys <graemeg.lists at gmail.com>
> Subject: [fpc-pascal] OOP and XML usage
> To: "FPC-Pascal users discussions" <fpc-pascal at lists.freepascal.org>
> 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  -  fpc-pascal at lists.freepascal.org
> http://lists.freepascal.org/mailman/listinfo/fpc-pascal
> 


      



More information about the fpc-pascal mailing list