1

i work with live stream xml structure , i should to check received xml data to desire which way to select , the problem is xml stream is multi level as shown below, all me tests Stuck with the first phase

server response xml :

<?xml version='1.0' encoding='UTF-8'?>
<stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" from="messenger.tashbik.com" id="40d07647" xml:lang="en" version="1.0">

<stream:features>
<starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"></starttls>
<mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
<mechanism>DIGEST-MD5</mechanism>
<mechanism>PLAIN</mechanism>
<mechanism>CRAM-MD5</mechanism>
</mechanisms>

<compression xmlns="http://jabber.org/features/compress">
<method>zlib</method>
</compression>

<auth xmlns="http://jabber.org/features/iq-auth"/>
<register xmlns="http://jabber.org/features/iq-register"/>
</stream:features>

how can i check all xml stream from top to down and access any level i want ?. as example i want to access stream:features level to check available futures , also i want to jump to the compression level to check it too .

i use NativeXML 4.04

TLama
  • 75,147
  • 17
  • 214
  • 392
Realbitt
  • 388
  • 6
  • 18
  • I don't have a solution to your problem, but I would suggest to use a existing XMPP library and not reinvent the wheel. A awesome library for Delphi is Jopl => http://code.google.com/p/exodus/ – Alex Oct 14 '12 at 19:06

1 Answers1

2

How to access list of child nodes for a particular node ?

There are many ways to list child nodes for a particular node. As the easiest one looks to me to find the node by path and iterate through the Containers indexed property. In the following sample code you can see how do iterate all nodes from the /stream:stream/stream:features node path:

uses
  NativeXml;

procedure TForm1.Button1Click(Sender: TObject);
var
  I: Integer;
  Node: TXMLNode;
  NativeXML: TNativeXML;
begin
  NativeXML := TNativeXML.Create(nil);
  try
    NativeXML.LoadFromFile('c:\Response.xml');
    if Assigned(NativeXML.Root) then
    begin
      Node := NativeXML.Root.FindNode('/stream:stream/stream:features');
      if Assigned(Node) then
        for I := 0 to Node.ContainerCount - 1 do
          ShowMessage(UTF8ToString(Node.Containers[I].Name));
    end;
  finally
    NativeXML.Free;
  end;
end;

How to get child node of a certain node by its name ?

There's also more than one way to go deeper in the XML node tree. When you know the node name, the easiest is to use the NodeByName function, which returns the reference to a child node, when it's found in the root of the parent tree, nil when it's not found. In the next code sample, you can see how to use the NodeByName function to get compression node as first, and from there get to the method node and display its value:

Node := NativeXML.Root.FindNode('/stream:stream/stream:features');
if Assigned(Node) then
begin
  Node := Node.NodeByName('compression');
  if Assigned(Node) then
  begin
    Node := Node.NodeByName('method');
    if Assigned(Node) then
      ShowMessage(UTF8ToString(Node.Value));
  end;
end;

To the same node as in previous example, you can get also e.g. using a direct path like this way:

if Assigned(NativeXML.Root) then
begin
  Node := NativeXML.Root.FindNode('/stream:stream/stream:features/compression/method');
  if Assigned(Node) then
    ShowMessage(UTF8ToString(Node.Value));
end;

The above options are not the only ways to get to the child nodes but they should be enough at least as a starting point. You haven't described what you gonna do with that response file, so it's hard to suggest what might be the best way for you (if choose one of the node iteratations or use path selections).

Your original XML file that I've used for testing:

<?xml version='1.0' encoding='UTF-8'?>
<stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" from="messenger.tashbik.com" id="40d07647" xml:lang="en" version="1.0">    
<stream:features>
   <starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"></starttls>
   <mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
      <mechanism>DIGEST-MD5</mechanism>
      <mechanism>PLAIN</mechanism>
      <mechanism>CRAM-MD5</mechanism>
   </mechanisms>
   <compression xmlns="http://jabber.org/features/compress">
      <method>zlib</method>
   </compression>
   <auth xmlns="http://jabber.org/features/iq-auth"/>
   <register xmlns="http://jabber.org/features/iq-register"/>
</stream:features>
TLama
  • 75,147
  • 17
  • 214
  • 392
  • 1
    perfect answer , you opened me many ways to start . thanks a lot – Realbitt Oct 14 '12 at 02:57
  • i work on jabber client (Chat) and this xml is live stream between client and server over live TCP/IP connection. did you think there is a better way for this situation ? – Realbitt Oct 14 '12 at 03:14
  • I don't know [`XMPP`](http://xmpp.org/xmpp-protocols/rfcs/) protocol at all, but from a quick view it's just based on XML exchange, so always you'll have to parse XML files and as many people says, `NativeXml` is a very fast XML parser, so I'd say you chose a good parser for this. Btw., for some basic comparision of Delphi XML parsers you may take a look at [`this question`](http://stackoverflow.com/q/9488573/960757). – TLama Oct 14 '12 at 03:38
  • 1
    @TLama - + 1. Thanks for this. Got me up and running with NatveXML within a couple of minutes. Great explanation and examples. – Johnny Oct 15 '12 at 11:24
  • another question : how can i return node as string as XML structure as example i got node object by `Node := Node.NodeByName('method');` i want some thing like `Node.ToString;` to get it as string but full XML structure as `zlib` thanks – Realbitt Oct 18 '12 at 14:22
  • i found it :) all in `WriteToString` – Realbitt Oct 20 '12 at 19:49
  • Oh, sorry, I would try to help you, but I've been notified about the new comment for this post when your comment contained just *"another question"* and then I forget on it without going back to see the update. That's also the reason for asking through the new question post ;-) – TLama Oct 20 '12 at 19:59