How to read and write XML document node values?

Sunil Sharma picture Sunil Sharma · Jun 28, 2012 · Viewed 11.3k times · Source

I want to read some nodes of a XML file and show their values in some custom input fields. User can then change the values if needed, and by clicking the Next button these values should be saved back to the XML.

How to do this in InnoSetup script ?

Answer

TLama picture TLama · Jun 29, 2012

Use the CreateOleObject function to instantiate the standard MSXML2.DOMDocument COM object. The following script shows how to load and save a text value for a single node from the XML file posted below (the script itself was inspired by the examples from MSDN):

[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
DefaultGroupName=My Program
UninstallDisplayIcon={app}\MyProg.exe
Compression=lzma2
SolidCompression=yes
OutputDir=userdocs:Inno Setup Examples Output

[Files]
Source: "MyProg.exe"; DestDir: "{app}"
Source: "MyProg.chm"; DestDir: "{app}"

[Icons]
Name: "{group}\My Program"; Filename: "{app}\MyProg.exe"

[Code]
var
  CustomEdit: TEdit;
  CustomPageID: Integer;

function LoadValueFromXML(const AFileName, APath: string): string;
var
  XMLNode: Variant;
  XMLDocument: Variant;  
begin
  Result := '';
  XMLDocument := CreateOleObject('Msxml2.DOMDocument.6.0');
  try
    XMLDocument.async := False;
    XMLDocument.load(AFileName);
    if (XMLDocument.parseError.errorCode <> 0) then
      MsgBox('The XML file could not be parsed. ' + 
        XMLDocument.parseError.reason, mbError, MB_OK)
    else
    begin
      XMLDocument.setProperty('SelectionLanguage', 'XPath');
      XMLNode := XMLDocument.selectSingleNode(APath);
      Result := XMLNode.text;
    end;
  except
    MsgBox('An error occured!' + #13#10 + GetExceptionMessage, mbError, MB_OK);
  end;
end;

procedure SaveValueToXML(const AFileName, APath, AValue: string);
var
  XMLNode: Variant;
  XMLDocument: Variant;  
begin
  XMLDocument := CreateOleObject('Msxml2.DOMDocument.6.0');
  try
    XMLDocument.async := False;
    XMLDocument.load(AFileName);
    if (XMLDocument.parseError.errorCode <> 0) then
      MsgBox('The XML file could not be parsed. ' + 
        XMLDocument.parseError.reason, mbError, MB_OK)
    else
    begin
      XMLDocument.setProperty('SelectionLanguage', 'XPath');
      XMLNode := XMLDocument.selectSingleNode(APath);
      XMLNode.text := AValue;
      XMLDocument.save(AFileName);
    end;
  except
    MsgBox('An error occured!' + #13#10 + GetExceptionMessage, mbError, MB_OK);
  end;
end;

procedure InitializeWizard;
var  
  CustomPage: TWizardPage;
begin
  CustomPage := CreateCustomPage(wpWelcome, 'Custom Page', 
    'Enter the new value that will be saved into the XML file');
  CustomPageID := CustomPage.ID;
  CustomEdit := TEdit.Create(WizardForm);
  CustomEdit.Parent := CustomPage.Surface;
end;

procedure CurPageChanged(CurPageID: Integer);
begin
  if CurPageID = CustomPageID then
    CustomEdit.Text := LoadValueFromXML('C:\Setup.xml', '//Setup/FirstNode');
end;

function NextButtonClick(CurPageID: Integer): Boolean;
begin
  Result := True;
  if CurPageID = CustomPageID then
    SaveValueToXML('C:\Setup.xml', '//Setup/FirstNode', CustomEdit.Text);
end;

Here is the XML file used in the script:

<?xml version="1.0" encoding="UTF-8"?>
<Setup>
    <FirstNode>First node value!</FirstNode>
    <SecondNode>Second node value!</SecondNode>
</Setup>