Inno Setup - XML editing XPath request fails with “NIL Interface Exception at runtime”

亡梦爱人 提交于 2020-08-25 07:27:08

问题


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?


回答1:


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.



来源:https://stackoverflow.com/questions/45716413/inno-setup-xml-editing-xpath-request-fails-with-nil-interface-exception-at-ru

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!