Search code examples
xmldelphidelphi-2007

How to write more than once in an XML document


I'm trying to save a word and a boolean value, that I have in an array of records, to an XML document. This is my code:

procedure AddArrayToXMLFile(const Array : array of TKeycodeRecord; const Name : string);
var
  XMLFile : IXMLDocument;
  NameNode, ArrayFieldNode: IXMLNode;
  i : integer;
begin
  if FileExists(ArrayXMLFilePath) then
  begin
    XMLFile := LoadXMLDocument(ArrayXMLFilePath);
  end
  else
  begin
    XMLFile := NewXMLDocument;
    NameNode := XMLFile.AddChild(Name);
    ArrayFieldNode := NameNode.AddChild('child');
  end;

  for i := 0 to Length(Array) - 1 do
  begin
    ArrayFieldNode.Attributes['keycode'] := Array[i].keycode;
    ArrayFieldNode.Attributes['shiftState'] := Array[i].shiftState;
  end;

  XMLFile.SaveToFile(ArrayXMLFilePath);
end;

And this is the result:

<?xml version="1.0"?>
<TestName><child keycode="48" shiftState="false"/></TestName>

The procedure saves only the last entry of the array, which makes me believe that the for loop only changes the values of the first entry, instead of adding more values to the XML document. The wanted result would look like this, but with more entries:

<?xml version="1.0"?>
<TestName><child keycode="52" shiftState="false"/></TestName>
<TestName><child keycode="70" shiftState="true"/></TestName>
<TestName><child keycode="75" shiftState="false"/></TestName>
<TestName><child keycode="49" shiftState="false"/></TestName>
<TestName><child keycode="48" shiftState="false"/></TestName>

or like this:

<?xml version="1.0"?>
<TestName><child keycode="48" shiftState="false"/><child keycode="49" shiftState="false"/><child keycode="48" shiftState="false"/>

Solution

  • You need to add the nodes NameNode and ArrayFieldNode in the for loop, like that:

    procedure AddArrayToXMLFile(const Array : array of TKeycodeRecord; const Name : string);
    var
      XMLFile : IXMLDocument;
      NameNode, ArrayFieldNode: IXMLNode;
      i : integer;
    begin
      if FileExists(ArrayXMLFilePath) then
      begin
        XMLFile := LoadXMLDocument(ArrayXMLFilePath);
      end
      else
      begin
        XMLFile := NewXMLDocument;
      end;
    
      NameNode := XMLFile.AddChild(Name);
    
      for i := 0 to Length(Array) - 1 do
      begin      
        ArrayFieldNode := NameNode.AddChild('child');
        ArrayFieldNode.Attributes['keycode'] := Array[i].keycode;
        ArrayFieldNode.Attributes['shiftState'] := Array[i].shiftState;
      end;
    
      XMLFile.SaveToFile(ArrayXMLFilePath);
    end;
    

    The way you did is you added a single node and then in the loop you changed the attributes of the same node in each iteration.