[Lazarus] Read/write records from/to XML

Bart bartjunk64 at gmail.com
Sun Jan 11 18:33:39 CET 2015


Hi,

I have an XML file with the folowing structure:

<?xml version="1.0" encoding="utf-8"?>
<AppName>
  <Info>
    <Application>Versie 3.0.1</Application>
    <CopyRight>(C) FooBar</CopyRight>
    <Warning>A message in a bottle</Warning>
  </Info>
  <Persons Count=99>
    <Person Index="000">
      <Name>Jan</Name>
      <City>Bergentheim</City>
      <Email>Jan at FooBar.non</Email>
    </Person">
    <Person Index="001">
      <Name>Mary</Name>
      <City>Amsterdam</City>
      <Email>Mary at FooBar.non</Email>
    </Person>
    ....
  </Persons>
</AppName>

What would be the best/most simple way to:
- sequentially read "Count" persons
- find person with Index=X and read Name, City etc?

Currently I iterate through all nodes from the TXMlDocument I read
using ReadXMLFile() and parsing all Text-node values.
It goes something like this:

    iNode := XMLDoc.FirstChild;
    while iNode <> nil do
    begin
      ProcessNode(iNode,  0); // Recursive
      iNode := iNode.NextSibling;
    end;

In ProcessNode I check the nodetype, construct the path, check if the
path is valid, determine if it is a name, city, some other field, or
invalid and store the value in the appropriate recordfield.

This is rather cumbersome.
Mosty, because I need (want) to check that e.g. a City node must be a
child of a Person node, which must be child of Persons node, which
must be child the root node.

E.g. if someone text-edits the file (that's the downside of making it
human-readable) and makes it like so:

...
  <Persons Count=99>
      <Name>Klaas</Name>
    <Person Index="000">
      <Name>Jan</Name>
      <City>Bergentheim</City>
      <Email>Jan at FooBar.non</Email>
    </Person">

The <Name>Klaas</Name> (whilst being legal xml) should be (silently)
disregarded.

So, I'm thinking I'm not using the most optimal method reading the
XML-file, certainly there must be suitable classes to do such a thing?

So, basically what I am looking for is, given the TXMlDocument object:
- find value of Persons/Count
- find Persons/Person with Index=X/Name

Preferrably I want a solution that does not drag in databse components
(the program is supposed to be stand-alone, no external libraries
should be needed).

Bart




More information about the Lazarus mailing list