Umgang mit XML- und JSON-Formaten in FastScript

2025-04-22

XML und JSON sind inzwischen zu den wichtigsten Standards für die Datenspeicherung und den Informationsaustausch zwischen Computersystemen geworden. Als Reaktion auf Benutzeranfragen wurden Klassen für die Arbeit mit XML und JSON zu FastScript hinzugefügt. In diesem Artikel sehen wir uns genauer an, wie man mit diesen Klassen arbeitet, über welche Eigenschaften und Methoden sie verfügen und wie man Berichte aus Skriptcode erstellt.

 


 

XML-Format

In Skripten werden 2 Klassen verwendet, um mit XML zu arbeiten. Diese Klassen sind auf maximale Leistung und geringen Speicherverbrauch ausgerichtet.

Klassen für das Arbeiten mit XML

 

TfrXMLDocument – ist eine Klasse, die die Funktionalität eines XML-Dokuments kapselt. Die folgenden Eigenschaften und Methoden sind in dieser Klasse verfügbar.

Eigenschaften und Methoden der Klasse Beschreibung
procedure SaveToStream(Stream: TStream); speichert XML im übergebenen Stream
procedure LoadFromStream(Stream: TStream; AllowPartialLoading: Boolean = False); lädt XML aus dem übergebenen Stream hoch
procedure SaveToFile(const FileName: string); speichert XML in einer Datei mit dem angegebenen Namen
procedure LoadFromFile(const FileName: string); lädt XML aus einer Datei mit dem angegebenen Namen hoch
procedure Clear; Entfernt alle XML-Knoten aus dem Baum außer dem Stammknoten. Der Inhalt des Knotens wird NICHT geleert.
property Root: TfrXMLItem; ermöglicht den Zugriff auf das Stammelement des Baums
property AsText: string; ermöglicht, XML als Zeichenkette abzurufen und festzulegen (mit dieser Eigenschaft können Sie beispielsweise XML mithilfe einer Berichtsvariablen an ein Berichtsskript übergeben)
property AutoIndent: Boolean; legt fest, wie die XML-Ausgabe generiert werden soll: als einzelne Zeile oder als eingerückter Text

 

TfrXMLNode – a class that encapsulates the properties of an XML document node.

You cannot create an object of this type directly. It is created by calling the Add() method of the element to which you want to add a child element. Let’s take a closer look at the properties and methods of the TfrXMLNode class.

Eigenschaften und Methoden der Klasse Beschreibung
function Add(AName:string):TfrXMLItem; erstellt ein untergeordnetes TfrXMLItem Element mit dem angegebenen Namen und gibt es zurück
procedure Clear; löscht die Liste der untergeordneten Elemente
procedure InsertItem(Index:integer; AItem: TfrXMLItem); fügt ein untergeordnetes Element an der angegebenen Position ein; das Element kann zu einem anderen Dokument gehören
function Find(AName:string):Integer; sucht unter den untergeordneten Elementen ein TfrXMLItem mit dem angegebenen Namen und gibt es zurück. Wenn das Element nicht gefunden wird, wird -1 zurückgegeben. Wenn es mehrere Elemente mit dem angegebenen Namen gibt, wird das erste von ihnen zurückgegeben
function FindItem(AName:string):TfrXMLItem; sucht unter den untergeordneten Elementen ein TfrXMLItem mit dem angegebenen Namen und gibt es zurück. Wenn das Element nicht gefunden wird, wird ein neues Element mit dem angegebenen Namen erstellt und zurückgegeben. Wenn es mehrere Elemente mit dem angegebenen Namen gibt, wird das erste von ihnen zurückgegeben.
function Root: TfrXMLItem; gibt das Stammelement des Dokuments zurück
property Count:Integer; Gibt die Anzahl der untergeordneten Knoten des Elements zurück
property Items[AIndex:Integer]: TfrXMLItem; gibt ein untergeordnetes Element anhand seines Indexes zurück
property Prop[AName:string]:string; gibt den Wert des Knotenattributs mit dem angegebenen Namen zurück oder legt ihn fest 
property Name: string; Name des Element-Tags
property Parent: TfrXMLItem; Name des übergeordneten Elements. Bei Root ist es gleich nil
property Text:string; Eine Zeichenkette mit einer Liste von Knotenparametern in der folgenden Form: Name1=”Value1” Name2=”Value2”… Sonderzeichen sind in dieser Zeichenkette Escapezeichen.
procedure Delete(AIndex: Integer); löscht das untergeordnete Element mit dem AIndex-Index 
procedure DeleteProp(const APropName: string); löscht ein Knotenattribut mit dem angegebenen Namen
property Value: string; Text, der zwischen dem öffnenden und dem schließenden Tag des Elements steht
function PropExists(APropName:string):Boolean; hilft festzustellen, ob ein Element ein Attribut mit dem angegebenen Namen hat
function IndexOf(AItem: TfrXMLItem):Integer; gibt den Index des übergebenen Elements zurück
function GetPropNames(ANames:TStrings); Füllt die übergebene Zeichenkettenliste mit TfrXMLItem-Attributnamen

 

Versuchen wir, einen Bericht mithilfe von Klassen für das Arbeiten mit XML zu erstellen. Als Beispiel werden wir Daten aus der Datei „country.xml“ in einem Bericht anzeigen, dabei jedoch nicht TClientDataSet verwenden, sondern auf die XML-Datei direkt zugreifen. Erstellen Sie einen neuen Bericht, wechseln Sie in den Bearbeitungsmodus und fügen Sie MasterData in den Bericht ein. Und obendrauf fügen Sie mehrere Memos hinzu, um die Daten anzuzeigen. Erstellen Sie außerdem das OnBeforePrint Ereignis für das MasterData-Objekt. 

Der endgültige Code des Berichtsskripts sieht wie folgt aus:

var doc: TfrXMLDocument;
 item: TfrXMLItem;
 IIndex: Integer;
 
procedure MasterData1OnBeforePrint(Sender: TfrxComponent);
var cur: TfrXMLItem;
 S: string;
begin
 cur := item[IIndex];
 mmNum.Text := cur.Prop['Code'];
 mmName.Text := cur.Prop['Name'];
 mmCapital.Text := cur.Prop['Capital'];
 mmArea.Text := cur.Prop['Area'];
 mmPopulation.Text := cur.Prop['Population'];
 mmContinent.Text := cur.Prop['Continent'];
 Inc(IIndex);
end;
 
begin
 Doc := TfrXMLDocument.Create;
 Doc.LoadFromFile('..\..\Data\country.xml');
 item := Doc.Root[1];
 IIndex := 0;
 MasterData1.RowCount := item.count;
end.


Führen Sie den Bericht aus. Zur besseren Lesbarkeit haben wir auch Spaltenüberschriften hinzugefügt.

Fertiger Bericht

 


 

JSON Format

Wechseln wir vom XML-Format zu JSON-Format. FastReport verwendet auch 2 Klassen um mit JSON zu arbeiten. Das sind TfrJSON und TfrJSONArray. In diesem Fall sind diese Klassen nur ein Wrapper um Klassen von System.JSON in der Delphi Plattform oder ähnliche Klassen in Lazarus.

Klassen zum Arbeiten mit JSON

 

TfrJSONObject ist eine Klasse, die Funktionen für die Arbeit mit JSON-Objekten kapselt. 

Eigenschaften und Methoden der Klasse Beschreibung
function Create(const JSONstring: string); erzeugt ein JSON-Objekt und füllt es mit der übergebenen Zeichenkette
function IsValid:Boolean; gibt True zurück, wenn das Objekt gültiges JSON enthält
procedure LodFromFile(const AFilName:string); lädt Daten aus der angegebenen Datei. Wenn das Objekt Daten enthält, gehen diese verloren
procedure LoadFromtStream(const AStream:TStream); lädt Daten aus dem übergebenen Stream. Wenn das Objekt Daten enthält, gehen diese verloren
function ToString:string;   gibt eine Zeichenkette zurück, die die alphabetische Darstellung des JSON-Objekts enthält
procedure SaveToFile(const AFileName: string); speichert die alphabetische Darstellung eines JSON-Objekts in einer Datei
procedure SaveToStream(AStream: TStream speichert die alphabetische Darstellung eines JSON-Objekts in einem Stream
function IsNameExists(const AName:string); gibt True zurück, wenn das Objekt eine Eigenschaft mit dem angegebenen Namen hat
function IsNameValueExists(const Name, Value: string): boolean; gibt True zurück, wenn das Objekt eine Eigenschaft mit dem angegebenen Namen hat und ihr Wert mit dem angegebenen Wert übereinstimmt
function Count:Integer; gibt die Gesamtzahl der Eigenschaften eines JSON-Objekts zurück
property Names[AIndex:Integer]:string; gibt den Namen der Eigenschaft mit dem angegebenen Index zurück
Property ValueType[IndexOrName:Variant]:TfrJSONType; gibt den Typ der Eigenschaft mit dem angegebenen Index oder Namen zurück. Der Typ kann einer der folgenden Werte sein:

 – jsUnknown – der Eigenschaftstyp ist unbekannt (es ist ein Parsing-Fehler aufgetreten oder es gibt keine Eigenschaft mit diesem Index oder Namen).
– jsNumber – die Eigenschaft ist vom numerischen Typ.
– jsString – die Eigenschaft ist vom Zeichenkettentyp.
– jsBoolean – die Eigenschaft ist vom Booleschen Typ (true/false).
– jsNull – der Eigenschaftstyp ist null (der Wert ist nicht festgelegt).
– jsList – der Eigenschaftentyp ist ein JSON-Array.
– jsObject – der Eigenschaftstyp ist ein verschachteltes JSON-Objekt.


Mit den folgenden Eigenschaften können Sie die Werte eines JSON-Objekts in der einen oder anderen Form abrufen. Bei allen diesen Eigenschaften erfolgt die Indizierung entweder über die Eigenschaftsnummer in der Eigenschaftsliste oder über ihren Namen. Beachten Sie, dass AsString[‘1’] <> AsString[1] nicht gleich sind. Auch wenn Sie versuchen, den Eigenschaftswert mit einer ungeeigneten Methode abzurufen, können Fehler auftreten und falsche Eigenschaftswerte zurückgegeben werden. Wenn eine Eigenschaft beispielsweise vom Typ „Objekt“ oder „Array“ ist und Sie versuchen, ihren Wert mithilfe der Eigenschaft „AsString“ abzurufen, erhalten Sie eine leere Zeichenkette zurück. In anderen Fällen gibt AsString eine Zeichenkettendarstellung des Eigenschaftswerts zurück.

Eigenschaften und Methoden der Klasse Beschreibung
property AsObject[IndexOrName: Variant]: TfrxJSON; ermöglicht es, ein verschachteltes JSON-Objekt abzurufen
property AsArray[IndexOrName: Variant]: TfrJSONArray; ermöglicht es, ein verschachteltes JSON-Array abzurufen
Property AsString[IndexOrName: Variant]: string; ermöglicht es, den Eigenschaftswert als Zeichenkette anzurufen. Diese Methode kann auf Eigenschaften von anderen Typen als Objekten und Arrays angewendet werden. Für logische Werte wird eine Zeichenkette mit dem Wert „True“ oder „False“ zurückgegeben. Bei Zahlen mit einem Bruchteil wird unabhängig von den regionalen Einstellungen immer ein Punkt als Dezimaltrennzeichen verwendet.
property AsNumber[IndexOrName: Variant]: Extended; ermöglicht es, den Eigenschaftswert als Zahl abzurufen. Wenn die Eigenschaft nicht numerisch ist, wird 0 zurückgegeben
property AsBoolean[IndexOrName: Variant]: Boolean; ermöglicht es, den Eigenschaftswert als Booleschen Wert abzurufen. Wenn die Eigenschaft von einem anderen Typ ist, wird False zurückgegeben. 


Um ein Nullfeld zurückzugeben, müssen Sie sich etwas mehr Mühe geben. Im Allgemeinen gibt es keine solche Methode. Sie können jedoch die ValueType-Eigenschaft verwenden, die für ein Nullfeld jsNull zurückgibt, oder die AsString-Eigenschaft verwenden, die die Zeichenkette „null“ zurückgibt.

Betrachten wir näher die Methoden zur Behandlung von Objekteigenschaften.

Methoden der Klasse Beschreibung
Procedure Delete(AName: String);   löscht die Eigenschaft des Objekts mit dem angegebenen Namen
function AddObject(const AName: string): Integer fügt dem Objekt ein leeres untergeordnetes Objekt mit dem angegebenen Namen hinzu
function AddArray(const AName: string): Integer; fügt dem Objekt ein leeres Array mit dem angegebenen Namen hinzu
function AddString(const AName, AValue: string): Integer; fügt dem Objekt eine Zeichenkette mit dem angegebenen Namen hinzu
function AddBool(const AName: string; AValue: boolean): Integer; fügt dem Objekt einen booleschen Wert mit dem angegebenen Namen hinzu
function AddNumber(const AName: string; AValue:Extended): Integer; fügt dem Objekt einen numerischen reelen Wert mit dem angegebenen Namen hinzu
function AddInteger(const AName: string; AValue:Integer): Integer; fügt dem Objekt einen numerischen Ganzzahlwert mit dem angegebenen Namen hinzu
function AddNull(const AName: string): Integer; Fügt dem Objekt einen Nullwert mit dem angegebenen Namen hinzu


Die Methoden geben eine Ganzzahl zurück, die den Index des hinzugefügten Elements in der Liste aller Felder darstellt.

Alle Methoden, die einem Objekt Felder hinzufügen, überwachen nicht, ob bereits Felder mit gleichem Namen vorhanden sind. Die Verantwortung dafür liegt beim Programmierer, der diese Klasse verwendet. Diese Überwachung ist notwendig, um zu verhindern, dass mehrere Felder mit denselben Namen in der JSON-Ausgabe erscheinen. Das Verhalten des Systems in diesem Fall ist nicht definiert - es hängt vom Parser ab, der das empfangene JSON weiter parst. Das bedeutet, dass jeder beliebige Wert mit demselben Namen in der Arbeit erscheinen kann! 

Die Klasse TJSONArray kapselt Methoden und Eigenschaften für die Arbeit mit JSON-Arrays. Die Grundeigenschaften sind grundsätzlich gleich, aber auf sie kann nur per Index zugegriffen werden. Es werden nur Operationen unterstützt, die auf ein beliebiges Element zugreifen, seinen Wert abfragen oder ein Element löschen. Es ist nicht möglich, Elemente im Array zu verschieben oder ihren Typ zu ändern. Betrachten wir die Eigenschaften und Methoden zum Abrufen der Werte von Elementen in dieser Klasse.

Eigenschaften und Methoden der Klasse Beschreibung
function Count:Integer; gibt die Anzahl der Elemente in einem Array zurück
property ValueType[AIndex: Integer]: TfrJSONType; gibt den Typ des Array-Elements mit dem angegebenen Index zurück
property AsObject[AIndex: Integer]: TfrJSONObject; gibt ein Objekt zurück, das den Zugriff auf ein Array-Element als JSON-Objekt ermöglicht
Property AsArray[AIndex: Integer]: TfrJSONArray gibt ein Objekt zurück, das den Zugriff auf ein Array-Element als JSON-Array ermöglicht
property AsString[AIndex: Integer]: string; gibt den Wert eines Array-Elements als Zeichenkette zurück
property AsNumber[AIndex: Integer]: Extended; gibt den Wert eines Array-Elements als Zahl zurück
property AsBoolean[AIndex: Integer]: Boolean; gibt den Wert eines Array-Elements als booleschen Wert zurück


Wie bei einem Objekt sollten Sie beim Abrufen von Werten von Array-Elementen vorsichtig sein. Je nach dem Wert-Typ sollten Sie die entsprechende Methode verwenden, um ihn abzurufen.

Nachfolgend werden Methoden zum Bearbeiten von Elementen eines JSON-Arrays beschrieben.

Eigenschaften und Methoden der Klasse Beschreibung
procedure Delete(AIndex:Integer); lLöscht ein Array-Element mit einem angegebenen Index
function AddObject: Integer; fügt ein verschachteltes JSON-Objekt am Ende des Arrays hinzu
function AddArray: Integer; fügt ein verschachteltes JSON- Array am Ende des Arrays hinzu
function AddString(const AValue: string): Integer; fügt eine Zeichenkette am Ende des Arrays hinzu
function AddBool(AValue: boolean): Integer; fügt einen booleschen Wert am Ende des Arrays hinzu
function AddNumber(AValue:Extended): Integer; fügt eine reelle Zahl am Ende des Arrays hinzu
function AddInteger(AValue: Integer): Integer; fügt eine Ganzzahl am Ende des Arrays hinzu
function AddNull: Integer; fügt Null am Ende des Arrays hinzu


Alle diese Methoden geben die Position des zum Array hinzugefügten Elements zurück. Sie können kein Element in die Mitte eines Arrays einfügen – dies ist eine Einschränkung der Basisklassen in System.JSON.

 


 

Besonderheiten der Verwendung von Klassen für den JSON-Zugriff 

Bei der Verwendung von Objekten ist zu beachten, dass alle Wrapper-Objekten nach ihrer Verwendung aus dem Code entfernt werden müssen. 

Bitte beachten Sie, wenn Sie ein untergeordnetes Objekt oder Array abrufen möchten und stattdessen ein Skalarwert oder überhaupt kein Wert vorhanden ist, gibt die Eigenschaft „nil“ zurück und der weitere Zugriff auf eine solche Eigenschaft führt zu einer Ausnahme. Sie sollten keine Methoden verwenden, die nicht für die Arbeit mit Werten bestimmter Typen ausgelegt sind, die in einem Element gespeichert sind, um diese Werte abzurufen. 

Beachten Sie auch, dass bei den Namen der Objekteigenschaften zwischen Groß- und Kleinschreibung unterschieden wird, d.h., „Item1“ und „item1“ sind unterschiedliche Namen!

Sie können den Objektelementen nur dann Werte zuweisen, wenn der Typ dieser Werte mit dem Typ übereinstimmt, der dem Element zugewiesen ist. Wenn Sie einen Elementtyp neu definieren müssen, löschen Sie dieses Element und fügen Sie ein neues Element mit demselben Namen und dem erforderlichen Typ hinzu. Es ist nicht möglich, neue Werte für Array-Elemente einzugeben. Sie müssen ein JSON-Array löschen und es dann mit den gewünschten Werten neu erstellen.

Verwenden wir die oben beschriebenen Klassen und schreiben ein Skript, das Daten (ohne Typinformationen) aus einer XML-Datei extrahiert und in ein JSON-Objekt einfügt.

procedure XMLToJSON;
var XML: TfrXMLDocument;
 xi, xi1: TfrXMLItem;
 I, J: Integer;
 JO: TfrJSONObject;
 JA, JA1: TfrJSONArray;
 SL: TStringList;
begin
 XML:=TfrXMLDocument.Create;
 XML.LoadFromFile('.\..\..\data\country.xml'); 
 JO:=TfrJSONObject.Create('{}');
 JO.AddArray('data');
 JA:=JO.AsArray['data'];
 xi:=X.Root[1];
 xi1:=xi.Items[0];
 SL:=TStringList.Create;
 xi1.GetParamNames(SL);
 for I:=0 to xi.Count - 1 do begin
 xi1:=xi.Items[I];
 JA1:=JA.AsArray[JA.AddArray];
 for J:=0 to SL.Count-1 do 
 JA1.AddString(xi1.Prop[SL[J]]);
 JA1.Free;
 end;
 JA.Free;
 JO.SaveToFile('.\..\..\data\country.json');
 JO.Free;
 SL.Free; 
end; 


Versuchen wir nun, einen Bericht auf der Grundlage der erhaltenen Daten zu erstellen (fügen Sie die entsprechenden Komponenten MasterData und Memo auf der Berichtsseite ein):

var J:TfrJSONObject;
 A:TfrJSONArray;
 curr:Integer;
 
procedure MasterData1OnBeforePrint(Sender: TfrxComponent);
var A1:TfrJSONArray;
begin
 A1:=A.AsArray(curr);
 Memo1.Memo.Text:=A1.AsString[0];
 Memo2.Memo.Text:=A1.AsString[1];
 Memo3.Memo.Text:=A1.AsString[2];
 Memo4.Memo.Text:=A1.AsString[3];
 Memo5.Memo.Text:=A1.AsString[4];
 Memo6.Memo.Text:=A1.AsString[5];
 A1.Free;
 curr := curr + 1;
end;
 
begin
 J:=TfrJSONObject.Create('');
 J.LoadFromFile('.\..\..\data\country.json');
 A:=J.AsArray[0];
 MasterData1.RowCount:=A.Count;
 curr:=0;
end.

 

Der Bericht wurde erfolgreich erstellt


Sie können diese Objekte auch im Delphi-Code verwenden - verbinden Sie einfach die frXML- und frJSON-Module in der uses-Anweisung. 

 


 

Schlussfolgerung

In diesem Artikel haben wir die Verwendung von Klassen für die Arbeit mit JSON und XML in FastReport betrachtet. Wenn Sie sowohl in Delphi als auch in Lazarus nicht nur Berichte entwickeln, wird die Verwendung dieser Klassen Probleme reduzieren, wenn Sie von einer Umgebung zur anderen wechseln. In beiden IDEs ist das Verhalten gleich. 

Zu Ihrem Komfort haben wir zwei Beispiele beigefügt, die die Erstellung von XML- und JSON-basierten Berichten veranschaulichen. Sie können sie sofort in FastReportDemo öffnen und ausführen, das im Lieferumfang von FastReport enthalten ist. Möglicherweise müssen Sie die Berichte vor dem Start konfigurieren – geben Sie den richtigen Pfad zur Datendatei „country.xml“ an. Sie befindet sich sowohl im DemoCenter als auch im Ordner mit den Beispielen. 

VCL FastScript JSON Script Report Delphi
22. April 2025

Umgang mit der TfrShellTreeView-Komponente in FastReport VCL

In diesem Artikel werden wir uns die TfrShellTreeView-Komponente ansehen. Es dient zur Anzeige von Dateisystemelementen und ist teilweise analog zu den Komponenten TDirectoryListBox, TDirectoryOutline und TShellTreeView.
21. April 2025

Funktionsweise von RFID-Tags in FastReport VCL

In diesem Artikel werden wir die Funktionsweise von RFID-Tags mit dem neuen TfrxDeviceCommand-Objekt in FastReport VCL mit der Veröffentlichung 2025.2 untersuchen.
8. April 2025

Konvertieren einer Microsoft Word-Datei (.docx) in eine FastReport .NET-Datei (.frx)

Ein Konverter von Microsoft Word (.docx) Format zu einem file FastReport .NET (.frx): Beschreibung und Anweisungen zur Verwendung des Tools.
Fast Reports
  • 800-985-8986 (Englisch, USA)
  • +31 97 01025-8466 (Englisch, EU)
  • +49 30 56837-3928 (Deutsch, DE)
  • +55 19 98147-8148 (Portugiesisch, BR)
  • info@fast-report.com
  • 66 Canal Center Plaza, Ste 505, Alexandria, VA 22314

© 1998-2025 Fast Reports Inc.