Inno Setup – XML editing XPath request fails with "NIL Interface Exception at runtime"

I’ve created a Inno Setup script for my app in which I’m trying to edit some XML configuration in the post install step (mostly connection strings). I have some pretty simple XPath request but I have a runtime exception when using selectSingleNode whereas getElementsByTagName works perfectly fine.

This code does not work. It throws "NIL Interface Exception at runtime".

procedure ReadValueFromXML(const AFileName, APath, AAttribute, AValue: string); var   XMLNode: Variant;   XMLDocument: Variant;   begin   XMLDocument := CreateOleObject('Msxml2.DOMDocument');   try     XMLDocument.async := False;     LOG(AFileName);     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);       LOG(XMLNode.getAttribute(AAttribute));       XMLDocument.save(AFileName);     end;   except     MsgBox('An error occured!' + #13#10 + GetExceptionMessage, mbError, MB_OK);   end; end; 

So far I’ve been trying to call it with several XPath request :

  • ReadValueFromXML(FilePath, '//Phedre', 'ConnectionString', PhedreCon.Text)
  • ReadValueFromXML(FilePath, '//PhedreConfiguration/Databases/Phedre', 'ConnectionString', PhedreCon.Text)
  • ReadValueFromXML(FilePath, '/PhedreConfiguration/Databases/Phedre', 'ConnectionString', PhedreCon.Text)

This, on the other hand, works fine (logs the connection strings) :

procedure ReadValueFromXML(const AFileName, APath, AAttribute, AValue: string); var   XMLNode: Variant;   XMLDocument: Variant;   Index: Integer;   begin   XMLDocument := CreateOleObject('Msxml2.DOMDocument');   try     XMLDocument.async := False;     LOG('Lecture du fichier ' + AFileName);     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.getElementsByTagName(APath);       for Index := 0 to XMLNode.length - 1 do       begin         LOG(XMLNode.item[Index].getAttribute(AAttribute));       end;     end;   except     MsgBox('An error occured!' + #13#10 + GetExceptionMessage, mbError, MB_OK);   end; end; 

the XML used is :

<PhedreConfiguration d1p1:schemaLocation="http://ns.edf.fr/phedre/config/v1.0 ./PhedreConfiguration.xsd" xmlns:d1p1="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://ns.edf.fr/phedre/config/v1.0">     <Databases>         <Phedre ConnectionString="Server=****; Port=3306; Database=****; Uid=****; Pwd=****;"/>         <Arche ConnectionString="Server=****; Port=3306; Database=****;  Uid=****; Pwd=****;"/>     </Databases>     [...] </PhedreConfiguration> 

So my question is: Is there any kind of syntax error in my XPath request? Why would getElementsByTagName('Phedre') work and selectSingleNode('//Phedre') won’t?

Add Comment
1 Answer(s)

Thanks to @choroba’s comment I found the solution. Namespace needs to be specified in XPath request when used.

The solution was to set selection namespace in the procedure:

XMLDocument.setProperty(   'SelectionNamespaces', 'xmlns:ns=''http://ns.edf.fr/phedre/config/v1.0'''); 

And call it with //ns:Phedre.

Add Comment

Your Answer

By posting your answer, you agree to the privacy policy and terms of service.