Tutorial: Delphi Praxis Shout Box
Ich habe mich aufgrund des Wettbewerbs das 1. Mal mit
XML beschäftigt.
(Wie so viele
)
Es gibt mehrere Wege die Informationen aus dem
XML File zu extrahieren.
Ich werde in diesem
Tutorial 2 einfache Wege beschreiben.
Voraussetzungen:
- Komponente TXMLDocument steht erst ab Delphi 6 Professional zur Verfügung
- die
XML-Datenbindungs-Experten erst ab einer Enterprise Version.
- (Ich habe eine Delphi 7 Enterprise installiert)
- außerdem einen Computer mit Windows
- Internetzugang und Zugriff auf
http://www.delphipraxis.net/rdf.php?shoutbox=1
credits:
-
für den Wettbewerb
- Borland für Delphi und die Delphi Hilfe
- Teile der Delphi 7 - Hilfe wurden hier verwendet (copyright by borland)
- mirage228: Korrektur: Voraussetzungen D6 statt D7
1. Lösungsvorschlag:
Es gibt eine Komponente
TXMLDocument in der Palette
Internet.
Zitat von
Delphi 7 Hilfedatei:
Die Klasse TXMLDocument wird für
XML-Dokumente verwendet.
Damit kann man doch was anfangen!
Mit LoadFromFile kann man eine Datei laden und kommt somit an die Infos ran.
Das ist mir immer noch zu Umständlich, es geht einfacher...
In der Hilfe ist vom
XML-Datenbindungs-Experten zu lesen.
So verwenden Sie den
XML-Datenbindungs-Experten:
0. Zu aller erst speichern Sie die Datei
http://www.delphipraxis.net/rdf.php?shoutbox=1 unter
C:\TEMP\RDF.XML ab.
1. Klicken Sie auf Datei / Neu / Weitere, und wählen Sie unten auf der Registerkarte Neu das Symbol
XML-Datenbindung aus.
2. Der
XML-Datenbindungs-Experte wird angezeigt.
3. Geben Sie auf der ersten Seite des Experten das
XML-Dokument oder Schema an, für das Sie Schnittstellen generieren möchten. Dabei kann es sich um ein
XML-Beispieldokument, eine .DTD-Datei (Dokumenttypdefinition), eine .XDR- Datei (Reduced
XML Data) oder eine .XSD-Datei (
XML-Schemadatei) handeln.
In unserem Beispiel verwenden wir natürlich eine XML Beispieldatei (c:\temp\rdf.xml)
4. Klicken Sie auf die Schaltfläche Optionen, um die Benennungsstrategien anzugeben, die der Experte beim Generieren von Schnittstellen und Implementierungsklassen verwenden soll sowie die Standardzuordnung von im Schema definierten Typen zu nativen Delphi-Datentypen festzulegen.
Sie ändern in dem Beispiel hier nichts!
5. Gehen Sie zum zweiten Dialogfeld des Experten. Dieses Dialogfeld ermöglicht Ihnen die Angabe detaillierter Informationen über jeden Knotentyp im Dokument oder Schema. Auf der linken Seite befindet sich eine Strukturansicht, die alle Knotentypen im Dokument anzeigt. Bei komplexen Knoten (Knoten mit untergeordneten Elementen) kann die Strukturansicht erweitert werden, um die untergeordneten Elemente anzuzeigen. Wenn Sie einen Knoten in dieser Strukturansicht auswählen, werden auf der rechten Seite des Dialogfelds Informationen zu diesem Knoten angezeigt, und Sie können dort angeben, wie der Experte diesen Knoten behandeln soll.
Die Struktur in unserem Beispiel ist folgende:
- Es gibt einen komplexen rdfType der ein Element shout beinhaltet.
- Der shoutType besteht aus 4 Feldern:
-
username : WideString
-
profile : WideString
-
timestamp : WideString
-
message : WideString
Das Steuerelement Quellname zeigt den Namen des Knotentyps im
XML-Schema an.
Das Steuerelement Quelldatentyp zeigt den Typ des Knotenwerts an, wie dieser im
XML-Schema angegeben wurde.
Das Steuerelement Dokumentation ermöglicht Ihnen das Hinzufügen von Kommentaren, die die Verwendung oder den Zweck des Knotens beschreiben.
Falls der Experte Quellcode für den ausgewählten Knoten generiert (falls es sich also um einen komplexen Typ handelt, für den der Experte eine Schnittstelle und eine Implementierungsklasse generiert, oder falls es sich um eines der ungeordneten Elemente eines komplexen Typs handelt, für den der Experte eine Eigenschaft der Schnittstelle des komplexen Typs generiert), können Sie mit dem Kontrollkästchen Bindung erzeugen angeben, ob der Assistent den Quellcode für den Knoten erstellen soll. Wenn Sie Bindung erzeugen deaktivieren, generiert der Experte keine Schnittstelle oder Implementierungsklasse für einen komplexen Typ bzw. erstellt keine Eigenschaft in der übergeordneten Schnittstelle für das untergeordnete Element oder Attribut.
Mit dem Abschnitt Bindungsoptionen können Sie Einfluss darauf nehmen, welchen Quellcode der Experte für das ausgewählte Element generiert. Für jeden Knoten können Sie den Bezeichnername angeben (den Namen der generierten Schnittstelle oder Eigenschaft). Darüber hinaus müssen Sie bei Schnittstellen angeben, welche von ihnen den Stammknoten des Dokuments repräsentiert. Für Knoten, die für Eigenschaften stehen, können Sie den Typ der Eigenschaft angeben, und, falls die Eigenschaft keine Schnittstelle ist, ob es sich um eine schreibgeschützte Eigenschaft handelt.
In dem Beispiel müssen Sie hier nichts verändern
Wenn Sie unnötigen Overhead vermeiden wollen, so können sie beim Zugriffsmodus "Schreibgeschützt" einstellen.
Dadurch werden nur die get_* Methoden erzeugt. Die set_* Methoden verwenden Sie im Beispiel eh nicht.
6. Nach Festlegung des Quellcodes, den der Experte für jeden Knoten generieren soll, gehen Sie zum dritten Dialogfeld über. Dieses Dialogfeld ermöglicht Ihnen die Auswahl einiger globaler Optionen, die steuern, wie der Experte seinen Quellcode generiert, und sie ermöglicht Ihnen außerdem eine Vorschau des generierten Codes. Des Weiteren können Sie hier angeben, wie die gewählten Optionen für die spätere Verwendung gespeichert werden sollen.
Um eine Vorschau des vom Experten generierten Quellcodes zu erhalten, markieren Sie eine Schnittstelle in der Liste Bindungs-Info. Die resultierende Schnittstellendefinition wird anschließend im Steuerelement Code-Vorschau angezeigt.
Mithilfe der Einstellung für die Datenbindung geben Sie an, wie der Experte die gewählten Optionen speichern soll. Sie können die Einstellungen als Anmerkungen in der Schemadatei speichern, die mit dem Dokument verknüpft ist (d. h. in der auf der ersten Registerkarte des Dialogfelds angegebenen Schemadatei), oder Sie können eine unabhängige Schemadatei angeben, die nur vom Experten verwendet wird.
In dem Beispiel müssen Sie die Einstellungen nicht in die *.xdb Datei speichern.
Es schadet aber auch nicht und ist evtl. sinnvoll, wenn Sie den Experten mehrmals aufrufen um etwas zu spielen.
7. Wenn Sie auf Fertig stellen klicken, generiert der Datenbindungs-Experte eine neue
Unit, die Schnittstellen und Implementierungsklassen für alle im
XML-Dokument enthaltenen Knotentypen definiert. Darüber hinaus erstellt er eine globale Funktion, die ein TXMLDocument-Objekt akzeptiert und die Schnittstelle für den Stammknoten der Datenhierarchie zurückgibt.
So nun schauen Sie sich den erzeugten Quellcode an:
(Im Beispiel wurde Zugriffsmodus=Schreibgeschützt gesetzt - Punkt 5)
Einige Zeilen sind mit einem "//" auskommentiert.
Diese sind für den schreibenden Zugriff und werden in unserem Beispiel nicht benötigt.
Sie können die Zeilen löschen.
Delphi-Quellcode:
{***************************************************}
{ }
{ XML-Datenbindung }
{ }
{ Generiert am: 23.05.2004 18:47:14 }
{ Generiert von: C:\TEMP\rdf.xml }
{ Einstellungen gespeichert in: C:\TEMP\rdf.xdb }
{ }
{***************************************************}
unit rdf;
interface
uses xmldom, XMLDoc, XMLIntf;
type
{ Forward-Deklarationen }
IXMLRdfType =
interface;
IXMLShoutType =
interface;
{ IXMLRdfType }
IXMLRdfType =
interface(IXMLNodeCollection)
['
{AB636EA9-A6F0-4E48-A1B8-F6137FED285A}']
{ Eigenschaftszugriff }
function Get_Shout(
Index: Integer): IXMLShoutType;
{ Methoden & Eigenschaften }
// function Add: IXMLShoutType;
// function Insert(const Index: Integer): IXMLShoutType;
property Shout[
Index: Integer]: IXMLShoutType
read Get_Shout;
default;
end;
{ IXMLShoutType }
IXMLShoutType =
interface(IXMLNode)
['
{EC6BF547-7780-4FEF-8ADB-788E6D440DAB}']
{ Eigenschaftszugriff }
function Get_Username: WideString;
function Get_Profile: WideString;
function Get_Timestamp: WideString;
function Get_Message: WideString;
{ Methoden & Eigenschaften }
property Username: WideString
read Get_Username;
property Profile: WideString
read Get_Profile;
property Timestamp: WideString
read Get_Timestamp;
property Message: WideString
read Get_Message;
end;
{ Forward-Deklarationen }
TXMLRdfType =
class;
TXMLShoutType =
class;
{ TXMLRdfType }
TXMLRdfType =
class(TXMLNodeCollection, IXMLRdfType)
protected
{ IXMLRdfType }
function Get_Shout(
Index: Integer): IXMLShoutType;
// function Add: IXMLShoutType;
// function Insert(const Index: Integer): IXMLShoutType;
public
procedure AfterConstruction;
override;
end;
{ TXMLShoutType }
TXMLShoutType =
class(TXMLNode, IXMLShoutType)
protected
{ IXMLShoutType }
function Get_Username: WideString;
function Get_Profile: WideString;
function Get_Timestamp: WideString;
function Get_Message: WideString;
// MaBuSE: hier sind keine Set_* Methoden da Zugriffsmodus Schreibgeschützt ausgewählt wurde
end;
{ Globale Funktionen }
// function Getrdf(Doc: IXMLDocument): IXMLRdfType;
function Loadrdf(
const FileName: WideString): IXMLRdfType;
// function Newrdf: IXMLRdfType;
const
TargetNamespace = '
';
implementation
{ Globale Funktionen }
// function Getrdf(Doc: IXMLDocument): IXMLRdfType;
// begin
// Result := Doc.GetDocBinding('rdf', TXMLRdfType, TargetNamespace) as IXMLRdfType;
// end;
function Loadrdf(
const FileName: WideString): IXMLRdfType;
begin
Result := LoadXMLDocument(FileName).GetDocBinding('
rdf', TXMLRdfType, TargetNamespace)
as IXMLRdfType;
end;
// function Newrdf: IXMLRdfType;
// begin
// Result := NewXMLDocument.GetDocBinding('rdf', TXMLRdfType, TargetNamespace) as IXMLRdfType;
// end;
{ TXMLRdfType }
procedure TXMLRdfType.AfterConstruction;
begin
RegisterChildNode('
shout', TXMLShoutType);
ItemTag := '
shout';
ItemInterface := IXMLShoutType;
inherited;
end;
function TXMLRdfType.Get_Shout(
Index: Integer): IXMLShoutType;
begin
Result := List[
Index]
as IXMLShoutType;
end;
// function TXMLRdfType.Add: IXMLShoutType;
// begin
// Result := AddItem(-1) as IXMLShoutType;
// end;
// function TXMLRdfType.Insert(const Index: Integer): IXMLShoutType;
// begin
// Result := AddItem(Index) as IXMLShoutType;
// end;
{ TXMLShoutType }
function TXMLShoutType.Get_Username: WideString;
begin
Result := ChildNodes['
username'].Text;
end;
function TXMLShoutType.Get_Profile: WideString;
begin
Result := ChildNodes['
profile'].Text;
end;
function TXMLShoutType.Get_Timestamp: WideString;
begin
Result := ChildNodes['
timestamp'].Text;
end;
function TXMLShoutType.Get_Message: WideString;
begin
Result := ChildNodes['
message'].Text;
end;
end.
So nun haben Sie eine Datei "rdf.pas" mit der Sie kinderleicht auf den
XML-Feed der Shout Box zugreifen können.
1. Sie erzeugen eine neue Applikation.
2. Auf das TForm1 legen sie einen TButton und ein TMemo.
3. In die uses das rdf.pas aufnehmen, damit ist das
XML Interface verfügbar.
Delphi-Quellcode:
implementation
{$R *.dfm}
uses rdf;
end.
4. Auf den TButton doppelklicken und folgendes schreiben:
4.1. "Memo1.Clear;" - Damit wird das Memo geleert.
4.2. "var XmlRdf: IXMLRdfType;" - Das ist das Interface aus der rdf.aps Datei die automatisch erstellt wurde.
4.3. "XmlRdf := LoadRdf('C:\TEMP\RDF.XML');" - Hier wird die
XML Datei geöffnet und intern der TXmlDocument Komponente zugewiesen.
4.4. Nun können Sie relativ einfach mit XmlRdf.Shout[i].Message auf die i. Nachricht zugreifen.
4.5. mit einer for Schleife können Sie alle Felder via Memo1.Lines.Add(string) in das Memo schreiben -> fertig
Nun sollten Sie folgenden Quelltext geschrieben haben:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
XmlRdf: IXMLRdfType;
i: Integer;
begin
Memo1.Lines.Clear;
XmlRdf := LoadRdf('C:\TEMP\RDF.XML');
for i := 0 to XmlRdf.Count -1 do
begin
Memo1.Lines.Add(XmlRdf.Shout[i].Timestamp+' - '+XmlRdf.Shout[i].Username+': '+XmlRdf.Shout[i].Message);
end;
end;
5. Wie bekommen Sie die
XML Datei auf Ihren Rechner?
5.1. Die
Unit "urlmon" in die uses Anweisung mit aufnehmen.
5.2. Mit "URLDownloadToFIle(nil, 'Quell-
URL', 'Ziel-Dateiname', 0, nil);" können Sie die Datei einfach downloaden.
URLDownloadToFIle(nil, 'http://www.delphipraxis.net/rdf.php?shoutbox=1', 'C:\TEMP\RDF.XML', 0, nil);
6. Fertig -> Testen
kompletter Quelltext der Unit1.pas:
Delphi-Quellcode:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 =
class(TForm)
Memo1: TMemo;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses rdf, urlmon;
procedure TForm1.Button1Click(Sender: TObject);
var
XmlRdf: IXMLRdfType;
i: Integer;
begin
URLDownloadToFIle(
nil, '
http://www.delphipraxis.net/rdf.php?shoutbox=1', '
C:\TEMP\RDF.XML', 0,
nil);
Memo1.Lines.Clear;
XmlRdf := LoadRdf('
C:\TEMP\RDF.XML');
for i := 0
to XmlRdf.Count -1
do
begin
Memo1.Lines.Add(XmlRdf.Shout[i].Timestamp+'
- '+XmlRdf.Shout[i].Username+'
: '+XmlRdf.Shout[i].
Message);
end;
end;
end.
2. Lösungsvorschlag:
kommt in ein paar Tagen