Difference between revisions of "XML Tutorial/de"

From Lazarus wiki
Jump to navigationJump to search
m (Fixed syntax highlighting)
 
(15 intermediate revisions by 8 users not shown)
Line 1: Line 1:
 
{{XML Tutorial}}
 
{{XML Tutorial}}
 
+
<br>
 +
Zurück zu den [[Additional information/de|Zusätzlichen Informationen]].<br>
 +
<br>
 +
__TOC__
 +
<br>
 
== Einleitung ==
 
== Einleitung ==
  
Die Extensible Markup Language ist eine von [http://www.w3.org/ W3C] empfohlene Sprache, die für den Informationsaustausch zwischen verschiedenen Systemen geschaffen wurde. Es ist eine textbasierte Möglichkeit, um Informationen zu speichern. Moderne Datenaustauschsprachen wie XHTML, ebenso wie die meisten WebServices Technologien, basieren auf XML.
+
Die Extensible Markup Language ist eine von [http://www.w3.org/ W3C] empfohlene Sprache, die für den Informationsaustausch zwischen verschiedenen Systemen geschaffen wurde. Sie ist eine textbasierte Möglichkeit, um Informationen zu speichern. Moderne Datenaustauschsprachen wie XHTML, ebenso wie die meisten WebServices Technologien, basieren auf XML.
  
Gegenwärtig gibt es eine Reihe von Units, die XML unter Free Pascal unterstützen. Diese Units sind "XMLRead", "XMLWrite" und "DOM" und sie sind ein Teil der Free Component Library (FCL) des Free Pascal Compilers. Die FCL ist bereits im Standard-Suchpfad für den Compiler in Lazarus. Daher müssen sie nur die Units zu ihrem uses Abschnitt hinzufügen, um die XML Unterstützung zu erhalten. Die FCL ist gegenwärtig (Oktober 2005) noch nicht dokumentiert. Daher hat dieses kurze Tutorial die Zielsetzung einen XML Einstieg unter Verwendung dieser Units zu bieten.
+
Gegenwärtig gibt es eine Reihe von Units, die XML unter Free Pascal unterstützen. Diese Units sind "XMLRead", "XMLWrite" und "DOM" und sind ein Teil der Free Component Library (FCL) des Free Pascal Compilers. Die FCL ist bereits im Standard-Suchpfad für den Compiler in Lazarus. Daher müssen Sie nur die Units zu Ihrem uses Abschnitt hinzufügen, um die XML Unterstützung zu erhalten. Die FCL ist gegenwärtig (Oktober 2005) noch nicht dokumentiert. Daher hat dieses kurze Tutorial das Ziel, einen Einstieg in XML unter Verwendung dieser Units zu bieten.
  
 
Das XML DOM (Document Object Model) ist eine Reihe standardisierter Objekte, die eine ähnliche Schnittstelle für die Benutzung von XML für verschiedene Sprachen und Systeme bieten. Der Standard spezifiziert nur die Methoden, Eigenschaften und andere Schnittstellen Teile des Objekts. Die Implementierung in verschiedenen Sprachen ist frei gelassen. Die FCL unterstützt gegenwärtig vollständig das [http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/ XML DOM 1.0].
 
Das XML DOM (Document Object Model) ist eine Reihe standardisierter Objekte, die eine ähnliche Schnittstelle für die Benutzung von XML für verschiedene Sprachen und Systeme bieten. Der Standard spezifiziert nur die Methoden, Eigenschaften und andere Schnittstellen Teile des Objekts. Die Implementierung in verschiedenen Sprachen ist frei gelassen. Die FCL unterstützt gegenwärtig vollständig das [http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/ XML DOM 1.0].
Line 11: Line 15:
 
== Beispiele ==
 
== Beispiele ==
  
Unterhalb finden sie eine Liste von Beispielen zur XML Datenmanipulation mit wachsender Komplexität.
+
Unten finden Sie eine Liste von Beispielen zur XML-Datenmanipulation mit wachsender Komplexität.
  
 
=== Lesen eines Textknotens ===
 
=== Lesen eines Textknotens ===
  
 
Für Delphi Programmierer:
 
Für Delphi Programmierer:
Wenn sie mit TXMLDocument arbeiten, ist zu beachten, dass der Text innerhalb eines Knotens ein separater Textknoten ist. Deshalb müssen sie auf den Text eines Knoten als separaten Knoten zugreifen. Gehen sie zum Beispiel von folgender XML Datei aus:
+
Wenn Sie mit TXMLDocument arbeiten, ist zu beachten, dass der Text innerhalb eines Knotens ein separater Textknoten ist. Deshalb müssen Sie auf den Text eines Knotens als separaten Knoten zugreifen. Gehen Sie zum Beispiel von folgender XML-Datei aus:
  
<xml>
+
<syntaxhighlight lang="xml">
  <?xml version="1.0" encoding="utf-8"?>
+
  <?xml version="1.0"?>
 
  <request>
 
  <request>
 
   <request_type>PUT_FILE</request_type>
 
   <request_type>PUT_FILE</request_type>
Line 25: Line 29:
 
   <password>abc</password>
 
   <password>abc</password>
 
  </request>
 
  </request>
</xml>
+
</syntaxhighlight>
  
 
Das folgende Code-Beispiel zeigt sowohl den richtigen als auch den falschen Weg, um den Wert eines Textknotens zu erhalten:
 
Das folgende Code-Beispiel zeigt sowohl den richtigen als auch den falschen Weg, um den Wert eines Textknotens zu erhalten:
  
<delphi>
+
<syntaxhighlight lang=pascal>
 
  var
 
  var
 
   PassNode: TDOMNode;
 
   PassNode: TDOMNode;
Line 42: Line 46:
 
   // Der Text des Knotens ist ein separater Kindknoten
 
   // Der Text des Knotens ist ein separater Kindknoten
 
   WriteLn(PassNode.FirstChild.NodeValue); // gibt "abc" korrekt aus
 
   WriteLn(PassNode.FirstChild.NodeValue); // gibt "abc" korrekt aus
</delphi>
+
</syntaxhighlight>
  
 
=== Ausgeben der Knotennamen ===
 
=== Ausgeben der Knotennamen ===
Line 48: Line 52:
 
Das folgende Beispiel zeigt, wie man die Knotennamen in einem Memo (platziert auf einem Formular) ausgibt.
 
Das folgende Beispiel zeigt, wie man die Knotennamen in einem Memo (platziert auf einem Formular) ausgibt.
  
Unterhalb sehen sie die XML Datei namens 'C:\Programas\teste.xml':
+
Unterhalb sehen Sie die XML-Datei namens 'C:\Programas\teste.xml':
  
<xml>
+
<syntaxhighlight lang="xml">
  <?xml version="1.0" encoding="ISO-8859-1"?>
+
  <?xml version="1.0"?>
 
  <images directory="mydir">
 
  <images directory="mydir">
 
   <imageNode URL="graphic.jpg" title="">
 
   <imageNode URL="graphic.jpg" title="">
Line 58: Line 62:
 
   </imageNode>
 
   </imageNode>
 
  </images>
 
  </images>
</xml>
+
</syntaxhighlight>
  
 
Und hier der Pascal Code um die Aufgabe auszuführen:
 
Und hier der Pascal Code um die Aufgabe auszuführen:
  
<delphi>
+
<syntaxhighlight lang=pascal>
 
  var
 
  var
 
   Documento: TXMLDocument;
 
   Documento: TXMLDocument;
Line 83: Line 87:
 
   Documento.Free;
 
   Documento.Free;
 
  end;
 
  end;
</delphi>
+
</syntaxhighlight>
  
 
Dies führt zur Ausgabe von:
 
Dies führt zur Ausgabe von:
Line 95: Line 99:
 
=== Füllen eines TreeView mit XML ===
 
=== Füllen eines TreeView mit XML ===
  
Eine übliche Verwendung von XML Dateien ist, sie zu analysieren und ihren Inhalt in einem baumartigen Format anzuzeigen. Sie können die TTreeView Komponente auf dem "Common Controls" Tab von Lazarus finden.
+
Eine übliche Verwendung von XML Dateien ist, sie zu analysieren und ihren Inhalt in einem baumartigen Format anzuzeigen. Sie können die TTreeView-Komponente auf dem "Common Controls" Tab von Lazarus finden.
  
Die Funktion unten nimmt ein zuvor geladenes oder im Code erzeugtes XML Dokument und füllt einen TreeView mit seinen Inhalten. Die Beschriftung von jedem Knoten ist der Inhalt des ersten Attributs eines jeden Knotens.
+
Die Funktion unten nimmt ein zuvor geladenes oder im Code erzeugtes XML-Dokument und füllt einen TreeView mit seinen Inhalten. Die Beschriftung jedes Knotens ist der Inhalt des ersten Attributs eines jeden Knotens.
  
<delphi>
+
<syntaxhighlight lang=pascal>
 
procedure TForm1.XML2Tree(tree: TTreeView; XMLDoc: TXMLDocument);
 
procedure TForm1.XML2Tree(tree: TTreeView; XMLDoc: TXMLDocument);
 
var
 
var
Line 111: Line 115:
 
      
 
      
 
     // Einen Knoten zum Baum hinzufügen
 
     // Einen Knoten zum Baum hinzufügen
     TreeNode := tree.Items.AddChild(TreeNode, Node.Attributes[0].NodeValue);
+
     if Node.HasAttributes then
 +
        TreeNode := tree.Items.AddChild(TreeNode, Node.Attributes[0].NodeValue)
 +
    else
 +
        TreeNode := tree.Items.Addchild(TreeNode, '');
  
 
     // Zum Kindknoten weiter gehen
 
     // Zum Kindknoten weiter gehen
Line 132: Line 139:
 
   end;
 
   end;
 
end;
 
end;
</delphi>
+
</syntaxhighlight>
  
=== Modifizieren eines XML Dokuments ===
+
=== Modifizieren eines XML-Dokuments ===
  
Das wichtigste, das man sich merken muss ist, das TDOMDocument das "handle" für DOM ist. Eine Instanz dieser Klasse erhält man, indem man eine erzeugt oder indem man ein XML Dokument lädt.
+
Das wichtigste, was man sich merken muss ist, dass 'TDOMDocument' das "Handle" für DOM ist. Eine Instanz dieser Klasse erhält man, indem man eine erzeugt oder indem man ein XML-Dokument lädt.
  
Dagegen können Knoten nicht wir normale Objekte erzeugt werden. Man muss die Methoden von TDOMDocument für die Erzeugung verwenden und sie danach mit anderen Methoden an die richtige Stelle zu bringen. Der Grund dafür ist, dass die Knoten einem speziellen Dokument auf DOM gehören müssen.
+
Dagegen können Knoten nicht wie normale Objekte erzeugt werden. Man muss die Methoden von TDOMDocument für die Erzeugung verwenden und sie danach mit anderen Methoden an die richtige Stelle zu bringen. Der Grund dafür ist, dass die Knoten einem speziellen Dokument auf DOM gehören müssen.
  
 
Nachfolgend sind einige gebräuchliche Methoden von TDOMDocument:
 
Nachfolgend sind einige gebräuchliche Methoden von TDOMDocument:
  
<delphi>
+
<syntaxhighlight lang=pascal>
 
   function CreateElement(const tagName: DOMString): TDOMElement; virtual;
 
   function CreateElement(const tagName: DOMString): TDOMElement; virtual;
 
   function CreateTextNode(const data: DOMString): TDOMText;
 
   function CreateTextNode(const data: DOMString): TDOMText;
Line 148: Line 155:
 
     virtual;
 
     virtual;
 
   function CreateAttribute(const name: DOMString): TDOMAttr; virtual;
 
   function CreateAttribute(const name: DOMString): TDOMAttr; virtual;
</delphi>
+
</syntaxhighlight>
  
Und jetzt eine Beispielsmethode, die das ausgewählte Element auf einem TTreeView lokalisiert und einen Kindknoten in das entsprechende XML Dokument einfügt. Der TreeView muss vorher mit den Inhalten einer XML Datei unter Verwendung der [[Networking#Populating a TreeView with XML|XML2Tree Funktion]] gefüllt werden.
+
Und jetzt eine Beispielsmethode, die das ausgewählte Element auf einem TTreeView lokalisiert und einen Kindknoten in das entsprechende XML-Dokument einfügt. Der TreeView muss vorher mit den Inhalten einer XML-Datei unter Verwendung der [[Networking#Populating a TreeView with XML|XML2Tree Funktion]] gefüllt werden.
  
<delphi>
+
<syntaxhighlight lang=pascal>
 
procedure TForm1.actAddChildNode(Sender: TObject);
 
procedure TForm1.actAddChildNode(Sender: TObject);
 
var
 
var
Line 186: Line 193:
 
   end;
 
   end;
 
end;
 
end;
</delphi>
+
</syntaxhighlight>
  
 
=== Erzeugen eines TXMLDocument aus einem String ===
 
=== Erzeugen eines TXMLDocument aus einem String ===
  
Ist eine XML Datei in MyXmlString gegeben, erzeugt der folgende Code ihre DOM:
+
Ist eine XML-Datei in MyXmlString gegeben, erzeugt der folgende Code Ihre DOM:
  
<delphi>
+
<syntaxhighlight lang=pascal>
 
Var
 
Var
 
   S : TStringStream;
 
   S : TStringStream;
Line 202: Line 209:
 
     S.Position:=0;
 
     S.Position:=0;
 
     XML:=Nil;
 
     XML:=Nil;
     ReadXMLFile(XML,S); // Komplettes XML Dokument
+
     ReadXMLFile(XML,S); // Komplettes XML-Dokument
 
     // Alternativ:
 
     // Alternativ:
     ReadXMLFragment(AParentNode,S); // Nur das XML Fragment lesen.
+
     ReadXMLFragment(AParentNode,S); // Nur das XML-Fragment lesen.
 
   Finally
 
   Finally
 
     S.Free;
 
     S.Free;
 
   end;
 
   end;
 
end;
 
end;
</delphi>
+
</syntaxhighlight>
 +
 
 +
=== Überprüfen der Gültigkeit der Struktur einer XML-Datei ===
 +
 
 +
Seit März 2007 besitzt der FCL XML-Parser die Fähigkeit ein XML-Dokument anhand einer DTD zu überprüfen. Dabei wird überprüft, ob die logische Struktur des Dokumentes mit vordefinierten Regeln aus einer ''Document Type Definition'' (DTD) übereinstimmt. Diese Technik wird auch bei Webseiten mit HMTL angewendet.
 +
 
 +
Hier ist ein kleines Beispiel einer XML-Datei mit interner DTD:
 +
 
 +
<syntaxhighlight lang="xml">
 +
  <?xml version='1.0'?>
 +
  <!DOCTYPE root [
 +
  <!ELEMENT root (child)+ >
 +
  <!ELEMENT child (#PCDATA)>
 +
  ]>
 +
  <root>
 +
    <child>This is a first child.</child>
 +
    <child>And this is the second one.</child>
 +
  </root>
 +
</syntaxhighlight>
 +
 
 +
Diese DTD legt als 'root' als Wurzelelement fest. Dieses Wurzelelement muss mindestens ein Kindelement mit dem Namen 'child' besitzen. Diese 'child'-Elemente dürfen nur Buchstaben (PCHDATA = parsed character data, verarbeite Buchstaben-Daten) enthalten. Wenn der Parser irgendwelche Abweichungen gegenüber diesen Regeln feststellt, wird er diese melden.
 +
 
 +
Durch das Überprüfen der Dokumentstruktur ist das Laden der XML-Datei etwas komplizierter. In diesem Beispiel können wir auf die XML-Datei über ein TStream-Objekt zugreifen:
 +
 
 +
<syntaxhighlight lang=pascal>procedure TMyObject.DOMFromStream(AStream: TStream);
 +
var
 +
  Parser: TDOMParser;
 +
  Src: TXMLInputSource;
 +
  TheDoc: TXMLDocument;
 +
begin
 +
  try
 +
    // ein neues Parserobjekt erstellen
 +
    Parser := TDOMParser.Create;
 +
    // die XML-Datei muss über ein TXMLInputSource-Objekt geladen werden
 +
    Src := TXMLInputSource.Create(AStream);
 +
    // wir wollen eine Überprüfung der Dokumentstruktur
 +
    Parser.Options.Validate := True;
 +
    // Festlegen einer Methode, die bei Fehlern aufgerufen wird
 +
    Parser.OnError := @ErrorHandler;
 +
    // nun beginnen wir die Überprüfung
 +
    Parser.Parse(Src, TheDoc);
 +
    // ... und räumen hinterher wieder auf
 +
  finally
 +
    Src.Free;
 +
    Parser.Free;
 +
  end;
 +
end;
 +
 
 +
procedure TMyObject.ErrorHandler(E: EXMLReadError);
 +
begin
 +
  if E.Severity = esError then  // wir sind nur in Fehlern bezüglich der Verletzung der DTD interessiert
 +
    writeln(E.Message);
 +
  // an dieser Stelle können wir auch alles andere machen, was bei einem Fehler getan werden sollte
 +
end;</syntaxhighlight>
 +
 
 +
=== Whitespace-Zeichen ===
 +
Wenn Sie führende Whitespace-Zeichen in den Knotentexten erhalten wollen, dann ist obige Methode der richtige Weg zum Laden Ihres Dokuments. Führende Whitespace-Zeichen werden standardgemäß ignoriert. Dies ist der Grund, warum die Funktion 'ReadXML(...)' niemals die Whitespace-Zeichen in Knotentexten zurückgibt.
 +
Vor dem Aufruf von ''Parser.Parse(Src, TheDoc)'' fügen Sie folgende Zeile ein:
 +
 
 +
<syntaxhighlight lang=pascal>Parser.Options.PreserveWhitespace := True;</syntaxhighlight>
 +
 
 +
Dadurch zwingt man den Parser dazu, alle Whitespace-Zeichen zu übergeben. Dies schließt auch alle Zeilenendezeichen ein, die in einem XML-Dokument nur zur besseren Lesbarkeit stehen!
 +
 
 +
=== Erzeugen einer XML-Datei ===
 +
 
 +
Nachfolgend ist der komplette Code für das Schreiben in eine XML-Datei.
 +
(Er wurde einem Tutorial des DeveLazarus-Blogs entnommen.)
 +
Bitte denken Sie an den Verweis auf die Bibliotheken DOM und XMLWrite in der 'uses'-Klausel.
 +
 
 +
<syntaxhighlight lang=pascal>unit Unit1;
 +
 
 +
{$mode objfpc}{$H+}
 +
 
 +
interface
 +
 
 +
uses
 +
  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls,
 +
  DOM, XMLWrite;
 +
 
 +
type
 +
  { TForm1 }
 +
  TForm1 = class(TForm)
 +
    Button1: TButton;
 +
    Label1: TLabel;
 +
    Label2: TLabel;
 +
    procedure Button1Click(Sender: TObject);
 +
  private
 +
    { private declarations }
 +
  public
 +
    { public declarations }
 +
  end;
 +
 
 +
var
 +
  Form1: TForm1;
 +
 
 +
implementation
 +
 
 +
{ TForm1 }
 +
 
 +
procedure TForm1.Button1Click(Sender: TObject);
 +
var
 +
  Doc: TXMLDocument;                                        // Variable für das Dokument
 +
  RootNode, parentNode, nofilho: TDOMNode;                  // Variable für die Elemente (Knoten)
 +
begin
 +
  try
 +
    // Erzeuge ein Dokument
 +
    Doc := TXMLDocument.Create;
 +
 
 +
    // Erzeuge einen Wurzelknoten
 +
    RootNode := Doc.CreateElement('register');
 +
    Doc.Appendchild(RootNode);                              // sichere den Wurzelelement 
 +
    // Create a parent node
 +
    RootNode:= Doc.DocumentElement;
 +
    parentNode := Doc.CreateElement('usuario');
 +
    TDOMElement(parentNode).SetAttribute('id', '001');      // erzeuge die Attribute für das Elternelement
 +
    RootNode.Appendchild(parentNode);                        // sichere das Elternelement
 +
 
 +
    // Create a child node
 +
    parentNode := Doc.CreateElement('nome');                // erzeuge einen Kindelement
 +
    // TDOMElement(parentNode).SetAttribute('sexo', 'M');    // erzeuge die Attribute
 +
    nofilho := Doc.CreateTextNode('Fernando');              // füge einen Wert für den Knoten ein
 +
    parentNode.Appendchild(nofilho);                        // sichere den Knoten
 +
    RootNode.ChildNodes.Item[0].AppendChild(parentNode);    // füge das Kindelement in das Elternelement ein
 +
 +
    // Create a child node
 +
    parentNode := Doc.CreateElement('idade');                // erzeuge einen Kindelement
 +
    // TDOMElement(parentNode).SetAttribute('ano', '1976');  // erzeuge die Attribute
 +
    nofilho := Doc.CreateTextNode('32');                    // füge einen Wert für den Knoten ein
 +
    parentNode.Appendchild(nofilho);                        // sichere den Knoten
 +
    RootNode.ChildNodes.Item[0].AppendChild(parentNode);    // füge das Kindelement in das Elternelement ein
 +
 
 +
    writeXMLFile(Doc, 'test.xml');                          // schreibe in die XML-Datei
 +
  finally
 +
    Doc.Free;                                                // gib den Speicher frei
 +
  end;
 +
end;
 +
 
 +
initialization
 +
  {$I unit1.lrs}
 +
 
 +
end.</syntaxhighlight>
 +
 
 +
Das Ergebnis steht in folgender XML-Datei:
 +
<syntaxhighlight lang="xml"><?xml version="1.0"?>
 +
<register>
 +
  <usuario id="001">
 +
    <nome>Fernando</nome>
 +
    <idade>32</idade>
 +
  </usuario>
 +
</register></syntaxhighlight>
 +
 
 +
--[[User:Fernandosinesio|Fernandosinesio]] 22:28, 24 April 2008 (CEST)fernandosinesio@gmail.com
 +
 
 +
=== Encoding ===
 +
 
 +
Seit der SVN Revision 12582, ist der XML-Reader fähig, Daten in einer beliebigen Kodierung zu verarbeiten durch den Einsatz externer Dekoder. Siehe [[XML_Decoders]] für weitere Details.
 +
 
 +
Nach den XML-Standards ist das Encoding-Attribut in der ersten Zeile einer XML-Datei optional, falls die tatsächliche Kodierung UTF-8 oder UTF-16 ist (was durch Vorhandensein des BOM erkannt wird). In Lazarus Version 0.9.26 hat TXMLDocument eine Eigenschaft Encoding, die aber momentan ignoriert wird. writeXMLFile benutzt immer UTF-8 und erzeugt kein Encoding-Attribut in der ersten Zeile der XML-Datei.
 +
 
 +
== Siehe auch ==
 +
 
 +
* [[XML Decoders]]
 +
* [[Using INI Files/de| Einsatz von INI-Dateien]]
 +
* [[fcl-xml]]
  
 
== Externe Links ==
 
== Externe Links ==
  
* [http://www.w3schools.com/xml/default.asp W3Schools] XML Tutorial
+
* [http://www.w3schools.com/xml/default.asp W3Schools] Xml Tutorial
  
* [http://www.thomas-zastrow.de/texte/fpcxml/index.php Thomas Zastrow Artikel] FPC und XML
+
* [http://www.thomas-zastrow.de/texte/fpcxml/index.php Thomas Zastrows Artikel] [http://web.archive.org/web/20080802150722/http://www.thomas-zastrow.de/texte/fpcxml/index.php Alternativer Link] FPC und XML

Latest revision as of 02:41, 2 March 2020

Deutsch (de) English (en) español (es) français (fr) magyar (hu) Bahasa Indonesia (id) italiano (it) 日本語 (ja) 한국어 (ko) português (pt) русский (ru) 中文(中国大陆)‎ (zh_CN)

Zurück zu den Zusätzlichen Informationen.


Einleitung

Die Extensible Markup Language ist eine von W3C empfohlene Sprache, die für den Informationsaustausch zwischen verschiedenen Systemen geschaffen wurde. Sie ist eine textbasierte Möglichkeit, um Informationen zu speichern. Moderne Datenaustauschsprachen wie XHTML, ebenso wie die meisten WebServices Technologien, basieren auf XML.

Gegenwärtig gibt es eine Reihe von Units, die XML unter Free Pascal unterstützen. Diese Units sind "XMLRead", "XMLWrite" und "DOM" und sind ein Teil der Free Component Library (FCL) des Free Pascal Compilers. Die FCL ist bereits im Standard-Suchpfad für den Compiler in Lazarus. Daher müssen Sie nur die Units zu Ihrem uses Abschnitt hinzufügen, um die XML Unterstützung zu erhalten. Die FCL ist gegenwärtig (Oktober 2005) noch nicht dokumentiert. Daher hat dieses kurze Tutorial das Ziel, einen Einstieg in XML unter Verwendung dieser Units zu bieten.

Das XML DOM (Document Object Model) ist eine Reihe standardisierter Objekte, die eine ähnliche Schnittstelle für die Benutzung von XML für verschiedene Sprachen und Systeme bieten. Der Standard spezifiziert nur die Methoden, Eigenschaften und andere Schnittstellen Teile des Objekts. Die Implementierung in verschiedenen Sprachen ist frei gelassen. Die FCL unterstützt gegenwärtig vollständig das XML DOM 1.0.

Beispiele

Unten finden Sie eine Liste von Beispielen zur XML-Datenmanipulation mit wachsender Komplexität.

Lesen eines Textknotens

Für Delphi Programmierer: Wenn Sie mit TXMLDocument arbeiten, ist zu beachten, dass der Text innerhalb eines Knotens ein separater Textknoten ist. Deshalb müssen Sie auf den Text eines Knotens als separaten Knoten zugreifen. Gehen Sie zum Beispiel von folgender XML-Datei aus:

 <?xml version="1.0"?>
 <request>
   <request_type>PUT_FILE</request_type>
   <username>123</username>
   <password>abc</password>
 </request>

Das folgende Code-Beispiel zeigt sowohl den richtigen als auch den falschen Weg, um den Wert eines Textknotens zu erhalten:

 var
  PassNode: TDOMNode;
  Doc:      TXMLDocument;
 begin
  // Einlesen der xml Datei
  ReadXMLFile(Doc, 'c:\xmlfiles\test.xml');
  // Abrufen des "password" Knotens
  PassNode := Doc.DocumentElement.FindNode('password');
  // Ausgeben des Wertes des gewählten Knotens
  WriteLn(PassNode.NodeValue); // wird leer sein
  // Der Text des Knotens ist ein separater Kindknoten
  WriteLn(PassNode.FirstChild.NodeValue); // gibt "abc" korrekt aus

Ausgeben der Knotennamen

Das folgende Beispiel zeigt, wie man die Knotennamen in einem Memo (platziert auf einem Formular) ausgibt.

Unterhalb sehen Sie die XML-Datei namens 'C:\Programas\teste.xml':

 <?xml version="1.0"?>
 <images directory="mydir">
  <imageNode URL="graphic.jpg" title="">
    <Peca DestinoX="0" DestinoY="0">Pecacastelo.jpg1.swf</Peca>
    <Peca DestinoX="0" DestinoY="86">Pecacastelo.jpg2.swf</Peca>
  </imageNode>
 </images>

Und hier der Pascal Code um die Aufgabe auszuführen:

 var
   Documento: TXMLDocument;
   i, j: Integer;
 begin
   ReadXMLFile(Documento, 'C:\Programas\teste.xml');
   Memo.Lines.Clear;
   with Documento.DocumentElement.ChildNodes do
   begin
     for i := 0 to (Count - 1) do
     begin
       Memo.Lines.Add(Item[i].NodeName + ' ' + Item[i].Attributes.Item[0].NodeValue);
       for j := 0 to (Item[i].ChildNodes.Count - 1) do
       begin
         Memo.Lines.Add(Item[i].ChildNodes.Item[j].NodeName + ' '
          + Item[i].ChildNodes.Item[j].FirstChild.NodeValue);
       end;
     end;
   end;
   Documento.Free;
 end;

Dies führt zur Ausgabe von:

imageNode graphic.jpg
Peca Pecacastelo.jpg1.swf
Peca Pecacastelo.jpg1.swf

Füllen eines TreeView mit XML

Eine übliche Verwendung von XML Dateien ist, sie zu analysieren und ihren Inhalt in einem baumartigen Format anzuzeigen. Sie können die TTreeView-Komponente auf dem "Common Controls" Tab von Lazarus finden.

Die Funktion unten nimmt ein zuvor geladenes oder im Code erzeugtes XML-Dokument und füllt einen TreeView mit seinen Inhalten. Die Beschriftung jedes Knotens ist der Inhalt des ersten Attributs eines jeden Knotens.

procedure TForm1.XML2Tree(tree: TTreeView; XMLDoc: TXMLDocument);
var
  iNode: TDOMNode;

  procedure ProcessNode(Node: TDOMNode; TreeNode: TTreeNode);
  var
    cNode: TDOMNode;
  begin
    if Node = nil then Exit; // Aufhören, wenn ein Blatt erreicht ist
    
    // Einen Knoten zum Baum hinzufügen
    if Node.HasAttributes then
        TreeNode := tree.Items.AddChild(TreeNode, Node.Attributes[0].NodeValue)
    else
        TreeNode := tree.Items.Addchild(TreeNode, '');

    // Zum Kindknoten weiter gehen
    cNode := Node.ChildNodes.Item[0];

    // Alle Kindknoten bearbeiten
    while cNode <> nil do
    begin
      ProcessNoDe(cNode, TreeNode);
      cNode := cNode.NextSibling;
    end;
  end;
    
begin
  iNode := XMLDoc.DocumentElement.ChildNodes.Item[0];
  while iNode <> nil do
  begin
    ProcessNode(iNode, nil); // Rekursiv
    iNode := iNode.NextSibling;
  end;
end;

Modifizieren eines XML-Dokuments

Das wichtigste, was man sich merken muss ist, dass 'TDOMDocument' das "Handle" für DOM ist. Eine Instanz dieser Klasse erhält man, indem man eine erzeugt oder indem man ein XML-Dokument lädt.

Dagegen können Knoten nicht wie normale Objekte erzeugt werden. Man muss die Methoden von TDOMDocument für die Erzeugung verwenden und sie danach mit anderen Methoden an die richtige Stelle zu bringen. Der Grund dafür ist, dass die Knoten einem speziellen Dokument auf DOM gehören müssen.

Nachfolgend sind einige gebräuchliche Methoden von TDOMDocument:

   function CreateElement(const tagName: DOMString): TDOMElement; virtual;
   function CreateTextNode(const data: DOMString): TDOMText;
   function CreateCDATASection(const data: DOMString): TDOMCDATASection;
     virtual;
   function CreateAttribute(const name: DOMString): TDOMAttr; virtual;

Und jetzt eine Beispielsmethode, die das ausgewählte Element auf einem TTreeView lokalisiert und einen Kindknoten in das entsprechende XML-Dokument einfügt. Der TreeView muss vorher mit den Inhalten einer XML-Datei unter Verwendung der XML2Tree Funktion gefüllt werden.

procedure TForm1.actAddChildNode(Sender: TObject);
var
  Posicao: Integer;
  NovoNo: TDomNode;
begin
  {*******************************************************************
  *  Ausgewähltes Element bestimmen
  *******************************************************************}
  if TreeView1.Selected = nil then Exit;

  if TreeView1.Selected.Level = 0 then
  begin
    Posicao := TreeView1.Selected.Index;

    NovoNo := XMLDoc.CreateElement('item');
    TDOMElement(NovoNo).SetAttribute('nome', 'Item');
    TDOMElement(NovoNo).SetAttribute('arquivo', 'Arquivo');
    XMLDoc.DocumentElement.ChildNodes.Item[Posicao].AppendChild(NovoNo);

    {*******************************************************************
    *  Den TreeView updaten
    *******************************************************************}
    TreeView1.Items.Clear;
    XML2Tree(TreeView1, XMLDoc);
  end
  else if TreeView1.Selected.Level >= 1 then
  begin
    {*******************************************************************
    *  Diese Funktion bearbeitet nur eine Ebene des Baumes,
    *  kann aber leicht so geändert werden, dass eine beliebige Anzahl von Ebenen bearbeitet wird.
    *******************************************************************}
  end;
end;

Erzeugen eines TXMLDocument aus einem String

Ist eine XML-Datei in MyXmlString gegeben, erzeugt der folgende Code Ihre DOM:

Var
  S : TStringStream;
  XML : TXMLDocument;

begin
  S:= TStringStream.Create(MyXMLString);
  Try
    S.Position:=0;
    XML:=Nil;
    ReadXMLFile(XML,S); // Komplettes XML-Dokument
    // Alternativ:
    ReadXMLFragment(AParentNode,S); // Nur das XML-Fragment lesen.
  Finally
    S.Free;
  end;
end;

Überprüfen der Gültigkeit der Struktur einer XML-Datei

Seit März 2007 besitzt der FCL XML-Parser die Fähigkeit ein XML-Dokument anhand einer DTD zu überprüfen. Dabei wird überprüft, ob die logische Struktur des Dokumentes mit vordefinierten Regeln aus einer Document Type Definition (DTD) übereinstimmt. Diese Technik wird auch bei Webseiten mit HMTL angewendet.

Hier ist ein kleines Beispiel einer XML-Datei mit interner DTD:

  <?xml version='1.0'?>
  <!DOCTYPE root [
  <!ELEMENT root (child)+ >
  <!ELEMENT child (#PCDATA)>
  ]>
  <root>
    <child>This is a first child.</child>
    <child>And this is the second one.</child>
  </root>

Diese DTD legt als 'root' als Wurzelelement fest. Dieses Wurzelelement muss mindestens ein Kindelement mit dem Namen 'child' besitzen. Diese 'child'-Elemente dürfen nur Buchstaben (PCHDATA = parsed character data, verarbeite Buchstaben-Daten) enthalten. Wenn der Parser irgendwelche Abweichungen gegenüber diesen Regeln feststellt, wird er diese melden.

Durch das Überprüfen der Dokumentstruktur ist das Laden der XML-Datei etwas komplizierter. In diesem Beispiel können wir auf die XML-Datei über ein TStream-Objekt zugreifen:

procedure TMyObject.DOMFromStream(AStream: TStream);
var
  Parser: TDOMParser;
  Src: TXMLInputSource;
  TheDoc: TXMLDocument;
begin
  try
    // ein neues Parserobjekt erstellen
    Parser := TDOMParser.Create;
    // die XML-Datei muss über ein TXMLInputSource-Objekt geladen werden
    Src := TXMLInputSource.Create(AStream);
    // wir wollen eine Überprüfung der Dokumentstruktur
    Parser.Options.Validate := True;
    // Festlegen einer Methode, die bei Fehlern aufgerufen wird
    Parser.OnError := @ErrorHandler;
    // nun beginnen wir die Überprüfung
    Parser.Parse(Src, TheDoc);
    // ... und räumen hinterher wieder auf
  finally
    Src.Free;
    Parser.Free;
  end;
end;

procedure TMyObject.ErrorHandler(E: EXMLReadError);
begin
  if E.Severity = esError then  // wir sind nur in Fehlern bezüglich der Verletzung der DTD interessiert
    writeln(E.Message);
  // an dieser Stelle können wir auch alles andere machen, was bei einem Fehler getan werden sollte
end;

Whitespace-Zeichen

Wenn Sie führende Whitespace-Zeichen in den Knotentexten erhalten wollen, dann ist obige Methode der richtige Weg zum Laden Ihres Dokuments. Führende Whitespace-Zeichen werden standardgemäß ignoriert. Dies ist der Grund, warum die Funktion 'ReadXML(...)' niemals die Whitespace-Zeichen in Knotentexten zurückgibt. Vor dem Aufruf von Parser.Parse(Src, TheDoc) fügen Sie folgende Zeile ein:

Parser.Options.PreserveWhitespace := True;

Dadurch zwingt man den Parser dazu, alle Whitespace-Zeichen zu übergeben. Dies schließt auch alle Zeilenendezeichen ein, die in einem XML-Dokument nur zur besseren Lesbarkeit stehen!

Erzeugen einer XML-Datei

Nachfolgend ist der komplette Code für das Schreiben in eine XML-Datei. (Er wurde einem Tutorial des DeveLazarus-Blogs entnommen.) Bitte denken Sie an den Verweis auf die Bibliotheken DOM und XMLWrite in der 'uses'-Klausel.

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls,
  DOM, XMLWrite;

type
  { TForm1 }
  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    Label2: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;
  
var
  Form1: TForm1;
  
implementation

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var
  Doc: TXMLDocument;                                         // Variable für das Dokument
  RootNode, parentNode, nofilho: TDOMNode;                   // Variable für die Elemente (Knoten)
begin
  try
    // Erzeuge ein Dokument
    Doc := TXMLDocument.Create;

    // Erzeuge einen Wurzelknoten
    RootNode := Doc.CreateElement('register');
    Doc.Appendchild(RootNode);                               // sichere den Wurzelelement   
    // Create a parent node
    RootNode:= Doc.DocumentElement;
    parentNode := Doc.CreateElement('usuario');
    TDOMElement(parentNode).SetAttribute('id', '001');       // erzeuge die Attribute für das Elternelement
    RootNode.Appendchild(parentNode);                        // sichere das Elternelement

    // Create a child node
    parentNode := Doc.CreateElement('nome');                 // erzeuge einen Kindelement
    // TDOMElement(parentNode).SetAttribute('sexo', 'M');    // erzeuge die Attribute
    nofilho := Doc.CreateTextNode('Fernando');               // füge einen Wert für den Knoten ein
    parentNode.Appendchild(nofilho);                         // sichere den Knoten
    RootNode.ChildNodes.Item[0].AppendChild(parentNode);     // füge das Kindelement in das Elternelement ein
 
    // Create a child node
    parentNode := Doc.CreateElement('idade');                // erzeuge einen Kindelement
    // TDOMElement(parentNode).SetAttribute('ano', '1976');  // erzeuge die Attribute
    nofilho := Doc.CreateTextNode('32');                     // füge einen Wert für den Knoten ein
    parentNode.Appendchild(nofilho);                         // sichere den Knoten
    RootNode.ChildNodes.Item[0].AppendChild(parentNode);     // füge das Kindelement in das Elternelement ein

    writeXMLFile(Doc, 'test.xml');                           // schreibe in die XML-Datei
  finally
    Doc.Free;                                                // gib den Speicher frei
  end;
end;

initialization
  {$I unit1.lrs}

end.

Das Ergebnis steht in folgender XML-Datei:

<?xml version="1.0"?>
<register>
  <usuario id="001">
    <nome>Fernando</nome>
    <idade>32</idade>
  </usuario>
</register>

--Fernandosinesio 22:28, 24 April 2008 (CEST)fernandosinesio@gmail.com

Encoding

Seit der SVN Revision 12582, ist der XML-Reader fähig, Daten in einer beliebigen Kodierung zu verarbeiten durch den Einsatz externer Dekoder. Siehe XML_Decoders für weitere Details.

Nach den XML-Standards ist das Encoding-Attribut in der ersten Zeile einer XML-Datei optional, falls die tatsächliche Kodierung UTF-8 oder UTF-16 ist (was durch Vorhandensein des BOM erkannt wird). In Lazarus Version 0.9.26 hat TXMLDocument eine Eigenschaft Encoding, die aber momentan ignoriert wird. writeXMLFile benutzt immer UTF-8 und erzeugt kein Encoding-Attribut in der ersten Zeile der XML-Datei.

Siehe auch

Externe Links