当前位置: 首页 > news >正文

Delphi XML解析速度大比拼

最近闲来无事,想比较下在win系统中,MSXML、NativeXML和OXML三种组件解析XML的速度。

先说结果:
解析10万个,最深7层,每层最多5个结点的xml文件,在我电脑(U7 265K 16G内存)下,

| 解析器 | 用时(毫秒) | 相对速度 |
| --------- | ------ | -------- |
| OXml | 182 | 1.0x(基准) |
| MSXML | 411 | 约 2.26 倍 |
| NativeXml | 1203 | 约 6.61 倍 |

代码如下:
unit Main;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
Vcl.StdCtrls, Xml.XMLDoc, Xml.XMLIntf, NativeXml, Vcl.ExtCtrls, Vcl.ComCtrls,
IOUtils,OXmlUtils,OXmlPDOM;

type
TForm10 = class(TForm)
BtnCreateXML: TButton;
BtnUseMSXML: TButton;
BtnUseNativeXml: TButton;
XMLmemo: TMemo;
Panel1: TPanel;
MsgMemo: TMemo;
progressBar: TProgressBar;
lblStatus: TLabel;
BtnUseOXML: TButton;
procedure BtnCreateXMLClick(Sender: TObject);
procedure BtnUseMSXMLClick(Sender: TObject);
procedure BtnUseNativeXmlClick(Sender: TObject);
procedure BtnUseOXMLClick(Sender: TObject);
private
function CreateXML(NodeCount: integer): boolean;
{ Private declarations }
public
{ Public declarations }
end;

var
Form10: TForm10;
FilePath: string;

implementation
uses system.Diagnostics;

procedure TForm10.BtnCreateXMLClick(Sender: TObject);
begin
CreateXML(100000);
XMLmemo.Lines.LoadFromFile(FilePath,TEncoding.UTF8);
end;

procedure TForm10.BtnUseMSXMLClick(Sender: TObject);
var
XMLDoc:xml.XMLDoc.TXMLDocument;
RootNode: IXMLNode;
i: Integer;
procedure GetChildNods(Node: IXMLNode);
var
Child: IXMLNode;
tt:string;
NodeValue: string;
begin
if Node.HasChildNodes then
begin
for var J := 0 to Node.ChildNodes.Count - 1 do
begin
Child := Node.ChildNodes[J];
tt:= VarToStr(Child.Attributes['ID']);
if Child.NodeType=xml.XMLIntf.ntText then
NodeValue :=Child.Text// VarToStr(Child.NodeValue);
else if Child.NodeType=xml.XMLIntf.ntElement then
begin
inc(i);
GetChildNods(Child);
end;
end;
end;
end;

begin
XMLDoc := xml.XMLDoc.TXMLDocument.Create(self);
var Stopwatch := TStopwatch.StartNew;
try
XMLDoc.LoadFromFile(FilePath);
XMLDoc.Active := True;
XMLDoc.Encoding:='GBK';
RootNode := XMLDoc.DocumentElement;
i := 0;
GetChildNods(RootNode);
Stopwatch.Stop;
finally
XMLDoc.Active := False;
XMLDoc.Free;
MsgMemo.Lines.Add('共读取了' + i.ToString + '个节点。');
MsgMemo.Lines.Add('用时' + Stopwatch.ElapsedMilliseconds.ToString);
end;
end;

procedure TForm10.BtnUseNativeXmlClick(Sender: TObject);
var
XML: TNativeXml;
RootNode: TsdElement;
i: Integer;

procedure GetChildNodes(Node: NativeXml.TXMLNode);
var
NodeValue: string;
Child: NativeXml.TXmlNode;
begin
for var J := 0 to Node.NodeCount - 1 do
begin
Child := Node.Nodes[J];
if Child.ElementType = xeCharData then
NodeValue := Child.Value
else
if Child.ElementType=xeElement then
begin
Inc(i);
GetChildNodes(Child);
end;
end;
end;

begin
XML := TNativeXml.Create(nil);
var Stopwatch := TStopwatch.StartNew;
try
i := 0;
XML.ExternalEncoding:=seAnsi;
XML.LoadFromFile(FilePath);
RootNode := XML.Root;
GetChildNodes(RootNode);
finally
XML.Free;
MsgMemo.Lines.Add('共读取了' + i.ToString + '个节点。');
MsgMemo.Lines.Add('用时' + Stopwatch.ElapsedMilliseconds.ToString);
end;
end;

procedure TForm10.BtnUseOXMLClick(Sender: TObject);
var
XML: IXMLDocument;
RootNode: PXmlNode;
i: Integer;

procedure GetChildNodes(Node: PXmlNode);
varNodeValue: string;Child: PXmlNode;
beginChild := Node.FirstChild;while Child <> nil dobegincase Child.NodeType ofntText, ntCData:NodeValue := Child.Text;  // 读取文本值ntElement:beginInc(i);GetChildNodes(Child);end;// 其他节点类型忽略end;Child := Child.NextSibling;end;
end;

begin
// 创建 XML 文档对象(使用接口自动释放)
XML := CreateXMLDoc;
var Stopwatch := TStopwatch.StartNew;
try
i := 0;
// OXml 加载文件,默认编码自动检测,如果需要 ANSI,可以设置,但 OXml 的 LoadFromFile 支持指定编码参数
// 这里我们简单使用 LoadFromFile,如果需要 ANSI 强制,可以传入 TEncoding.Default
XML.ReaderSettings.ErrorHandling := ehSilent;
if not XML.LoadFromFile(FilePath,TEncoding.UTF8) then
begin
MsgMemo.Lines.Add('加载 XML 文件失败。');
Exit;
end;

  RootNode := XML.DocumentElement;if RootNode = nil thenbeginMsgMemo.Lines.Add('没有根元素。');Exit;end;// 调用递归遍历(根节点本身不计入 i)GetChildNodes(RootNode);
finally// XML 是接口,自动释放,无需手动 FreeMsgMemo.Lines.Add('共读取了' + i.ToString + '个节点。');MsgMemo.Lines.Add('用时' + Stopwatch.ElapsedMilliseconds.ToString);
end;

end;

function TForm10.CreateXML(NodeCount: integer): boolean;
var
XMLDoc: xml.XMLDoc.TXMLDocument;
RootNode, DataNode, ItemNode: IXMLNode;
i: Integer;

function CreateChildNodes(Node: IXMLNode; Level: Integer): Boolean;
var
Child: IXMLNode;
CountOnLevel:Byte;
begin
if Level=1 then
CountOnLevel:=10
else CountOnLevel:=5;

for var j := 1 to CountOnLevel do
begininc(i);if i > NodeCount thenExit;Child := Node.AddChild('第' + Level.ToString + '层' + j.ToString + '项');Child.Attributes['ID'] := i;Child.Attributes['Name'] := 'Item_' + IntToStr(i);Child.Text := '测试文本' + IntToStr(i);// 每1000个节点更新一次进度,提升性能if i mod 1000 = 0 thenbeginprogressBar.Position := Round(i / NodeCount * 100);lblStatus.Caption := '正在生成XML文件...(' + IntToStr(i) + '/' + IntToStr(NodeCount) + ')';Application.ProcessMessages;end;if Level < 7 thenCreateChildNodes(Child, Level + 1);
end;

end;

begin
result := False;
progressBar.Position := 0;
if FileExists(FilePath) then
begin
try
DeleteFile(PChar(FilePath));
except
MsgMemo.Lines.Add('⚠ 提示:删除旧测试文件失败,将尝试覆盖');
end;
end;

try
XMLDoc := xml.XMLDoc.TXMLDocument.Create(Self);
try
XMLDoc.Active := True; // Delphi 12必须显式激活
XMLDoc.Options := [doNodeAutoIndent];
XMLDoc.Encoding := 'UTF-8';
XMLDoc.Version := '1.0';

  if not Assigned(XMLDoc.DocumentElement) thenbeginRootNode := XMLDoc.CreateNode('DataRoot');XMLDoc.DocumentElement := RootNode;endelsebeginRootNode := XMLDoc.DocumentElement;if RootNode.NodeName <> 'DataRoot' thenbeginRootNode := XMLDoc.CreateNode('DataRoot');XMLDoc.DocumentElement := RootNode;end;end;lblStatus.Caption := '正在生成XML文件...(0/' + IntToStr(NodeCount) + ')';Application.ProcessMessages;// 递归添加测试节点(优化性能)CreateChildNodes(RootNode, 1);// 强制更新最后进度progressBar.Position := 100;lblStatus.Caption := '正在保存XML文件...';Application.ProcessMessages;// 保存文件(使用UTF-8编码)XMLDoc.SaveToFile(FilePath);// 验证文件是否生成成功if FileExists(FilePath) thenbeginResult := True;lblStatus.Caption := 'XML文件生成完成: ' + FilePath;MsgMemo.Lines.Add('✓ 生成测试XML文件成功,包含 ' + IntToStr(NodeCount) + ' 个节点');MsgMemo.Lines.Add(' 文件路径: ' + FilePath);MsgMemo.Lines.Add(' 文件大小: ' + FormatFloat('#,##0 KB', tfile.getsize(FilePath) / 1024));endelsebeginMsgMemo.Lines.Add('✗ 生成XML文件失败:文件未创建');end;
finallyXMLDoc.Active := False;XMLDoc.Free;
end;
Result := True;

except
on E: Exception do
begin
MsgMemo.Lines.Add('✗ 生成XML失败: ' + E.Message);
MsgMemo.Lines.Add(' 错误类型: ' + E.ClassName);
MsgMemo.Lines.Add(' 建议:检查临时目录权限 - ' + TPath.GetTempPath);
end;
end;
end;

initialization
FilePath := TPath.Combine(TPath.GetAppPath, '测试XML.xml');

finalization

end.

http://www.jsqmd.com/news/385187/

相关文章:

  • AI元人文:制造、部署应用与养护AI(岐式参考)
  • 完整教程:数据结构与算法篇-排序算法-统一视角
  • 题解:洛谷 P10372 [AHOI2024 初中组 / 科大国创杯初中组 2024] 家庭作业
  • 题解:洛谷 P9973 [THUPC 2024 初赛] 你说得对,但是 AIGC
  • 构造喵喵题收录
  • 2026年2月热门排阻厂商有哪些?速来掌握,合金检测电阻/低温漂高精密电阻/采样电阻/电阻,排阻源头厂家哪个好 - 品牌推荐师
  • 2026年荣誉代理固态电容公司有哪些?排行信息来了,业展代理电流采样/低温漂高精密电阻/宝宫代理,荣誉代理品牌联系方式 - 品牌推荐师
  • 激光切管机怎么选?2026十大品牌技术实力巅峰对决 - 匠言榜单
  • 互联网大厂Java面试:从Spring MVC到微服务架构的技术问答
  • 2026耐高温电阻市场观察:这些公司值得关注,低TCR高精密电阻/精密电阻/业展代理/低温漂高精密电阻,电阻公司推荐榜 - 品牌推荐师
  • 从性能出发,探讨国内耐脉冲电阻的优选品牌,THUNDER盛雷城代理/3PPM高精密电阻,电阻供应厂家哪家靠谱 - 品牌推荐师
  • 细胞群体动力学仿真软件:NetLogo_(5).NetLogo编程语言介绍
  • C#并发编程新宠:Channel通道全解析(第一部分)
  • ASP.NET Core Blazor简介和快速入门一(基础篇)
  • 细胞群体动力学仿真软件:NetLogo_(5).细胞状态与环境交互
  • GTK4图片查看器项目实战:从零构建专业图像应用
  • 提示工程架构师经验谈:模式的5个必用技巧+反模式的4个必避坑
  • IntelliJ IDEA Maven 工具栏消失怎么办?完整教程:从入门到实战部署
  • Flourish(Line, bar and pie charts 模板)使用可视化操作方法
  • 细胞群体动力学仿真软件:NetLogo_(3).细胞自动机理论基础
  • 细胞群体动力学仿真软件:NetLogo_(4).基本模型构建
  • DeepSeek悄咪咪放大招:上下文暴涨至1M,知识库直抵2025年5月,收藏这份AI技术进化秘籍!
  • 细胞群体动力学仿真软件:NetLogo_(3).NetLogo用户界面详解
  • 细胞群体动力学仿真软件:NetLogo_(4).NetLogo中的细胞模型创建
  • Springboot3+vue3的网上购物商城商品销售平台
  • Springboot3+vue3语言的设备故障报修管理系统
  • 细胞群体动力学仿真软件:NetLogo_(2).NetLogo界面与基本操作
  • 细胞群体动力学仿真软件:NetLogo_(2).安装与配置NetLogo
  • 大数据运维与管理专业学习数据分析的必要性
  • 【Docker进阶篇】告别OOM Kill!Java容器化内存与CPU限制实战指南