2012-02-28 15 views
30

हमारे पास वर्तमान में बड़े एक्सएमएल स्ट्रिंग्स हैं जिन्हें हम वर्तमान में MSXML2डेल्फी के लिए सबसे तेज़ एक्सएमएल पार्सर उपलब्ध क्या है?

का उपयोग करके पार्स करते हैं। मैंने बस एमएसएक्सएमएल 6 का उपयोग करके गति सुधार की उम्मीद करनी है और कुछ भी नहीं मिला है!

वर्तमान में हम डोम दस्तावेज़ का एक बहुत बना सकते हैं और मुझे लगता है कि कुछ भूमि के ऊपर हो सकता है लगातार MSXML2/6 dll के साथ बातचीत में

किसी डेल्फी के लिए एक बेहतर/तेजी से एक्सएमएल घटक के पता है?

किसी को भी एक विकल्प के सुझाव दे सकते हैं, और यह तेजी से होता है, तो हम इसे एकीकृत करने के लिए विचार करेंगे, लेकिन वह बहुत काम हो सकता है, इसलिए उम्मीद है कि संरचना MSXML

द्वारा

प्रयुक्त होने वाले बोर्ड भी अलग नहीं होगा हम प्रयोग कर रहे हैं डेल्फी 2010

पॉल

+0

मुझे लगता है कि एक मॉड ने उन टिप्पणियों को हटा दिया है जिनमें मूल्यवान जानकारी है। क्यूं कर? –

+0

@ डेविड हेफरन, क्या अभी भी कोई उपयोगी जानकारी थी जो किसी भी उत्तर का हिस्सा नहीं थी? लंबी टिप्पणी धागे हमेशा हटाने के अधीन रहते हैं यदि समीक्षा मॉडरेटर मूल्य नहीं देखता है। –

+6

@MichaelMyers अच्छी तरह से मैंने सोचा कि उपयोगी जानकारी थी, लेकिन मुझे लगता है कि मोड असहमत थे। मैं वास्तव में नहीं देखता कि टिप्पणियों को हटाने से चीज़ें बेहतर होती हैं। अगर कोई वास्तव में इस प्रश्न में रूचि रखता है तो वे सब कुछ पढ़ने के लिए समय लगेगा। –

उत्तर

11

हाल ही में मुझे एक समान समस्या थी जहां एमएसएक्सएमएल डोम पार्सर का उपयोग करके दिए गए कार्य के लिए बहुत धीमी साबित हुई। मुझे बल्कि बड़े दस्तावेज़> 1 एमबी का विश्लेषण करना पड़ा और डोम पार्सर की स्मृति खपत निषिद्ध थी। मेरा समाधान एक डोम पार्सर का उपयोग नहीं करना था, लेकिन घटना संचालित एमएसएक्सएमएल एसएक्स पार्सर के साथ जाने के लिए। यह बहुत तेज, साबित हुआ। दुर्भाग्य से प्रोग्रामिंग मॉडल पूरी तरह से अलग है, लेकिन कार्य पर निर्भर है, यह इसके लायक हो सकता है। क्रेग मर्फी कैसे डेल्फी में MSXML SAX पार्सर का उपयोग करने पर एक उत्कृष्ट लेख प्रकाशित किया है: SAX, Delphi and Ex Em El

+1

इस तरह के काफी सफल परिवर्तन के मामले में और यदि सत्यापन की आवश्यकता नहीं है तो शायद [एक्सएमएललाइट] (http://msdn.microsoft.com/en-us/library/windows/desktop/ms752872%28v=vs.85%29। एएसपीएक्स) एक विकल्प होगा। [XmlLite परिचय] के XmlLite "उपयोग परिदृश्य" अनुभाग देखें (http://msdn.microsoft.com/en-us/library/windows/desktop/ms752838%28v=vs.85%29.aspx) – g2mk

+0

@ लार्स, "सैक्स, डेल्फी और एक्स एम एल" लिंक मरने लगते हैं; ( – rossmcm

3

himitsu द्वारा himXML को आज़मा कर देखें।

यह एमपीएल v1.1, जीपीएल v3.0 या LGPL v3.0 लाइसेंस के तहत जारी किया गया है।

आप इतनी के रूप में डाउनलोड करने के लिए सक्षम होने के लिए Delphi-Praxis (जर्मन) उत्कृष्ट डेल्फी साइट पर पंजीकरण करना होगा: और

यह एक बहुत ही प्रभावशाली प्रदर्शन किया है वितरण क़ौम शामिल यह प्रदर्शित करना मैंने इसे डेल्फी 2007, डेल्फी 2010 और डेल्फी एक्सई में सफलतापूर्वक उपयोग किया है।

+3

क्या आप कम से कम MSXML के साथ बेंचमार्क तुलना के साथ अपडेट कर सकते हैं? –

6

किसी दिन मैंने बहुत सरल XML परीक्षण सूट लिखा है। यह एमएसएक्सएमएल (डी 7 एमएसएक्सएमएल 3?), ओमनी एक्सएमएल (बिट पुराना) और जेडी एक्सएमएल (नवीनतम स्थिर) परोसता है। 1,52 एमबी फ़ाइल के लिए

टेस्ट परिणाम:

एक्सएमएल फ़ाइल लोडिंग समय MSXML: 240,20 [एमएस]

एक्सएमएल नोड चयन MSXML: 1,09 [एस]

एक्सएमएल फ़ाइल लोडिंग समय OmniXML: 2,25 [एस]

एक्सएमएल नोड चयन OmniXML: 1,22 [एस]

एक्सएमएल फ़ाइल लोडिंग समय JCL SimpleXML: 2,11 [0]

और JclSimpleXML नोड चयनों के लिए उल्लंघन का उपयोग: |

दुर्भाग्य से मैं वास्तव में नहीं ज्यादा समय ए वी ऊपर सही करने के लिए है, लेकिन sorces नीचे दिए गए हैं ...

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।क़दम

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. 
34

कुछ समय पहले मैं XML स्वरूप को record क्रमानुसार करने के लिए किया था; पूर्व के लिए:

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

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

को मैं रिकर्सिवली रिकॉर्ड क्षेत्रों माध्यम से नेविगेट और XML के लिए मूल्यों को संग्रहीत करने के लिए RTTI इस्तेमाल किया। मैंने कुछ एक्सएमएल पार्सर्स की कोशिश की है। मुझे एक्सएमएल बनाने के लिए डोम मॉडल की आवश्यकता नहीं थी, लेकिन इसे वापस लोड करने के लिए इसकी आवश्यकता थी।

एक्सएमएल में 310k नोड्स (10-15MBytes) शामिल थे; नीचे दी गई तालिका में प्रस्तुत परिणाम, सेकंड में समय के साथ 6 कॉलम हैं;
1 - नोड्स बनाने और मूल्य लिखने के लिए समय
2 - SaveToFile();
3 = 1 + 2
4 - LoadFromFile();
5 - नोड्स के माध्यम से नेविगेट करने और पढ़ने के मूल्यों
6 = 4 + 5
enter image description here

MSXML/Xerces/ADOM - के लिए विक्रेताओं differend रहे TXMLDocument (DOMVendor)
JanXML यूनिकोड के साथ काम नहीं करता है; मैंने कुछ त्रुटियों को ठीक किया है, और एक्सएमएल बचाया है, लेकिन लोडिंग एवी (या स्टैक ओवरफ्लो, मुझे याद नहीं है) का कारण बनता है;
manual - का अर्थ है TStringStream का उपयोग कर मैन्युअल रूप से एक्सएमएल लिखना।

मैंने डेल्फी -2010, विन 7x32, Q8200 CPU/2.3GHz, 4 जीबी रैम का उपयोग किया।

अद्यतन: आप इस परीक्षण के लिए स्रोत कोड डाउनलोड कर सकते हैं (आरटीटीआई का उपयोग कर एक्सएमएल को रिकॉर्ड क्रमबद्धता) यहां http://blog.karelia.pro/teran/files/2012/03/XMLTest.zip सभी पार्सर्स (ओमनी, मूल, जनवरी) शामिल हैं (अब एक्सएमएल में नोड्स गिनती लगभग 270k है), क्षमा करें, कोई नहीं है कोड में टिप्पणियां।

+3

कम से कम कुछ मानक +1। –

+0

अच्छी संख्या। मैं बस इतना जोड़ूंगा कि अच्छे प्रदर्शन प्राप्त करने के लिए एक बफरर्ड स्ट्रीम जोड़ने के लिए नेटिवएक्सएमएल ने विशिष्ट कदम उठाए हैं। मेरे पास एक बड़ी फाइल थी जो बहुत धीमी थी, और बाद में यह एक छोटी फ़ाइल के रूप में तेज़ था। उपरोक्त माप यह दिखाता है कि यह अच्छा है। – mj2008

+0

ध्यान दें कि जब तक हम उनके द्वारा किए गए कार्यान्वयन की तुलना नहीं करते हैं, तो यह संभव है कि उपरोक्त किसी भी उपकरण का उपयोग करने वाले किसी अन्य व्यक्ति ने काफी अलग प्रदर्शन प्राप्त किया हो। ओमनीएक्सएमएल के लिए बचत समय हर जगह की तुलना में 10x धीमी है। यह मेरे लिए संदिग्ध है। उदाहरण के लिए, वह OmniXML का उपयोग करने का एक महंगा (गलत) तरीका उपयोग कर रहा है। –

22

मुझे पता है कि यह एक पुराने सवाल है, लेकिन लोगों को मिल सकती है यह दिलचस्प:

मैं एक नया एक्सएमएल पुस्तकालय लिखा था डेल्फी (ओएक्सएमएल) के लिए: http://www.kluug.net/oxml.php

इसमें प्रत्यक्ष एक्सएमएल हैंडलिंग (पढ़ें + लिखें), एसएक्स पार्सर, डोम और एक अनुक्रमिक डोम पार्सर शामिल है। लाभों में से एक यह है कि ओएक्सएमएल सभी प्लेटफार्मों (विन, मैकॉक्स, लिनक्स, आईओएस, एंड्रॉइड) पर डेल्फी 6-डेल्फी एक्सई 5, एफपीसी/लाजर और सी ++ बिल्डर का समर्थन करता है।

OXml डोम रिकॉर्ड/सूचक आधारित है और किसी भी अन्य एक्सएमएल पुस्तकालय की तुलना में बेहतर प्रदर्शन प्रदान करता है:

पढ़ने परीक्षण समय पार्सर एक फ़ाइल (स्तंभ "लोड" से एक कस्टम एक्सएमएल डोम को पढ़ने के लिए की जरूरत है देता है) और निरंतर डमी फ़ंक्शन (कॉलम "नेविगेट") में नोड मान लिखने के लिए। फ़ाइल यूटीएफ -8 में एन्कोड की गई है और इसका आकार लगभग 5,6 एमबी है।

XML parse comparison

लिखने परीक्षण समय पार्सर एक डोम (स्तंभ "बनाने के") बना सकते हैं और एक फाइल करने के लिए इस डोम लिखने (स्तंभ "सहेजें") की जरूरत है देता है। फ़ाइल यूटीएफ -8 में एन्कोड की गई है और इसका आकार लगभग 11 एमबी है।

XML write comparison

+ गरीब OmniXML (मूल) लेखन प्रदर्शन तथ्य यह है कि OmniXML लिखने के लिए बफरिंग का उपयोग नहीं किया का परिणाम था। इस प्रकार एक TFileStream को लिखना बहुत धीमा था। मैंने OmniXML को अपडेट किया और बफरिंग समर्थन जोड़ा। आप एसवीएन से नवीनतम ओमनीएक्सएमएल कोड प्राप्त कर सकते हैं।

+1

कूल। मैं आपकी नई लाइब्रेरी देखूंगा! –

+3

@oxo ग्रेट लाइब्रेरी! यह एक जवाब होना चाहिए! – SOUser

+0

@oxo क्षमा करें, लेकिन OXml lib नहीं है मुक्त। – Ugur

संबंधित मुद्दे