tags:

views:

252

answers:

1

I'm considering saving my application settings as a xml instead of using the registry but I'm having a hard time understanding and using OmniXML.

I know some of you here use and recomend OnmiXML so I hope someone can give me some pointers.

I'm used to use TRegistry to create a new key if it doesn't exist, but I can't seem to find any similar option on OmniXML.

Basically what I wish to do is save settings on different XML levels, something like this:

<ProgramName version="6">
  <profiles>
    <profile name="Default">
      <Item ID="aa" Selected="0" />
      <Item ID="bb" Selected="1" />
    </profile>
  </profiles>
  <settings>
    <CheckForUpdates>1</CheckForUpdates>
    <CheckForUpdatesInterval>1</CheckForUpdatesInterval>
    <ShowSplashScreen></ShowSplashScreen>
  </settings>
</ProgramName>

Now, when first running the program I wont have the xml file so I will need to create all the sub-levels. With the TRegistry it was easy, just call OpenKey(pathtokey, True) and the key will be created if it doesn't exist. Is there any comparable way to do the same thing with OmniXML? Someting like:

SetNodeStr('./settings/CheckForUpdates', True);

Which would create the "path" if it doesn't already exist.

+5  A: 

The easy method to save application settings with OmniXML is to use the OmniXMLPersistent unit.

As explained in OmniXML Sample Page you simply define an object with published properties and with the TOmniXMLWriter class you serialize the object to a file or a string (loading with the TOmniXMLReader class)

The serialization supports objects nested, so you could have complex structures, for example your xml could be represented by this objects:

type
  TAppProfiles = class(TCollection)
    ...
  end;

  TAppProfile = class(TCollectionItem)
    ...
  end;

  TAppSettings = class(TPersistent)
  private
    FCheckForUpdates: Integer;
    FCheckForUpdatesInterval: Integer;
    FShowSplashScreen: Boolean;
  published
    property CheckForUpdates: Integer read FCheckForUpdates write FCheckForUpdates;
    property CheckForUpdatesInterval: Integer read FCheckForUpdatesInterval write FCheckForUpdatesInterval;
    property ShowSplashScreen: Boolean read FShowSplashScreen write FShowSplashScreen;
  end;

  TAppConfiguration = class(TPersistent)
  private
    FProfiles: TAppProfiles;
    FSettings: TAppSettings;
  published
    property Profiles: TAppProfiles read FProfiles write FProfiles;
    property Settings: TAppSettings read FSettings write FSettings;
  end;

//Declare an instance of your configuration object
var
  AppConf: TAppConfiguration;

//Create it
AppConf := TAppConfiguration.Create;

//Serialize the object!
TOmniXMLWriter.SaveToFile(AppConf, 'appname.xml', pfNodes, ofIndent);

//And, of course, at the program start read the file into the object
TOmniXMLReader.LoadFromFile(AppConf, 'appname.xml');

That's all.. without writing a single line of xml yourself...

If you still prefer the "manual" way, take a look at the OmniXMLUtils units or the Fluent interface to OmniXML (written by Primoz Gabrijelcic, the OmniXML author)

Ah.. public thanks to Primoz for this excellent delphi library!

paolorossi
(Primoz here) Just to prevent confusion - OmniXML was written by Miha Remec, I just contributed some small parts. And +1 for the answer - it's exactly what I would write.
gabr
Thanks paolorossi for the answer and the code. Unfortunately I also have to programmatically read/write hundreds of values, so for that particular part, I really need to manually create/read/delete the data. Anyone knows if it's possible to auto-create precedent nodes if they don't already exist? And finally a big thanks to Miha Remec and Primoz Gabrijelcic for OnmiXML and GpFluentXML respectively.
smartins