How to update multiple XML nodes in a loop with In

2019-06-13 04:08发布

问题:

I have to update a XML node that appears more than once, using Inno Setup.

How to do so?

For instance: I have to update <details> nodes (while I don't know how many nodes there are)

<server name="A">
    <details>id=5 gid=10</details>
</server>

<server name="B">
    <details>id=5 gid=10</details>
</server>

Thank you

回答1:

This is modified version of code by @TLama from an answer to How to read and write XML document node values?

In addition to his code, this version can update multiple nodes matching the XPath. The only difference is the call to selectNodes instead of selectSingleNode and the following for loop.

procedure SaveValueToXMLNodes(const AFileName, APath, AValue: string);
var
  XMLDocument: Variant;
  XMLNodeList: Variant;
  Index: Integer;
begin
  XMLDocument := CreateOleObject('Msxml2.DOMDocument.6.0');
  try
    XMLDocument.async := False;
    XMLDocument.load(AFileName);
    if XMLDocument.parseError.errorCode <> 0 then
    begin
      MsgBox('The XML file could not be parsed. ' +
        XMLDocument.parseError.reason, mbError, MB_OK)
    end
      else
    begin
      XMLDocument.setProperty('SelectionLanguage', 'XPath');
      XMLNodeList := XMLDocument.selectNodes(APath);
      for Index := 0 to XMLNodeList.length - 1 do
      begin
        XMLNodeList.item[Index].text := AValue;
      end;
      XMLDocument.save(AFileName);
    end;
  except
    MsgBox('An error occured!' + #13#10 + GetExceptionMessage, mbError, MB_OK);
  end;
end;

For an input file like:

<root>
    <server name="A">
        <details>id=5 gid=10</details>
    </server>
    <server name="B">
        <details>id=5 gid=10</details>
    </server>
</root>

you can use the code like:

SaveValueToXMLNodes('servers.xml', '/root/server/details', 'id=6 gid=11');

to get:

<root>
    <server name="A">
        <details>id=6 gid=11</details>
    </server>
    <server name="B">
        <details>id=6 gid=11</details>
    </server>
</root>