![]() |
Jabber XMLStream parsen
Ich lege mir beim Senden einer Nachricht ein paar extra Knoten in dem XMLStream an. Der sieht dann so aus:
XML-Code:
Jetzt wollte ich den natürlich wieder auslesen und alle Tags erhalten. Also foobar, color und body. Ich habe versucht dies mit einer rekursiven Prozedur zu lösen, nur bleibe ich immer wieder stecken, weil ich entweder nicht den XMLTag bekomme oder den XMLIterator oder den Inhalt des Tags. Ich weiß auch gar noch nit, wie doe einzelnen Elemente zusammenarbeiten sollen:
<message id="JCOM_2" to="mp@datawerk.de" from="mp-test@datawerk.de/DWJabberClient">
<foobar type="mp-extra-tag"> <color>clOlive</color> </foobar> <body>test</body> </message> ![]() Das habe ich bisher:
Delphi-Quellcode:
Hier noch ein anderer Versuch:
procedure GetTags(AXMLIteratorEx: IXMLIteratorEx);
var XMLIterator: IXMLIteratorEx; XMLTag: IXMLTag; XMLNode: IXMLNode; begin if AXMLIteratorEx.HasNext then begin XMLNode := AXMLIteratorEx.Next; if XMLNode.IsTag then begin ShowMessage(XMLNode.Name); GetTags(XMLTag.Query(XMLNode.Name)); end; end; end;
Delphi-Quellcode:
Damit bekomme ich den tag "foobar" aber nicht mehr den Tag "color". :(
procedure TForm1.GetTags(AXMLIterator: IXMLIterator);
var XMLIterator : IXMLIteratorEx; XMLTag : IXMLTag; XMLNode : IXMLNode; begin if AXMLIterator.HasNext then begin XMLNode := AXMLIterator.Next; if XMLNode.IsTag then begin ShowMessage(XMLNode.Name); XMLTag := JabberSession.CreateXMLTag; GetTags(XMLTag.Query(XMLNode.Name)); end; end; end; Ich habe auch schon versucht das ganze mit einem XMLTag oder XMLNode als Paramter aufzubauen, aber da bin ich immer genauso stecken geblieben. |
Re: Jabber XMLStream parsen
Oder erstmal nicht rekursiv:
Delphi-Quellcode:
Da bekomme ich in Zeile 22 eine AV und weiter geht es dann nicht.
procedure TForm1.OnJabberMessage(Sender: TObject; const Msg: IJabberMsg; const Tag: IXMLTag);
var Nickname : string; XMLIteratorEx : IXMLIteratorEx; XMLNode : IXMLNode; XMLTagIterator : IXMLTagIterator; XMLTag : IXMLTag; XMLCData : IXMLCData; s : string; begin if Assigned(JabberSession.Roster.FindUserID(Msg.FromJID)) then Nickname := JabberSession.Roster.FindUserID(Msg.FromJID).NickName; AddMsgToRTF(rtfMsg, clRed, Now, Nickname, Msg.Body); XMLIteratorEx := Tag.Children; while XMLIteratorEx.HasNext do begin XMLNode := XMLIteratorEx.Next; if XMLNode.IsTag then begin ShowMessage(XMLNode.Name); XMLIteratorEx := XMLTag.Query(XMLNode.Name); XMLNode := XMLIteratorEx.Next; if XMLNode.IsTag then ShowMessage(XMLNode.Name); end; end; end; |
Re: Jabber XMLStream parsen
Hallo Michael,
leider habe ich keine Erfahrung im Umgang mit JabberCom, aber mein Gefühl sagt mir, dass es etwa so gehen könnte:
Delphi-Quellcode:
Grüße vom marabu
procedure GetTags(iter: IXMLIteratorEx);
var xn: IXMLNode; begin while iter.HasNext do begin xn := iter.Next; ShowMessage(xn.Name); if xn.IsTag then with xn as IXMLTag do GetTags(Query('*')); end; end; procedure TDemoForm.JabberSessionMessage(ASender: TObject; const Msg: IJabberMsg; const Tag: IXMLTag); begin with Msg.MsgTag do GetTags(Query('*')); end; |
Re: Jabber XMLStream parsen
Danke für deine Hilfe, ich werde das morgen an der Arbeit mal ausprobieren. ;)
|
Re: Jabber XMLStream parsen
Also so geht es erstmal ohne das sich eine AV bekomme:
Delphi-Quellcode:
Aber an den untergeordneten Tag von foobar komme ich immer noch nicht dran. :(
procedure TForm1.GetTags(iter: IXMLIteratorEx);
var xn: IXMLNode; begin while iter.HasNext do begin xn := iter.Next; if xn.IsTag then with xn as IXMLTag do begin ShowMessage(xn.Name); GetTags(Query('*')); end; end; end; |
Re: Jabber XMLStream parsen
Nachtrag: Ich habe jetzt daraus mal eine Funktion gemacht, denn die ShowMessage nützt mir ja nichts. ,)
Delphi-Quellcode:
Jetzt fehlt mir aber der erste Tag, nämlich foobar. :gruebel:
function TForm1.GetTags(iter: IXMLIteratorEx): String;
var xn: IXMLNode; begin while iter.HasNext do begin xn := iter.Next; if xn.IsTag then with xn as IXMLTag do begin result := xn.Name; GetTags(Query('*')); end; end; end; |
Re: Jabber XMLStream parsen
Und ich habe immer noch keinen Test-Server am Laufen, aber schau mal:
Delphi-Quellcode:
Ich habe deine Message nachgebaut und dann wieder analysiert. Da ich noch nicht weiß, ob die Methode Query() XPath expressions unterstützt, bin ich erstmal auf die property children ausgewichen. Klappt!
procedure GetTags(iter: IXMLIteratorEx; s: TStrings);
var xn: IXMLNode; begin while iter.HasNext do begin xn := iter.Next; if xn.IsTag then with xn as IXMLTag do begin s.Add(Name); GetTags(children, s); end; end; end; procedure TDemoForm.ButtonClick(Sender: TObject); var xt: IXMLTag; s: TStringList; begin s := TStringList.Create; xt := Jabber.CreateXMLTag; with xt do begin Name := 'message'; PutAttrib('id', 'JCOM_2'); PutAttrib('to', 'mp@datawerk.de'); PutAttrib('from', 'mp-test@datawerk.de/DWJabberClient'); with AddTag('foobar') do begin PutAttrib('type', 'mp-extra-tag'); AddBasicTag('color', 'clOlive'); end; ShowMessage(xml); GetTags(children, s); ShowMessage(s.Text); s.Free; end; end; marabu |
Re: Jabber XMLStream parsen
Hm, werde ich mir gleich mal angucken. Dank dir noch mal.
|
Re: Jabber XMLStream parsen
Prima das klappt wunderbar. :P Nur wie komme ich jetzt an die Daten von einem Tag dran?
Code:
Beispielsweise hier an den Wert clOlive? IXMLTag hat zwar die Eigenschaft Data, die diesen Wert wohl enthalten soll, aber mir ist es bisher noch nicht gelungen ihm zu sagen von welchem Tag er den Wert ausgeben soll. :gruebel:
<message id="JCOM_3" to="mp-test@datawerk.de" from="mp@datawerk.de/DWJabberClient">
<foobar type="mp-extra-tag"> <color>clOlive</color> </foobar><body/> </message> |
Re: Jabber XMLStream parsen
ixmltag.data wird wohl die daten des tags auslesen auf den das interface gerade zeigt und weil du die tags durch den iterator alle durchgehst kannst du auch einfach von jedem tag das data-attribut zurückgeben anstatt dem namen
|
Re: Jabber XMLStream parsen
Jupp, hast Recht. So geht es:
Delphi-Quellcode:
:thumb: Danke noch mal.
procedure TForm1.GetTags(iter: IXMLIteratorEx; s: TStrings);
var xn : IXMLNode; begin while iter.HasNext do begin xn := iter.Next; if xn.IsTag then with xn as IXMLTag do begin s.Add(Name+ ': ' + (xn as IXMLTag).Data); GetTags(children, s); end; end; end; |
Re: Jabber XMLStream parsen
Hm, noch ein kleines Problem:
Delphi-Quellcode:
function GetFontColor(iter: IXMLIteratorEx): string;
var xn : IXMLNode; s : string; begin while iter.HasNext do begin xn := iter.Next; if xn.IsTag then with xn as IXMLTag do begin if xn.Name = 'color' then begin s := (xn as IXMLTag).Data; ShowMessage(s); result := s; end; GetFontColor(children); end; end; end;
Delphi-Quellcode:
In der Funktion GetFontColor zeigt mir ShowMessage den String noch an. Nach dem Funktionsaufruf ist der Rückgabewert jedoch leer? :gruebel:
s := GetFontColor(Tag.Children);
ShowMessage(s); |
Re: Jabber XMLStream parsen
Das Problem ist nun wirklich klein:
Delphi-Quellcode:
marabu
// ...
if xn.Name = 'color' then begin s := (xn as IXMLTag).Data; ShowMessage(s); result := s; end else Result := GetFontColor(children); // ... |
Re: Jabber XMLStream parsen
Ächtz. Acht Stunden am Stück vorm Computer sitzen scheint tötlich zu sein. :oops: Dank dir. ;)
|
Re: Jabber XMLStream parsen
Jetzt wollte ich das in eine rekursive Funktion umbauen:
Delphi-Quellcode:
Da bekomme ich aber in Zeile 14 den Fehler zur Laufzeit:
function GetTags(iter: IXMLIteratorEx): string;
var xn : IXMLNode; begin while iter.HasNext do begin xn := iter.Next; if xn.IsTag then with xn as IXMLTag do begin result := (xn as IXMLTag).Name; end else result := GetTags((xn as IXMLTag).Children); end; end; Zitat:
|
Re: Jabber XMLStream parsen
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Michael,
vielleicht kannst du das an deine Bedürfnisse anpassen. Ist weit weg von perfekt, weil ich es schnell aus einem alten XML-Editor von mir heraus operiert und angepasst habe. Grüße vom marabu |
Re: Jabber XMLStream parsen
Danke. Werde ich mir mal angucken.
|
Re: Jabber XMLStream parsen
du prüfst in deiner if-abfrage ob es ein tag ist und im else-zweig nimmst du das objekt tortzdem als ixmltag daher?
|
Re: Jabber XMLStream parsen
Vergessen wir das erstmal. Das war noch eine ziemlich unausgereifte Idee.
Aber da gibt es noch ein Problem:
Delphi-Quellcode:
Diese Funktion soll mir den Inhalt eines Tags zurückgeben. So weit so gut. Funktioniert auch, aber nur einmal, beim ersten Mal. Das Problem wird dfaran liegen, dass ich den Paramter iter global deklarieren musste:
function GetTagValue(iter: IXMLIteratorEx; ATag: String): String;
var xn : IXMLNode; begin while iter.HasNext do begin xn := iter.Next; if xn.IsTag then with xn as IXMLTag do begin if (xn as IXMLTag).Name = ATag then begin result := (xn as IXMLTag).Data; exit; end else begin result := GetTagValue(children, ATag); end; end; end; end;
Delphi-Quellcode:
Und dann der Aufruf:
procedure TForm1.OnJabberMessage(Sender: TObject; const Msg: IJabberMsg; const Tag: IXMLTag);
var sl : TStringList; begin XI := Tag.Children; // global!!!
Delphi-Quellcode:
Ich denke, ich weiß, was passiert: XI steht nach dem Aufruf an der Stelle, an der er was gefunden hatte. Wie löse ich das Problem jetzt am geschicktesten?
procedure TForm1.cbTagsChange(Sender: TObject);
begin ShowMessage(cbTags.Text + ': ' + GetTagValue(XI, cbTags.Text)); end; |
Re: Jabber XMLStream parsen
Hallo Michael,
das Problem hast du richtig erkannt, die Lösung ist denkbar einfach: Nicht das Iterator-Interface global speichern, sondern das Wurzel-Element.
Delphi-Quellcode:
Jetzt kannst du jederzeit GetTagValue(MsgTag, 'color') rufen und wirst auch gehört. Alternativ geht auch sowas:
procedure TForm1.OnJabberMessage(Sender: TObject; const Msg: IJabberMsg; const Tag: IXMLTag);
begin self.MsgTag := Tag; // ... end;
Delphi-Quellcode:
Grüße vom marabu
function ParseStr(var s: string; delimiters: string; purge: boolean = true): string;
var i: integer; begin i := 0; while (i < Length(s)) and (Pos(s[Succ(i)], delimiters) = 0) do Inc(i); Result := Copy(s, 1, i); Delete(s, 1, i + Ord(purge)); end; function TDemoForm.GetData(tag: IXMLTag; path: String): String; var ti: IXMLTagIterator; q: String; begin while Assigned(tag) and (path <> '') do begin q := ParseStr(path, '/'); ti := tag.QueryTag(q); tag := ti.Next; end; if Assigned(tag) then Result := tag.Data else Result := ''; end; procedure TDemoForm.QueryDataActionExecute(Sender: TObject); begin ShowMessage(GetData(MsgTag, 'foobar/color')); end; |
Re: Jabber XMLStream parsen
Jupp, datt wars. :thumb:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:07 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz