Delphi中如何用TXMLDocument处理EOutOfMemory解析超大XML?
- 内容介绍
- 文章标签
- 相关推荐
本文共计486个文字,预计阅读时间需要2分钟。
我有一个庞大的XML文件需要解析代码,例如下面的示例。问题似乎是,即使用childnode(IXMLNode)的内存也不会被释放。一旦父TXMLDocument被取消激活(Active :=false)或释放,似乎只有childnode会被释放。
我有一个大的 XML文件来解析代码,如下面的示例.问题似乎是,即使childnode超出范围,分配给childnode(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; 我知道你说你不想要一个单独的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;
我们用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;
Note: Any code is released into the public domain. No attribution required.
本文共计486个文字,预计阅读时间需要2分钟。
我有一个庞大的XML文件需要解析代码,例如下面的示例。问题似乎是,即使用childnode(IXMLNode)的内存也不会被释放。一旦父TXMLDocument被取消激活(Active :=false)或释放,似乎只有childnode会被释放。
我有一个大的 XML文件来解析代码,如下面的示例.问题似乎是,即使childnode超出范围,分配给childnode(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; 我知道你说你不想要一个单独的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;
我们用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;
Note: Any code is released into the public domain. No attribution required.

