In PHP DOM get Element/Node depth in recursive function

dom, php, recursion

Solution

The question would be a lot clearer if you provided the output you want. A depth parameter can be passed as follows:

function recursively_find_text_nodes($dom_element, $depth=1) {

    $return = array();

    foreach ($dom_element->childNodes as $dom_child) {

        switch ($dom_child->nodeType) {

            case XML_TEXT_NODE:
                if (trim($dom_child->nodeValue) !== '') {
                    $return[] = array (
                        'depth' => $depth, 
                        'value' => $dom_child->nodeValue
                    );
                }
                break;

            case XML_ELEMENT_NODE:
                $return[] = array (
                    'depth' => $depth,
                    'value' => $dom_child
                );

                $return = array_merge($return, $this->recursively_find_text_nodes($dom_child, $depth+1));
                break;
        }
    }

    return $return;
}

The return value probably won't be what you intended, but you'll have to be more specific for that.

Update

From what I understand, you probably mean something like this:

<?php

function recursively_find_text_nodes($dom_element, $depth=1, $predecessor_depth=0) {

    $return = array();

    foreach ($dom_element->childNodes as $dom_child) {

        switch ($dom_child->nodeType) {

            case XML_TEXT_NODE:
                if (trim($dom_child->nodeValue) !== '') {
                    $return[] = array (
                        'absolute_depth' => $depth,
                        'relative_depth' => $depth - $predecessor_depth,
                        'value' => $dom_child->nodeValue
                    );

                    $predecessor_depth = $depth;
                }
                break;

            case XML_ELEMENT_NODE:
                $return[] = array (
                    'absolute_depth' => $depth,
                    'relative_depth' => $depth - $predecessor_depth,
                    'value' => $dom_child
                );

                // Add the sub tree nodes to the result array
                $child_return_value = $this->recursively_find_text_nodes($dom_child, $depth+1, $predecessor_depth);
                $return = array_merge($return, $child_return_value);

                // Determine the depth of the last one processed
                $predecessor_depth = $return[count($return)-1]['absolute_depth'];

                break;
        }
    }

    return $return;
}

?>

If it is something else still, you should provide example input and output (always the first step when designing an algorithm.)

Problem

I have the following function, which reads all child elements/text nodes of a given dom element into an array, by recursively calling itself. It works fine, but I need the depth of each node (text or element) in relation to the first(!) given DOM node before any recursion happened. I can't figure out how to do this, any ideas? ``` function recursively_find_text_nodes($dom_element) { $return = array(); foreach ($dom_element->childNodes as $dom_child) { switch ($dom_child->nodeType) { case XML_TEXT_NODE: if (trim($dom_child->nodeValue) !== '') { $return[] = $dom_child->nodeValue; } break; case XML_ELEMENT_NODE: $return = array_merge($return, $this->recursively_find_text_nodes($dom_child)); break; } } return $return; } ``` I am parsing an XML node with this function. It can have any number of elements and subelements. The idea is that I +1 a depth variable, every time the function goes into recursion. the problem is that when I am in a node that actually does not go deeper, but up in the tree I'd have to -1 the variable. So for every node that I am currently in I would need the depth of the current element in regard to the DOM node that was passed to the function before(!) it went into recursion.

Original source