Delphi IXMLDOMDocument2无法加载文件名中包含%的XML文件

mo49yndu  于 2023-03-01  发布在  其他
关注(0)|答案(1)|浏览(114)

我在IXMLDOMDocument2中加载文件时遇到了一个奇怪的bug。如果文件名包含%并将parseError设置为:
系统找不到指定的资源。
该文件存在,当从其名称中删除%时,它工作正常。
有没有办法加载名称中包含%的XML文件?

tkqqtvp1

tkqqtvp11#

IXMLDOMDocument.load()的文档说明xmlSource源参数接受以下值之一:

  • 包含URL的字符串
  • IStream
  • ISequentialStream
  • IPersistStream
  • SAFEARRAY字节
  • 另一个IXMLDOMDocument示例

您正在尝试传递文件名,该方法将其视为URL(上面列表中的第一个选项)。URL中的字符%是为percent-encoding保留的。IXMLDOMDocument.load()方法正在尝试从作为参数传递的字符串中解码URL,这可能会导致文件名略有不同。棘手的是,当百分号后面没有一对十六进制数字时,这种情况不会发生,这意味着:Test%.xml将被解码为Test%.xml,但是Test%21.xml将被解码为Test!.xml,或者Test%4A.xml将被解码为TestJ.xml
传递给IXMLDOMDocument.load()方法的内容应该小心,有几种选择。

将文件名编码为URL

这很简单,你可以使用System.NetEncoding单元中的TNetEncoding.URL

var FileName := 'C:\test%21.xml';
var Doc := CoDOMDocument.Create;
Doc.load(TNetEncoding.URL.Encode(FileName));

IStream作为参数传递:

使用TFileStream(或System.IOUtils单元中的TFile.OpenRead())打开一个文件,并将其 Package 在System.CLasses单元中的TStreamAdapter中,System.CLasses单元实现了Winapi.ActiveX单元中声明的IStream接口。

var FileName := 'C:\test%21.xml';
var Stream: IStream := TStreamAdapter.Create(TFile.OpenRead(FileName), soOwned);
var Doc := CoDOMDocument.Create;
Doc.load(Stream);

改用loadXML()方法:

有一个IXMLDOMDOcument.loadXML()方法可以从字符串加载XML内容,可以使用TFile.ReadAllText()(单位System.IOUtils)读取文件的内容,并将其传递给loadXML()方法。

var FileName := 'C:\test%21.xml';
var Doc := CoDOMDocument.Create;
Doc.loadXML(TFile.ReadAllText(FileName));

我不推荐使用此选项加载XML,因为它会将文件的全部内容加载到内存中。

相关问题