Inno Setup - XML 编辑 XPath 请求失败 "NIL Interface Exception at runtime"
Inno Setup - XML editing XPath request fails with "NIL Interface Exception at runtime"
我为我的应用程序创建了一个 Inno Setup 脚本,我试图在其中编辑 post 安装步骤中的一些 XML 配置(主要是连接字符串)。我有一些非常简单的 XPath 请求,但是在使用 selectSingleNode
时出现运行时异常,而 getElementsByTagName
工作得很好。
此代码无效。它抛出 "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;
到目前为止,我一直在尝试使用多个 XPath 请求来调用它:
ReadValueFromXML(FilePath, '//Phedre', 'ConnectionString', PhedreCon.Text)
ReadValueFromXML(FilePath, '//PhedreConfiguration/Databases/Phedre', 'ConnectionString', PhedreCon.Text)
ReadValueFromXML(FilePath, '/PhedreConfiguration/Databases/Phedre', 'ConnectionString', PhedreCon.Text)
另一方面,这工作正常(记录连接字符串):
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;
使用的XML是:
<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>
所以我的问题是:我的 XPath 请求中是否存在任何类型的语法错误?为什么 getElementsByTagName('Phedre')
有效而 selectSingleNode('//Phedre')
无效?
感谢@choroba 的评论,我找到了解决方案。使用时需要在XPath请求中指定Namespace。
解决方案是在过程中设置选择命名空间:
XMLDocument.setProperty(
'SelectionNamespaces', 'xmlns:ns=''http://ns.edf.fr/phedre/config/v1.0''');
并用//ns:Phedre
调用它。
我为我的应用程序创建了一个 Inno Setup 脚本,我试图在其中编辑 post 安装步骤中的一些 XML 配置(主要是连接字符串)。我有一些非常简单的 XPath 请求,但是在使用 selectSingleNode
时出现运行时异常,而 getElementsByTagName
工作得很好。
此代码无效。它抛出 "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;
到目前为止,我一直在尝试使用多个 XPath 请求来调用它:
ReadValueFromXML(FilePath, '//Phedre', 'ConnectionString', PhedreCon.Text)
ReadValueFromXML(FilePath, '//PhedreConfiguration/Databases/Phedre', 'ConnectionString', PhedreCon.Text)
ReadValueFromXML(FilePath, '/PhedreConfiguration/Databases/Phedre', 'ConnectionString', PhedreCon.Text)
另一方面,这工作正常(记录连接字符串):
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;
使用的XML是:
<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>
所以我的问题是:我的 XPath 请求中是否存在任何类型的语法错误?为什么 getElementsByTagName('Phedre')
有效而 selectSingleNode('//Phedre')
无效?
感谢@choroba 的评论,我找到了解决方案。使用时需要在XPath请求中指定Namespace。
解决方案是在过程中设置选择命名空间:
XMLDocument.setProperty(
'SelectionNamespaces', 'xmlns:ns=''http://ns.edf.fr/phedre/config/v1.0''');
并用//ns:Phedre
调用它。