我有一个很大的 XML 文件需要在代码中进行解析,如下例所示。问题似乎是分配给子节点 (IXMLNode) 的内存没有释放,即使子节点超出范围也是如此。内存似乎仅在父 TXMLDocument 停用(Active:= false)或释放后才被释放。因此,我的代码在加载 xml 文档后开始时大约为 380Mb,后来膨胀到 2Gb,然后就结束了。将 childnode 设置为 nil 对内存使用没有影响。
我的问题是如何显式释放分配给 IXMLNode 接口的内存。我不愿意使用不同的 XML 对象,并且我想我已经尝试了几乎所有方法来控制节点接口的范围。
var
childnode: IXMLNode;
for i:=0 to rootnode.ChildNodes.Count-1 do begin
childnode:=rootnode.ChildNodes[i];
...
childnode:=nil;
end;
Run Code Online (Sandbox Code Playgroud)
我知道您说过您不想要一个单独的 XML 库;但也许其他人会喜欢示例代码:
var
sax: SAXXMLReader60;
stm: IStream;
begin
//Get a stream around our large file
stm := TStreamAdapter.Create(TFileStream.Create('USGovBudgetLineItems2008.xml', fmOpenRead ));
sax := CoSAXXMLReader60.Create;
sax.contentHandler := TVBSAXContentHandler.Create;
sax.parse(stm);
end;
Run Code Online (Sandbox Code Playgroud)
我们用我们的对象监听事件SAXContentHandler。
对于IDispatch您可以返回的所有事件E_NOTIMPL(msxml 甚至不调用它们)。
其余的你可以插入你想要的任何代码:
TVBSAXContentHandler = class(TInterfacedObject, IVBSAXContentHandler)
protected
{ IDispatch }
function GetTypeInfoCount(out Count: Integer): HResult; stdcall;
function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
function GetIDsOfNames(const IID: TGUID; Names: Pointer; NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
public
{ IVBSAXContentHandler }
procedure Set_documentLocator(const Param1: IVBSAXLocator); safecall;
procedure startDocument; safecall;
procedure endDocument; safecall;
procedure startPrefixMapping(var strPrefix: WideString; var strURI: WideString); safecall;
procedure endPrefixMapping(var strPrefix: WideString); safecall;
procedure startElement(var strNamespaceURI: WideString; var strLocalName: WideString;
var strQName: WideString; const oAttributes: IVBSAXAttributes); safecall;
procedure endElement(var strNamespaceURI: WideString; var strLocalName: WideString;
var strQName: WideString); safecall;
procedure characters(var strChars: WideString); safecall;
procedure ignorableWhitespace(var strChars: WideString); safecall;
procedure processingInstruction(var strTarget: WideString; var strData: WideString); safecall;
procedure skippedEntity(var strName: WideString); safecall;
// property documentLocator: IVBSAXLocator write Set_documentLocator;
end;
Run Code Online (Sandbox Code Playgroud)
注意:任何代码都会发布到公共领域。无需归属。
| 归档时间: |
|
| 查看次数: |
2281 次 |
| 最近记录: |