Search code examples
delphixmppnativexml

delphi nativexml multi level xml structure


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


Solution

  • 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>