Search code examples
xmllazarusfreepascal

Lazarus/Free Pascal: read/write nodes with the same name using TXMLConfig


It seems like TXMLConfig is only good for basic and simple saving of properties/settings for your application and not fit for full-on XML file parsing. You're supposed to only read XML files, which have also been created by your application. Under these circumstances, it makes sense that there is no support for nodes with the same name, since it would represent the same property/setting.

Let's assume the following XML file:

<Configuration Version="1.0">
  <Family Name="Simpson">
    <Member Gender="Male">Homer</Member>
    <Member Gender="Female">Marge</Member>
    <Member Gender="Male">Bart</Member>
    <Member Gender="Female">Lisa</Member>
    <Member Gender="Female">Maggie</Member>
  </Family>
</Configuration>

I read this official tutorial and searched the web, but couldn't figure it out. Is there any way to use TXMLConfig to read Lisa's gender for example?


Solution

  • You cannot use the TXMLConfig class since that does indeed only work if you do not have multiple nodes with the same name inside the same parent node.

    You have to use the more low level functions. Here is an example how to lookup the gender of Lisa:

    uses
      Classes, SysUtils, CustApp, Dom, XmlRead
    
    var
      Doc: TXMLDocument;
      Members: TDOMNodeList;
      Member: TDOMNode;
      Gender: TDOMNode;
      i: integer;
    begin
    
      // Read the XML file into an XML Document
      ReadXMLFile(Doc, 'D:\A.xml');
    
      // Get all nodes with name "Member"
      Members:= Doc.GetElementsByTagName('Member');
    
      // For all Member nodes
      for i:= 0 to Members.Count - 1 do
      begin
        Member:= Members[i];
    
        // Check if their content is Lisa
        if(Member.TextContent = 'Lisa') then
        begin
          // Get the attribute with name "Gender"
          Gender:= Member.Attributes.GetNamedItem('Gender');
    
          // Output the value of the attribute
          Writeln(Gender.TextContent);
        end;
      end;
    
      Readln;
    end.