MegaZone (zonereyrie) wrote,
MegaZone
zonereyrie

  • Mood:
  • Music:

Need help with PHP DOMXML - get_elements_by_tagname

I'm having some issues with PHP DOMXML - in particular the get_elements_by_tagname method. Now, the PGP docs on this are, well, sparse, so maybe I'm just doing something stupid. I thought this method would behave like the 'findnodes' XML method in Perl. Namely that you can pass it an xpath statement and it will find nodes that match:
$array = $node->get_elements_by_tagname($xpath);

And, indeed, this seems to have worked when I've used it in the past. But I'm working on a more complex system now which does a lot more sub-node access, etc, and it is failing on me. I put together this example to demonstrate the failure modes I'm experiencing.
<?php
if (PHP_OS == "WIN32" || PHP_OS == "WINNT") {
  define('EOL', "\r\n");
} 
else {
  define('EOL', "\n");
}
header("Content-Type: text/plain");
print PHP_VERSION . EOL;

$xml = 
'<TestDoc>
<level1>
<level2>
<level3>
<level4>
<fubar>fubar</fubar>
<fubaz>fubaz</fubaz>
</level4>
</level3>
</level2>
</level1>
</TestDoc>';

if (!$domResponse = domxml_open_mem($xml)) {
  print("failed!");
}

print pcGetField(&$domResponse, "fubar") . EOL;

lookup(&$domResponse);

function lookup($domResponseRef) {
  print $domResponseRef->dump_mem();
  $node = 
    $domResponseRef->get_elements_by_tagname("level4");
  $node = $node[0];
  print_r($node);
  print pcGetField2(&$node, "//fubar") . EOL;
  print pcGetField(&$domResponseRef, "fubar") . EOL;
  print pcGetField(&$node, "fubar") . EOL;
  $node = 
    $node->get_elements_by_tagname("fubar");
  print $node[0]->get_content() . EOL;
  $node = $node[0];
  print_r($node);
}

function pcGetField($nodeRef, $tag) {
  if(!isset($nodeRef)) {
    print("pcGetField: node is blank [" . $tag . "]");
    return "";
  }
  $node = $nodeRef->get_elements_by_tagname($tag);
  $node = $node[0];
  return $node->get_content();
}

function pcGetField2($nodeRef, $tag) {
  if(!isset($nodeRef)) {
    print("pcGetField: node is blank [" . $tag . "]");
    return "";
  }
  $xpath = xpath_new_context($nodeRef);
  $node = &xpath_eval($xpath, $tag);
  $node = $node->nodeset[0];

  return $node->get_content();
}
?>


With it like this everything is fine:
4.2.2
fubar
<?xml version="1.0"?>
<TestDoc>
<level1>
<level2>
<level3>
<level4>
<fubar>fubar</fubar>
<fubaz>fubaz</fubaz>
</level4>
</level3>
</level2>
</level1>
</TestDoc>
DomElement Object
(
    [type] => 1
    [tagname] => level4
    [0] => 3
    [1] => 138428856
)
fubar
fubar
fubar
fubar
DomElement Object
(
    [type] => 1
    [tagname] => fubar
    [0] => 2
    [1] => 137830792
)


You see, I'm jumping down to 'level4' so fubar is an immediate child node. But if I start from *anywhere* except the root node or the immediate parent, it fails. So if I change:
$node = $domResponseRef->get_elements_by_tagname("level4");
to
$node = $domResponseRef->get_elements_by_tagname("level1");
I get:
4.2.2
fubar
<?xml version="1.0"?>
<TestDoc>
<level1>
<level2>
<level3>
<level4>
<fubar>fubar</fubar>
<fubaz>fubaz</fubaz>
</level4>
</level3>
</level2>
</level1>
</TestDoc>
DomElement Object
(
    [type] => 1
    [tagname] => level1
    [0] => 3
    [1] => 137478408
)
fubar
fubar
<br />
<b>Fatal error</b>:  Call to a member function on a non-object in
<b>/home/megazone/scripts/PHP/Kiosk/test.php</b> on line <b>5\6</b><br
/>


Note that the it works when checking from the docroot and later when using xpath_eval and from the reference to the doc root - but fails the first time you try it from the subnode. It will fail with TestDoc, level1, level2, and level3. it will fail if I try get_elements_by_tagname("fubar"), get_elements_by_tagname("//fubar"), etc. It also fails if you're at say level3 and try to look for "level4/fubar". I think I've tried every combination I can think of.

So is this just a limitation that it only works when working with the root node of the document or when looking for an immediate child of the current node? What the heck am I not seeing?

Thanks.
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 5 comments