-2

I am currently writing a PHP class which handles an XML document. Specifically, a certain method of such class requires to know whether a node has children or whether it is a "leaf". Suppose an XML structure as follows:

<root>
    <obj1>
         <obj2>red</obj1>
         <obj3>green</obj3>
         <obj4>
             <obj5></obj5>
         </obj4>
    </obj1>
</root>

I would consider root, obj1 and obj4 to be nodes, while obj2, obj3 and obj5 to be leaves, not having child nodes themselves.

The code I use is the following:

$MyDoc = NewDOMDocument();
$node = $MyDoc->getElementsByTagName($node_name);
foreach($node as $node) {
    if($node->hasChildNodes()) {
        return true;
    }
    return false;
}

However, such code is returning "true" for any object I apply it to, whether it has childNodes or not.

What am I doing wrong?

j0k
  • 22,600
  • 28
  • 79
  • 90
max0005
  • 210
  • 4
  • 9
  • 1
    I suspect you forgot to add the ->load on your DOMDocument or this is handled in the NewDOMDocument-function? And the declaration of $node_name? Or did you mean to create a DOMDocument which then should be `$MyDoc = new DOMDocument(); // and load data`? – Robert de W Jul 19 '11 at 08:39
  • No, I actually included both in my code. Just didn't post them here as it would have been several hundred lines of code... Both $node_name and ->load are part of the document. – max0005 Jul 19 '11 at 08:42
  • Note the [ ] space in `$MyDoc = new DOMDocument();` – Robert de W Jul 19 '11 at 08:44
  • My code has $MyDocument = new DOMDocument("1.0"); - My bad, typo.. – max0005 Jul 19 '11 at 08:45
  • I have used the code from the MANUAL often - have you tried it? or looked at it even? http://php.net/manual/en/domnode.haschildnodes.php – Brian Jul 19 '11 at 08:38

2 Answers2

2
$node = $MyDoc->getElementsByTagName($node_name);
foreach($node as $node)

You're overwriting your variable. Try:

$nodelist = $MyDoc->getElementsByTagName($node_name);
foreach($nodelist as $node)
Robert de W
  • 316
  • 8
  • 24
  • Tried, nothing changed... Furthermore, the manual's second example http://www.php.net/manual/en/domnode.haschildnodes.php#90560 overwrites its variable in the foreach cyle. – max0005 Jul 19 '11 at 08:41
  • Yes, you're right. Though it's userinput, that post should be moderated. – Robert de W Jul 19 '11 at 08:42
1

I would consider root, obj1 and obj4 to be nodes, while obj2, obj3 and obj5 to be leaves, not having child nodes themselves.

You are wrong. A DOM tree is a hierarchy of nodes. This means DOMText, DOMElements, DOMDocument, etc all inherit from DOMNode. Please go through DOMDocument in php again to understand the concept.

Below is the tree hierarchy of your document:

root
    #text
    obj1
        #text
        obj2
            #text
        #text
        obj3
            #text
        #text
        obj4
            #text
            obj5
            #text
        #text
    #text

Of those you mentioned only obj5 is a leaf. Consequently:

var_dump($dom->getElementsByTagName('obj5')->item(0)->hasChildNodes()); // false

You cannot count just the DOMElement nodes with any of the DOMNode methods (unless you want to iterate over each of the child nodes and check their nodeType). But you can use XPath:

$dom = new DOMDocument;
$dom->loadXML($xml);
$xp = new DOMXPath($dom);
var_dump( $xp->evaluate('count(/root/obj1/obj2/*)') ); // 0

The * will only consider DOMElements (vs using node() which considers all nodes).

Community
  • 1
  • 1
Gordon
  • 312,688
  • 75
  • 539
  • 559