XML SAX

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Helios
Beiträge: 25
Registriert: Mi 29. Jun 2011, 22:36
OS, Lazarus, FPC: Lazarus 2.0.12 Windows 10 64Bit / Lazarus 2.0.10 Debian 11 „Bullseye" 64Bit
CPU-Target: 64Bit
Wohnort: Leonberg

XML SAX

Beitrag von Helios »

Hallo Forenmitglieder,
fast schon aus der Mode (XML:-), aber ich würde gerne mit Lazarus große XML Dateien einlesen und zwar nach der SAX Methode.
Wenn ich das richtig verstanden habe, ist SAX resourchenschonender (sequenzielle Abarbeitung der XML Datei möglich man braucht nicht komplett die XML Datei in eine DOM Struktur in den RAM laden).
Die Beispiele in Lazarus zu XML Dom habe ich soweit gesehen. Es gab wohl auch mal ein TSAXReader siehe https://forum.lazarus.freepascal.org/in ... ml#msg9069. Wurden die Arbeiten am TSAXReader eingestellt (und durch was ersetzt)?
Ich finde dazu leider auch keine griffigen Beispiele (mehr).
Kann mich hier jemand auf die richtigen Web Seiten per Link stubsen oder mich mit einem einfachen aber lauffähigen TSAXReader Beispiel versorgen?
Ich möchte mich ungern in der C/C++ Welt bedienen müssen (SAX aus der LibXML2 www.xmlsoft.org ist bestimmt gut aber eben nicht Pascal :D )
Vielen Dank bereits im voraus für eure Tipps und Gruß
Helios

charlytango
Beiträge: 301
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz 2.0 fixes FPC 3.2 fixes
CPU-Target: Win 32Bit, 64bit
Wohnort: Wien

Re: XML SAX

Beitrag von charlytango »

in etwa wie das hier: http://www.kluug.net/oxml.php?

Helios
Beiträge: 25
Registriert: Mi 29. Jun 2011, 22:36
OS, Lazarus, FPC: Lazarus 2.0.12 Windows 10 64Bit / Lazarus 2.0.10 Debian 11 „Bullseye" 64Bit
CPU-Target: 64Bit
Wohnort: Leonberg

Re: XML SAX

Beitrag von Helios »

Hab ich schon bei meinen Recherchen gesehen, ist aber leider nicht Open Source :(

Benutzeravatar
Winni
Beiträge: 628
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.06, fpc 3.04
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: XML SAX

Beitrag von Winni »

Hi!

Hier gibt's Sax für Delphi:

https://sourceforge.net/projects/saxforpascal/

Vielleicht läuftt das ja unter Lazarus.

Winni

Helios
Beiträge: 25
Registriert: Mi 29. Jun 2011, 22:36
OS, Lazarus, FPC: Lazarus 2.0.12 Windows 10 64Bit / Lazarus 2.0.10 Debian 11 „Bullseye" 64Bit
CPU-Target: 64Bit
Wohnort: Leonberg

Re: XML SAX

Beitrag von Helios »

Hi Winni,
hatte ich auch gesehen, ist aber seit fast 18 Jahren nicht mehr "angefasst" worden. Ich hatte gedacht der SAX Pfad in Lazarus selbst ist weiterentwickelt worden, so wie der DOM Ansatz in Lazarus ein Standard ist (mit Beispielen in der Lazarusinstallation etc.).
Den TSAXReader hat es aber mal in Lazarus gegeben oder täusche ich mich da total? Ich grabe mal tiefer in der Klassen Hierarchie (vielleicht tauche ich ja wieder auf:-))
Danke aber für den Hinweis, Winni!
Gruß
Helios

BeniBela
Beiträge: 276
Registriert: Sa 21. Mär 2009, 17:31
OS, Lazarus, FPC: Linux (Lazarus SVN, FPC 2.4)
CPU-Target: 64 Bit

Re: XML SAX

Beitrag von BeniBela »

SAX_XML heißt die Unit in FPC

Meine Internet Tools haben auch so was, aber primär für HTML gedacht: https://github.com/benibela/internettoo ... parser.pas

Helios
Beiträge: 25
Registriert: Mi 29. Jun 2011, 22:36
OS, Lazarus, FPC: Lazarus 2.0.12 Windows 10 64Bit / Lazarus 2.0.10 Debian 11 „Bullseye" 64Bit
CPU-Target: 64Bit
Wohnort: Leonberg

Re: XML SAX

Beitrag von Helios »

Hallo BeniBela,
auch für Deinen Beitrag herzlichen Dank!
Ja, die SAX und SAX_XML werden mit Lazarus/Free Pascal ausgeliefert, aber weiter als die Jungs in https://forum.lazarus.freepascal.org/in ... ml#msg9069 (wie eingangs erwähnt) komme ich auch nicht. Ich lande auch bei einem Laufzeitfehler... Schade.
Im Anhang mal das komplette Beispielprojekt, in der Hoffnung, das sich doch jemand findet, der mit dem ausgelieferten SAX Parser positive Erfahrungen gemacht hat und sein Wissen teilen kann.
Danke nochmal an alle und Gruß
Helios
Dateianhänge
Test.zip
(126.77 KiB) 14-mal heruntergeladen

PascalDragon
Beiträge: 276
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: XML SAX

Beitrag von PascalDragon »

TSAXReader ist eigentlich eine abstrakte Klasse. Du musst TXMLSAXReader aus SAX_XML. Außerdem ist der Eingabeparameter für Parse eben nicht der Dateiname, sonder XML String selbst. Wenn du eine Datei statt einen String hast, dann solltest du besser TSAXInputSource verwenden. Letztlich schaut dein Code dann so aus (und du musst dann auch noch die Unit SAX_XML verwenden):

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var XMLReader:TSAXReader;
  fs: TFileStream;
  src: TSAXInputSource;

begin
  if (OpenDialog1.Execute) then
  begin
    fs := TFileStream.Create(OpenDialog1.FileName, fmOpenRead);
    try
      src := TSAXInputSource.Create(fs);
      try
        XMLReader := TXMLSAXReader.Create;
        try
          XMLReader.OnStartElement := @MyStartElementEvent;
          XMLReader.Parse(src);
          //XMLReader:=nil;
        finally
          XMLReader.Free
        end;
      finally
        src.Free;
      end;
    finally
      fs.Free;
    end;
  end;
end;
Anmerkung: beachte, dass das Erstellen des TSAXXMLReader innerhalb des then-Zweigs der if-Bedingung ist, da du andernfalls ein Memory Leak hättest, wenn der User keinen Dateinamen auswählt.
FPC Compiler Entwickler

Helios
Beiträge: 25
Registriert: Mi 29. Jun 2011, 22:36
OS, Lazarus, FPC: Lazarus 2.0.12 Windows 10 64Bit / Lazarus 2.0.10 Debian 11 „Bullseye" 64Bit
CPU-Target: 64Bit
Wohnort: Leonberg

Re: XML SAX

Beitrag von Helios »

Hallo PascalDragon,
da hast Du Deinem Namen alle Ehre gemacht! Vielen Dank!
Mit Deinem/Euren Hinweis/Hinweisen habe ich noch weitergegraben und weitere CallBackfunktionen integriert.
Aus meiner Sicht sind die wesentlichen Hürden für die Verwendung des FPC SAX Ansatzes überwunden und ich kann diesen Thread hier erfolgreich schließen.
Vielen Dank nochmal an ale Beteiligten.
Tolle Programmiersprache und super Forum(mitglieder)!
Habt einen schönen Sonntag
Gruß
Helios

Code: Alles auswählen

 unit TestMain;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, SAX, SAX_XML;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    ListBox1: TListBox;
    OpenDialog1: TOpenDialog;
    procedure Button1Click(Sender: TObject);
    procedure MyStartDocument(Sender: TObject);
    procedure MyEndDocument(Sender: TObject);
    procedure MyStartElementEvent(Sender: TObject; const NamespaceURI, LocalName, QName: SAXString; Atts: TSAXAttributes);
    procedure MyEndElementEvent(Sender: TObject; const NamespaceURI, LocalName, QName: SAXString);
    procedure MyCharactersEvent(Sender: TObject; const ch: PSAXChar; AStart, ALength: Integer);
    procedure MyIgnorableWhitespaceEvent(Sender: TObject; const ch: PSAXChar; AStart, ALength: Integer);
  private

  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.MyStartDocument(Sender: TObject);
begin
  Form1.ListBox1.Items.Add('MyStartDocument');
end;

procedure TForm1.MyEndDocument(Sender: TObject);
begin
  Form1.ListBox1.Items.Add('MyEndDocument');
end;

procedure TForm1.MyStartElementEvent(Sender: TObject; const NamespaceURI, LocalName, QName: SAXString; Atts: TSAXAttributes);
begin
  Form1.ListBox1.Items.Add('MyStartElementEvent ' + NamespaceURI + ' ' + LocalName + ' ' + QName);
end;

procedure TForm1.MyEndElementEvent(Sender: TObject; const NamespaceURI, LocalName, QName: SAXString);
begin
  Form1.ListBox1.Items.Add('MyEndElementEvent ' + NamespaceURI + ' ' + LocalName + ' ' + QName);
end;

procedure TForm1.MyCharactersEvent(Sender: TObject; const ch: PSAXChar; AStart, ALength: Integer);
begin
  //Form1.ListBox1.Items.Add('MyCharactersEvent ' + ch + ' ' + IntToStr(AStart) + ' ' + IntToStr(ALength));
end;

procedure TForm1.MyIgnorableWhitespaceEvent(Sender: TObject; const ch: PSAXChar; AStart, ALength: Integer);
begin
  //Form1.ListBox1.Items.Add('MyIgnorableWhitespaceEvent ' + ch + ' ' + IntToStr(AStart) + ' ' + IntToStr(ALength));
end;    


procedure TForm1.Button1Click(Sender: TObject);
var
  XMLReader: TSAXReader;
  fs:        TFileStream;
  src:       TSAXInputSource;

begin
  ListBox1.Items.Clear;
  if (OpenDialog1.Execute) then
  begin
    fs := TFileStream.Create(OpenDialog1.FileName, fmOpenRead);
    try
      src := TSAXInputSource.Create(fs);
      try
        XMLReader := TSAXXMLReader.Create;
        try
          XMLReader.OnStartDocument       := @MyStartDocument;
          XMLReader.OnEndDocument         := @MyEndDocument;
          XMLReader.OnStartElement        := @MyStartElementEvent;
          XMLReader.OnEndElement          := @MyEndElementEvent;
          XMLReader.OnCharacters          := @MyCharactersEvent;
          XMLReader.OnIgnorableWhitespace := @MyIgnorableWhitespaceEvent;
          XMLReader.Parse(src);
          //XMLReader:=nil;
        finally
          XMLReader.Free
        end;
      finally
        src.Free;
      end;
    finally
      fs.Free;
    end;
  end;
end;

end.
Ein compilier- und ausführbares Projekt für alle die auf das gleiche Problem stoßen werden oder gestoßen sind im Anhang.
Dateianhänge
TestOk.zip
(128.09 KiB) 9-mal heruntergeladen

Antworten