问题
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