versiones edition descargar community borland delphi delphi-2010
http://blog.karelia.pro/teran/files/2012/03/XMLTest.zip

edition - ¿Cuál es el analizador XML más rápido disponible para Delphi?



delphi versiones (5)

Tenemos cadenas de XML razonablemente grandes que actualmente analizamos utilizando MSXML2

¡Acabo de intentar usar MSXML6 esperando una mejora de velocidad y no tengo nada!

Actualmente creamos una gran cantidad de documentos DOM y creo que puede haber un poco de sobrecarga en la interacción constante con el dll MSXML2 / 6

¿Alguien sabe de un componente XML mejor / más rápido para Delphi?

Si alguien puede sugerir una alternativa, y es más rápida, buscaríamos integrarla, pero eso sería mucho trabajo, por lo que esperamos que la estructura no sea muy diferente a la utilizada por MSXML.

Estamos usando Delphi 2010

Pablo


Algún día escribí un conjunto de pruebas XML muy simple. Sirve MSXML (D7 MSXML3?), Omni XML (poco antiguo) y Jedi XML (último estable).

Resultados de prueba para archivo de 1,52 MB:

Tiempo de carga del archivo XML MSXML: 240,20 [ms]

Selecciones de nodos XML MSXML: 1,09 [s]

Tiempo de carga de archivos XML OmniXML: 2,25 [s]

Selecciones de nodos XML OmniXML: 1,22 [s]

Tiempo de carga de archivos XML JclSimpleXML: 2,11 [s]

y violación de acceso para selecciones de nodo JclSimpleXML: |

Desafortunadamente, en realidad no tengo mucho tiempo para corregir el AV anterior, pero las hechiceras se encuentran a continuación ...

fmuMain.pas

program XmlEngines; uses FastMM4, Forms, fmuMain in ''fmuMain.pas'' {fmMain}, uXmlEngines in ''uXmlEngines.pas'', ifcXmlEngine in ''ifcXmlEngine.pas''; {$R *.res} begin Application.Initialize; Application.Title := ''XML Engine Tester''; Application.CreateForm(TfmMain, fmMain); Application.Run; end.

fmuMain.pas

unit fmuMain; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, xmldom, XMLIntf, msxmldom, XMLDoc, // ifcXmlEngine, StdCtrls; type TfmMain = class(TForm) mmoDebug: TMemo; dlgOpen: TOpenDialog; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure mmoDebugClick(Sender: TObject); private fXmlEngines: TInterfaceList; function Get_Engine(const aIx: Integer): IXmlEngine; protected property XmlEngine[const aIx: Integer]: IXmlEngine read Get_Engine; procedure Debug(const aInfo: string); // inline public procedure RegisterXmlEngine(const aEngine: IXmlEngine); end; var fmMain: TfmMain; implementation {$R *.dfm} uses uXmlEngines, TZTools; { TForm1 } function TfmMain.Get_Engine(const aIx: Integer): IXmlEngine; begin Result:= nil; Supports(fXmlEngines[aIx], IXmlEngine, Result) end; procedure TfmMain.RegisterXmlEngine(const aEngine: IXmlEngine); var Ix: Integer; begin if aEngine = nil then Exit; // WARRNING: program flow disorder for Ix:= 0 to Pred(fXmlEngines.Count) do if XmlEngine[Ix] = aEngine then Exit; // WARRNING: program flow disorder fXmlEngines.Add(aEngine) end; procedure TfmMain.FormCreate(Sender: TObject); begin fXmlEngines:= TInterfaceList.Create(); dlgOpen.InitialDir:= ExtractFileDir(ParamStr(0)); RegisterXmlEngine(TMsxmlEngine.Create(Self)); RegisterXmlEngine(TOmniXmlEngine.Create()); RegisterXmlEngine(TJediXmlEngine.Create()); end; procedure TfmMain.mmoDebugClick(Sender: TObject); procedure TestEngines(const aFilename: TFileName); procedure TestEngine(const aEngine: IXmlEngine); var PerfCheck: TPerfCheck; Ix: Integer; begin PerfCheck := TPerfCheck.Create(); try PerfCheck.Init(True); PerfCheck.Start(); aEngine.Load(aFilename); PerfCheck.Pause(); Debug(Format( ''XML file loading time %s: %s'', [aEngine.Get_ID(), PerfCheck.TimeStr()])); if aEngine.Get_ValidNode() then begin PerfCheck.Start(); for Ix:= 0 to 999999 do if aEngine.Get_ChildsCount() > 0 then begin aEngine.SelectChild(Ix mod aEngine.Get_ChildsCount()); end else aEngine.SelectRootNode(); PerfCheck.Pause(); Debug(Format( ''XML nodes selections %s: %s'', [aEngine.Get_ID(), PerfCheck.TimeStr()])); end finally PerfCheck.Free(); end end; var Ix: Integer; begin Debug(aFilename); for Ix:= 0 to Pred(fXmlEngines.Count) do TestEngine(XmlEngine[Ix]) end; var CursorBckp: TCursor; begin if dlgOpen.Execute() then begin CursorBckp:= Cursor; Self.Cursor:= crHourGlass; mmoDebug.Cursor:= crHourGlass; try TestEngines(dlgOpen.FileName) finally Self.Cursor:= CursorBckp; mmoDebug.Cursor:= CursorBckp; end end end; procedure TfmMain.Debug(const aInfo: string); begin mmoDebug.Lines.Add(aInfo) end; procedure TfmMain.FormDestroy(Sender: TObject); begin fXmlEngines.Free() end; end.

ifcXmlEngine.pas

unit ifcXmlEngine; interface uses SysUtils; type TFileName = SysUtils.TFileName; IXmlEngine = interface [''{AF77333B-9873-4FDE-A3B1-260C7A4D3357}''] procedure Load(const aFilename: TFileName); procedure SelectRootNode(); procedure SelectChild(const aIndex: Integer); procedure SelectParent(); // function Get_ID(): string; function Get_ValidNode(): Boolean; function Get_ChildsCount(): Integer; function Get_HaveParent(): Boolean; //function Get_NodeName(): Boolean; end; implementation end.

uXmlEngines.pas

unit uXmlEngines; interface uses Classes, // XMLDoc, XMLIntf, OmniXml, JclSimpleXml, // ifcXmlEngine; type TMsxmlEngine = class(TInterfacedObject, IXmlEngine) private fXmlDoc: XMLDoc.TXMLDocument; fNode: XMLIntf.IXMLNode; protected public constructor Create(const aOwner: TComponent); destructor Destroy; override; procedure Load(const aFilename: TFileName); procedure SelectRootNode(); procedure SelectChild(const aIndex: Integer); procedure SelectParent(); // function Get_ID(): string; function Get_ValidNode(): Boolean; function Get_ChildsCount(): Integer; function Get_HaveParent(): Boolean; //function Get_NodeName(): Boolean; end; TOmniXmlEngine = class(TInterfacedObject, IXmlEngine) private fXmlDoc: OmniXml.IXmlDocument; fNode: OmniXml.IXMLNode; protected public constructor Create; destructor Destroy; override; procedure Load(const aFilename: TFileName); procedure SelectRootNode(); procedure SelectChild(const aIndex: Integer); procedure SelectParent(); // function Get_ID(): string; function Get_ValidNode(): Boolean; function Get_ChildsCount(): Integer; function Get_HaveParent(): Boolean; //function Get_NodeName(): Boolean; end; TJediXmlEngine = class(TInterfacedObject, IXmlEngine) private fXmlDoc: TJclSimpleXML; fNode: TJclSimpleXMLElem; protected public constructor Create(); destructor Destroy(); override; procedure Load(const aFilename: TFileName); procedure SelectRootNode(); procedure SelectChild(const aIndex: Integer); procedure SelectParent(); // function Get_ID(): string; function Get_ValidNode(): Boolean; function Get_ChildsCount(): Integer; function Get_HaveParent(): Boolean; //function Get_NodeName(): Boolean; end; implementation uses SysUtils; { TMsxmlEngine } constructor TMsxmlEngine.Create(const aOwner: TComponent); begin if aOwner = nil then raise Exception.Create(''TMsxmlEngine.Create() -> invalid owner''); inherited Create(); fXmlDoc:= XmlDoc.TXmlDocument.Create(aOwner); fXmlDoc.ParseOptions:= [poPreserveWhiteSpace] end; destructor TMsxmlEngine.Destroy; begin fXmlDoc.Free(); inherited Destroy() end; function TMsxmlEngine.Get_ChildsCount: Integer; begin Result:= fNode.ChildNodes.Count end; function TMsxmlEngine.Get_HaveParent: Boolean; begin Result:= fNode.ParentNode <> nil end; function TMsxmlEngine.Get_ID: string; begin Result:= ''MSXML'' end; //function TMsxmlEngine.Get_NodeName: Boolean; //begin // Result:= fNode.Text //end; function TMsxmlEngine.Get_ValidNode: Boolean; begin Result:= fNode <> nil end; procedure TMsxmlEngine.Load(const aFilename: TFileName); begin fXmlDoc.LoadFromFile(aFilename); SelectRootNode() end; procedure TMsxmlEngine.SelectChild(const aIndex: Integer); begin fNode:= fNode.ChildNodes.Get(aIndex) end; procedure TMsxmlEngine.SelectParent; begin fNode:= fNode.ParentNode end; procedure TMsxmlEngine.SelectRootNode; begin fNode:= fXmlDoc.DocumentElement end; { TOmniXmlEngine } constructor TOmniXmlEngine.Create; begin inherited Create(); fXmlDoc:= OmniXml.TXMLDocument.Create(); fXmlDoc.PreserveWhiteSpace:= true end; destructor TOmniXmlEngine.Destroy; begin fXmlDoc:= nil; inherited Destroy() end; function TOmniXmlEngine.Get_ChildsCount: Integer; begin Result:= fNode.ChildNodes.Length end; function TOmniXmlEngine.Get_HaveParent: Boolean; begin Result:= fNode.ParentNode <> nil end; function TOmniXmlEngine.Get_ID: string; begin Result:= ''OmniXML'' end; //function TOmniXmlEngine.Get_NodeName: Boolean; //begin // Result:= fNode.NodeName //end; function TOmniXmlEngine.Get_ValidNode: Boolean; begin Result:= fNode <> nil end; procedure TOmniXmlEngine.Load(const aFilename: TFileName); begin fXmlDoc.Load(aFilename); SelectRootNode() end; procedure TOmniXmlEngine.SelectChild(const aIndex: Integer); begin fNode:= fNode.ChildNodes.Item[aIndex] end; procedure TOmniXmlEngine.SelectParent; begin fNode:= fNode.ParentNode end; procedure TOmniXmlEngine.SelectRootNode; begin fNode:= fXmlDoc.DocumentElement end; { TJediXmlEngine } constructor TJediXmlEngine.Create; begin inherited Create(); fXmlDoc:= TJclSimpleXML.Create(); end; destructor TJediXmlEngine.Destroy; begin fXmlDoc.Free(); inherited Destroy() end; function TJediXmlEngine.Get_ChildsCount: Integer; begin Result:= fNode.ChildsCount end; function TJediXmlEngine.Get_HaveParent: Boolean; begin Result:= fNode.Parent <> nil end; function TJediXmlEngine.Get_ID: string; begin Result:= ''JclSimpleXML''; end; //function TJediXmlEngine.Get_NodeName: Boolean; //begin // Result:= fNode.Name //end; function TJediXmlEngine.Get_ValidNode: Boolean; begin Result:= fNode <> nil end; procedure TJediXmlEngine.Load(const aFilename: TFileName); begin fXmlDoc.LoadFromFile(aFilename); SelectRootNode() end; procedure TJediXmlEngine.SelectChild(const aIndex: Integer); begin fNode:= fNode.Items[aIndex] end; procedure TJediXmlEngine.SelectParent; begin fNode:= fNode.Parent end; procedure TJediXmlEngine.SelectRootNode; begin fNode:= fXmlDoc.Root end; end.


Recientemente tuve un problema similar en el que el uso del analizador MSXML DOM resultó ser demasiado lento para la tarea dada. Tuve que analizar documentos bastante grandes> 1 MB y el consumo de memoria del analizador DOM era prohibitivo. Mi solución fue no utilizar un analizador DOM en absoluto, sino ir con el analizador MSXML SAX impulsado por eventos. Esto resultó ser mucho, mucho más rápido. Lamentablemente, el modelo de programación es totalmente diferente, pero dependiendo de la tarea, podría valer la pena. Craig Murphy ha publicado un excelente artículo sobre cómo usar el analizador MSXML SAX en Delphi : SAX, Delphi y Ex Em El


Sé que es una vieja pregunta, pero la gente puede encontrarla interesante:

Escribí una nueva biblioteca XML para Delphi (OXml): http://www.kluug.net/oxml.php

Cuenta con manejo directo de XML (lectura + escritura), analizador SAX, DOM y un analizador DOM secuencial. Una de las ventajas es que OXml admite Delphi 6-Delphi XE5, FPC / Lazarus y C ++ Builder en todas las plataformas (Win, MacOSX, Linux, iOS, Android).

OXml DOM está basado en registros / punteros y ofrece un mejor rendimiento que cualquier otra biblioteca XML:

La prueba de lectura devuelve el tiempo que el analizador necesita para leer un DOM XML personalizado desde un archivo (columna "cargar") y para escribir valores de nodo en una función ficticia constante (columna "navegar"). El archivo está codificado en UTF-8 y su tamaño es de aproximadamente 5,6 MB.

La prueba de escritura devuelve el tiempo que el analizador necesita para crear un DOM (columna "crear") y escribe este DOM en un archivo (columna "guardar"). El archivo está codificado en UTF-8 y su tamaño es de aproximadamente 11 MB.

+ El pobre rendimiento de escritura de OmniXML (original) fue el resultado del hecho de que OmniXML no usó el almacenamiento en búfer para escribir. Por lo tanto, escribir en un TFileStream fue muy lento. Actualicé OmniXML y agregué soporte de almacenamiento en búfer. Puede obtener el último código OmniXML del SVN.


himXML a himXML por himitsu .

Se lanza bajo la licencia MPL v1.1 , GPL v3.0 o LGPL v3.0 .

Tendrá que registrarse en el excelente sitio Delphi-Praxis (alemán) de Delphi para poder descargar:

Tiene un rendimiento muy impresionante y la distribución incluye demostraciones que demuestran eso. Lo utilicé con éxito en Delphi 2007, Delphi 2010 y Delphi XE.


Hace algún tiempo tuve que serializar el record al formato XML; por ejemplo:

TTest = record a : integer; b : real; end;

a

<Data> <a type="tkInteger">value</a> <b type="tkFloat">value</b> </Data>

Utilicé RTTI para navegar recursivamente por los campos de registro y almacenar valores en XML. He probado algunos XML Parsers. No necesitaba el modelo DOM para crear xml, pero lo necesitaba para cargarlo.

XML contenía aproximadamente 310k nodos (10-15MBytes); los resultados presentados en la tabla a continuación, hay 6 columnas con tiempo en segundos;
1 - tiempo para crear nodos y escribir valores
2 - SaveToFile ();
3 = 1 + 2
4 - LoadFromFile ();
5 - navegar a través de los nodos y leer valores
6 = 4 + 5

MSXML/Xerces/ADOM - son diferentes proveedores para TXMLDocument ( DOMVendor )
JanXML no funciona con Unicode; Solucioné algunos errores y guardé XML, pero cargar causa AV (o desbordamiento de pila, no recuerdo);
manual : significa escribir manualmente XML utilizando TStringStream .

Usé Delphi2010, Win7x32, CPU Q8200 / 2.3GHz, 4Gb de RAM.

actualización: Puede descargar el código fuente para esta prueba (registro de serialización a XML usando RTTI) aquí http://blog.karelia.pro/teran/files/2012/03/XMLTest.zip Todos los analizadores (Omni, Native, Jan) son incluido (ahora los nodos cuentan en XML es de aproximadamente 270k), lo siento, no hay comentarios en el código.