我在IXMLDOMDocument2中加载文件时遇到了一个奇怪的bug。如果文件名包含%并将parseError设置为:系统找不到指定的资源。该文件存在,当从其名称中删除%时,它工作正常。有没有办法加载名称中包含%的XML文件?
IXMLDOMDocument2
%
parseError
tkqqtvp11#
IXMLDOMDocument.load()的文档说明xmlSource源参数接受以下值之一:
IXMLDOMDocument.load()
xmlSource
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()方法的内容应该小心,有几种选择。
Test%.xml
Test%21.xml
Test!.xml
Test%4A.xml
TestJ.xml
这很简单,你可以使用System.NetEncoding单元中的TNetEncoding.URL:
System.NetEncoding
TNetEncoding.URL
var FileName := 'C:\test%21.xml'; var Doc := CoDOMDocument.Create; Doc.load(TNetEncoding.URL.Encode(FileName));
使用TFileStream(或System.IOUtils单元中的TFile.OpenRead())打开一个文件,并将其 Package 在System.CLasses单元中的TStreamAdapter中,System.CLasses单元实现了Winapi.ActiveX单元中声明的IStream接口。
TFileStream
System.IOUtils
TFile.OpenRead()
System.CLasses
TStreamAdapter
Winapi.ActiveX
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()方法。
IXMLDOMDOcument.loadXML()
TFile.ReadAllText()
var FileName := 'C:\test%21.xml'; var Doc := CoDOMDocument.Create; Doc.loadXML(TFile.ReadAllText(FileName));
我不推荐使用此选项加载XML,因为它会将文件的全部内容加载到内存中。
1条答案
按热度按时间tkqqtvp11#
IXMLDOMDocument.load()
的文档说明xmlSource
源参数接受以下值之一: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
:将
IStream
作为参数传递:使用
TFileStream
(或System.IOUtils
单元中的TFile.OpenRead()
)打开一个文件,并将其 Package 在System.CLasses
单元中的TStreamAdapter
中,System.CLasses
单元实现了Winapi.ActiveX
单元中声明的IStream
接口。改用
loadXML()
方法:有一个
IXMLDOMDOcument.loadXML()
方法可以从字符串加载XML内容,可以使用TFile.ReadAllText()
(单位System.IOUtils
)读取文件的内容,并将其传递给loadXML()
方法。我不推荐使用此选项加载XML,因为它会将文件的全部内容加载到内存中。