Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Jabber XMLStream parsen (https://www.delphipraxis.net/63547-jabber-xmlstream-parsen.html)

Luckie 20. Feb 2006 14:51


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:
<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>
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: http://jabbercom.sourceforge.net/xmlcom.html

Das habe ich bisher:
Delphi-Quellcode:
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;
Hier noch ein anderer Versuch:
Delphi-Quellcode:
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;
Damit bekomme ich den tag "foobar" aber nicht mehr den Tag "color". :(

Ich habe auch schon versucht das ganze mit einem XMLTag oder XMLNode als Paramter aufzubauen, aber da bin ich immer genauso stecken geblieben.

Luckie 20. Feb 2006 16:00

Re: Jabber XMLStream parsen
 
Oder erstmal nicht rekursiv:
Delphi-Quellcode:
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;
Da bekomme ich in Zeile 22 eine AV und weiter geht es dann nicht.

marabu 20. Feb 2006 19:18

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:
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;
Grüße vom marabu

Luckie 20. Feb 2006 21:53

Re: Jabber XMLStream parsen
 
Danke für deine Hilfe, ich werde das morgen an der Arbeit mal ausprobieren. ;)

Luckie 21. Feb 2006 08:09

Re: Jabber XMLStream parsen
 
Also so geht es erstmal ohne das sich eine AV bekomme:
Delphi-Quellcode:
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;
Aber an den untergeordneten Tag von foobar komme ich immer noch nicht dran. :(

Luckie 21. Feb 2006 08:39

Re: Jabber XMLStream parsen
 
Nachtrag: Ich habe jetzt daraus mal eine Funktion gemacht, denn die ShowMessage nützt mir ja nichts. ,)
Delphi-Quellcode:
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;
Jetzt fehlt mir aber der erste Tag, nämlich foobar. :gruebel:

marabu 21. Feb 2006 09:22

Re: Jabber XMLStream parsen
 
Und ich habe immer noch keinen Test-Server am Laufen, aber schau mal:

Delphi-Quellcode:
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;
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!

marabu

Luckie 21. Feb 2006 10:12

Re: Jabber XMLStream parsen
 
Hm, werde ich mir gleich mal angucken. Dank dir noch mal.

Luckie 21. Feb 2006 10:49

Re: Jabber XMLStream parsen
 
Prima das klappt wunderbar. :P Nur wie komme ich jetzt an die Daten von einem Tag dran?
Code:
<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>
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:

Frickeldrecktuxer_TM 21. Feb 2006 12:11

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

Luckie 21. Feb 2006 12:19

Re: Jabber XMLStream parsen
 
Jupp, hast Recht. So geht es:
Delphi-Quellcode:
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;
:thumb: Danke noch mal.

Luckie 21. Feb 2006 15:00

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:
s := GetFontColor(Tag.Children);
ShowMessage(s);
In der Funktion GetFontColor zeigt mir ShowMessage den String noch an. Nach dem Funktionsaufruf ist der Rückgabewert jedoch leer? :gruebel:

marabu 21. Feb 2006 15:06

Re: Jabber XMLStream parsen
 
Das Problem ist nun wirklich klein:

Delphi-Quellcode:
// ...
        if xn.Name = 'color' then
        begin
          s := (xn as IXMLTag).Data;
          ShowMessage(s);
          result := s;
        end else
          Result := GetFontColor(children);
// ...
marabu

Luckie 21. Feb 2006 15:10

Re: Jabber XMLStream parsen
 
Ächtz. Acht Stunden am Stück vorm Computer sitzen scheint tötlich zu sein. :oops: Dank dir. ;)

Luckie 22. Feb 2006 11:47

Re: Jabber XMLStream parsen
 
Jetzt wollte ich das in eine rekursive Funktion umbauen:
Delphi-Quellcode:
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;
Da bekomme ich aber in Zeile 14 den Fehler zur Laufzeit:
Zitat:

'Schnittstelle nicht unterstützt'.
Idee war es, das ganze in einem Treeview mit den entsprechenden Ebenen darzustellen, irgendwie oder so. :gruebel: Ich hätte dann noch eine globale Integer Variable mitgeführt, die entsprechend der Ebene hoch oder runtergesetzt wird oder so eben. Ich weiß noch nicht ganz genau, wie das gehen soll.

marabu 22. Feb 2006 13:04

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

Luckie 22. Feb 2006 13:28

Re: Jabber XMLStream parsen
 
Danke. Werde ich mir mal angucken.

Frickeldrecktuxer_TM 22. Feb 2006 13:35

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?

Luckie 23. Feb 2006 08:10

Re: Jabber XMLStream parsen
 
Vergessen wir das erstmal. Das war noch eine ziemlich unausgereifte Idee.

Aber da gibt es noch ein Problem:
Delphi-Quellcode:
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;
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:
Delphi-Quellcode:
procedure TForm1.OnJabberMessage(Sender: TObject; const Msg: IJabberMsg; const Tag: IXMLTag);
var
  sl               : TStringList;
begin
  XI := Tag.Children; // global!!!
Und dann der Aufruf:
Delphi-Quellcode:
procedure TForm1.cbTagsChange(Sender: TObject);
begin
  ShowMessage(cbTags.Text + ': ' + GetTagValue(XI, cbTags.Text));
end;
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?

marabu 23. Feb 2006 14:32

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:
procedure TForm1.OnJabberMessage(Sender: TObject; const Msg: IJabberMsg; const Tag: IXMLTag);
begin
  self.MsgTag := Tag;
  // ...
end;
Jetzt kannst du jederzeit GetTagValue(MsgTag, 'color') rufen und wirst auch gehört. Alternativ geht auch sowas:

Delphi-Quellcode:
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;
Grüße vom marabu

Luckie 23. Feb 2006 14:50

Re: Jabber XMLStream parsen
 
Jupp, datt wars. :thumb:


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:12 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz