php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #20948 DomElement->get_elements_by_tagname is now recursive
Submitted: 2002-12-11 17:15 UTC Modified: 2002-12-12 01:21 UTC
Votes:5
Avg. Score:4.0 ± 0.9
Reproduced:3 of 3 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: dave at thequestion dot net Assigned:
Status: Wont fix Package: DOM XML related
PHP Version: 4.3.0RC3 OS: FreeBSD
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2002-12-11 17:15 UTC] dave at thequestion dot net
The function DomElement->get_elements_by_tagname() is now recursive.  It is returning matching elements from it's children nodes as well.

In 4.2.3, this function would only return matching elements in it's node.

The following code (with output) shows the difference.

#!/usr/bin/php -q
<?php
  $xmlsource  = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
  $xmlsource .= "<root comment=\"root node\">";
  $xmlsource .= "  <one comment=\"one\">";
  $xmlsource .= "    <two comment=\"first two, count should be 1\">";
  $xmlsource .= "      <three comment=\"three\">";
  $xmlsource .= "      </three>";
  $xmlsource .= "    </two>";
  $xmlsource .= "    <four comment=\"four\">";
  $xmlsource .= "      <two comment=\"second two\">";
  $xmlsource .= "      </two>";
  $xmlsource .= "    </four>";
  $xmlsource .= "  </one>";
  $xmlsource .= "</root>";

  $doc = domxml_open_mem($xmlsource);

  echo "==========================================================\r\n";
  echo "PHP Version: ".phpversion()."\r\n";
  echo "==========================================================\r\n";
  echo sprintf("\$doc->get_elements_by_tagname(\"two\"): %d\r\n", count($doc->get_elements_by_tagname("two")));
  echo "----------------------------------------------------------\r\n";
  echo " Count | Node            | Comment\r\n";
  echo "----------------------------------------------------------\r\n";

  // Set root node
  $node_root = $doc->document_element();

  // Find node_one
  $array_nodes = $node_root->get_elements_by_tagname("one");
  if (count($array_nodes) > 0)
  {
    $node_one = $array_nodes[0];
    // echo sprintf("[%d] node_one comment: %s\r\n", count($array_nodes), $node_one->get_attribute("comment"));
    echo sprintf(" %-5d | %-15s | %s\r\n", count($array_nodes), "node_one", $node_one->get_attribute("comment"));
  }
  else
  {
    echo sprintf(" %-5d | %-15s | %s\r\n", 0, "node_one", "Not Found");
  }

  // Find node_firstTwo
  $array_nodes = $node_one->get_elements_by_tagname("two");
  if (count($array_nodes) > 0)
  {
    $node_firstTwo = $array_nodes[0];
    // echo sprintf("[%d] node_firstTwo comment: %s\r\n", count($array_nodes), $node_firstTwo->get_attribute("comment"));
    echo sprintf(" %-5d | %-15s | %s\r\n", count($array_nodes), "node_firstTwo", $node_firstTwo->get_attribute("comment"));
  }
  else
  {
    echo sprintf(" %-5d | %-15s | %s\r\n", 0, "node_firstTwo", "Not Found");
  }

  // Find node_four
  $array_nodes = $node_root->get_elements_by_tagname("four");
  if (count($array_nodes) > 0)
  {
    $node_four = $array_nodes[0];
    // echo sprintf("[%d] node_four comment: %s\r\n", count($array_nodes), $node_four->get_attribute("comment"));
    echo sprintf(" %-5d | %-15s | %s\r\n", count($array_nodes), "node_four", $node_four->get_attribute("comment"));
  }
  else
  {
    echo sprintf(" %-5d | %-15s | %s\r\n", 0, "node_four", "Not Found");
  }

  // Find node_secondTwo
  if ($node_four)
  {
    $array_nodes = $node_four->get_elements_by_tagname("two");
    if (count($array_nodes) > 0)
    {
      $node_secondTwo = $array_nodes[0];
      // echo sprintf("[%d] node_secondTwo comment: %s\r\n", count($array_nodes), $node_secondTwo->get_attribute("comment"));
      echo sprintf(" %-5d | %-15s | %s\r\n", count($array_nodes), "node_secondTwo", $node_secondTwo->get_attribute("comment"));
    }
    else
    {
      echo sprintf(" %-5d | %-15s | %s\r\n", 0, "node_secondTwo", "Not Found");
    }
  }
  echo "==========================================================\r\n";
?>

Output for PHP 4.2.3:
==========================================================
PHP Version: 4.2.3
==========================================================
$doc->get_elements_by_tagname("two"): 2
----------------------------------------------------------
 Count | Node            | Comment
----------------------------------------------------------
 1     | node_one        | one
 1     | node_firstTwo   | first two, count should be 1
 0     | node_four       | Not Found
==========================================================


Output for PHP 4.3.0RC3:
==========================================================
PHP Version: 4.3.0RC3
==========================================================
$doc->get_elements_by_tagname("two"): 2
----------------------------------------------------------
 Count | Node            | Comment
----------------------------------------------------------
 1     | node_one        | one
 2     | node_firstTwo   | first two, count should be 1
 1     | node_four       | four
 1     | node_secondTwo  | second two
==========================================================

Hopefully you can see what I'm trying to show here.  The fact that 4.3.0RC3 finds the node_four and thus the node_secondTwo shows that DomElement->get_elements_by_tagname is recursive.  Since PHP support for DOM XML is experimental, this might be a feature rather than a bug.  If that's the case, maybe a parameter could be added to the function to select whether or not to traverse deeper into the tree.

Thanks

Dave

Note: this was tested with libxml2-2.4.21 installed.  Everything on the system is identical for each run above except for the php binary.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2002-12-12 01:21 UTC] chregu@php.net
Hi

you're right, the behaviour changed. But the new behaviour is. what the W3C-Standard says:
"Returns a NodeList of all descendant Elements with a given tag name, in the order in which they are encountered in a preorder traversal of this Element tree."

Therefore, I won't change it. I will make a NEWS entry about that.

If you just want the direct children of an Element, use the Xpath Functions.

chregu
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Thu Apr 25 14:01:25 2019 UTC