XML DOM: hasChildNodes returns always TRUE

einsTeIn.NETeinsTeIn.NET Member Posts: 1,050
I've got a problem with XML DOM and I found this post where the same problem is described. It looks like he found a solution but I can't get it.

My problem is that I want to parse a XML file and I don't know its exact structure. Every element could have childs and I don't know how many. I must create some kind of recursive function to step along the tree of the XML file. Maybe someone created a solution for that already :?:

I thought I could use
Node.hasChildNodes
to find out if there are child elements. But this function returns TRUE even if there is only text within the node. That means every time I reach the bottom / lowermost level of the tree and there is only text content within this element, hasChildNodes returns TRUE and I get an error message. It says that there is no instance of an automation variable because the current node is not filled due to the fact that the current node list can't return a node from a text content. Or did I misunderstand something?

I created a test function and a test XML file...
IF NOT ISCLEAR(XMLDocument) THEN
  CLEAR(XMLDocument);
CREATE(XMLDocument);

XMLDocument.setProperty('ProhibitDTD',FALSE);
XMLDocument.validateOnParse(FALSE);
IF XMLDocument.load('C:\temp3.xml') THEN BEGIN
  XMLCurrNode := XMLDocument.selectSingleNode(XMLDocument.documentElement.nodeName);

  IF XMLCurrNode.hasChildNodes THEN BEGIN
    XMLNodeList := XMLCurrNode.childNodes;
    XMLCurrNode := XMLNodeList.nextNode;
    MESSAGE('Node: %1\Text: %2',XMLCurrNode.nodeName,XMLCurrNode.text);
  
    IF XMLCurrNode.hasChildNodes THEN BEGIN
      XMLNodeList := XMLCurrNode.childNodes;
      XMLCurrNode := XMLNodeList.nextNode;
      MESSAGE('Node: %1\Text: %2',XMLCurrNode.nodeName,XMLCurrNode.text);
    
      IF XMLCurrNode.hasChildNodes THEN BEGIN
        XMLNodeList := XMLCurrNode.childNodes;
        XMLCurrNode := XMLNodeList.nextNode;
        MESSAGE('Node: %1\Text: %2',XMLCurrNode.nodeName,XMLCurrNode.text);

        IF XMLCurrNode.hasChildNodes THEN BEGIN
          XMLNodeList := XMLCurrNode.childNodes;
          XMLCurrNode := XMLNodeList.nextNode;
          MESSAGE('Node: %1\Text: %2',XMLCurrNode.nodeName,XMLCurrNode.text);
        END;
      END;
    END;
  END;
END;
XML file temp3.xml
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE Data SYSTEM "myDTD.dtd">
<!--  @version: -->
<Data arg1="TEST">
  <a Aarg1="A1 arg" Aarg2="A2 arg">
    <AA AAarg1="AA1 arg">AA content</AA>
    <AB>AB content</AB>
  </a>
  <b>b content</b>
    <BA BAarg1="BA1 arg">
      <BAA>BAA content</BAA>
    </BA>
  <c>c content</c>
</Data>
"Money is likewise the greatest chance and the greatest scourge of mankind."

Comments

  • ara3nara3n Member Posts: 9,256
    Hello Einstein

    I ran you code with xmldom 6.0 and has child return false based on your xml file. What version are you using?

    What are you going to do with xml file? There are plenty examples of parsing on the web?
    Ahmed Rashed Amini
    Independent Consultant/Developer


    blog: https://dynamicsuser.net/nav/b/ara3n
  • ara3nara3n Member Posts: 9,256
    Here is an example on how to parse it.
    IF NOT ISCLEAR(XMLDocument) THEN
      CLEAR(XMLDocument);
    CREATE(XMLDocument);
    
    XMLDocument.setProperty('ProhibitDTD',FALSE);
    XMLDocument.validateOnParse(FALSE);
    IF XMLDocument.load('C:\temp3.xml') THEN BEGIN
      XMLCurrNode := XMLDocument.selectSingleNode(XMLDocument.documentElement.nodeName);
    
     GetNodes(XMLCUrrNode);
    END;
    


    And here are the functions.
    GetChildNodes(XMLCurrNode : Automation "'Microsoft XML, v6.0'.IXMLDOMNode")
    if XMLCurrNode.hasChildNodes then begin
       GetNodes(XMLCurrNode.firstChild);
    end else
      MESSAGE('Node: %1\Text: %2',XMLCurrNode.nodeName,XMLCurrNode.text);
    
    GetNodes(XMLCurrNode : Automation "'Microsoft XML, v6.0'.IXMLDOMNode")
    XMLNodeList := XMLCurrNode.childNodes;
    
    For I := 0 to XMLNodeList.length do begin
      GetChildNodes(XMLCurrNode);
      XMLCurrNode := XMLNodeList.nextNode;
    end;
    

    Only XMLDocument and XMLCurrNode is global variable
    XMLNodeList and I in second function are local variables.
    Ahmed Rashed Amini
    Independent Consultant/Developer


    blog: https://dynamicsuser.net/nav/b/ara3n
  • einsTeIn.NETeinsTeIn.NET Member Posts: 1,050
    Thanks for your reply.
    I also use v6.0. Yes, my example returns FALSE in the 4th indented IF...THEN. But imho it should return FALSE at the 3rd already. There is only content at the 4th level, so I expected that content would not be interpreted as additional node. Or am I wrong?

    I searched the web over and over again. I think I'm going crazy because I believed that there should be tausands of examples for that. But I didn't find at least one for my case. All solutions work with XPath or something else. But I don't know the structure of the XML file, so I can't use those examples. :cry:
    "Money is likewise the greatest chance and the greatest scourge of mankind."
  • ReinhardReinhard Member Posts: 249
    Text is considered a text node I think.
    http://www.w3schools.com/dom/dom_nodes.asp
  • einsTeIn.NETeinsTeIn.NET Member Posts: 1,050
    Oh! Now it's clear. I just misunderstood the meaning of node. Thank you for your reply. Very good link.
    I will try to follow that when I retry to solve it within the next few days.
    "Money is likewise the greatest chance and the greatest scourge of mankind."
Sign In or Register to comment.