?

Log in

No account? Create an account
Ramblings Journals I Read Calendar The Dirt MegaZone's Waste of Time Older Older Newer Newer
Need help with PHP DOMXML - get_elements_by_tagname - MegaZone's Safety Valve
The Ramblings of a Damaged Mind
zonereyrie
zonereyrie
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.

I am: frustrated frustrated
Current Media: office buzz

5 STDOUT || STDIN
Comments
lizzielizzie From: lizzielizzie Date: November 24th, 2003 07:19 pm (UTC) (Direct Link)
I can't be of any help whatsoever, so I'll just stand here and be cute.

Pose!
zonereyrie From: zonereyrie Date: November 24th, 2003 10:33 pm (UTC) (Direct Link)
Oh baby, you make it hard to think about code. ;-)
sprak3000 From: sprak3000 Date: November 24th, 2003 09:33 pm (UTC) (Direct Link)

Might be broken in your version

You may need to grab a later version of PHP; did a quick Google and found this bug listed. The bug poster is not doing quite the same test you are, but it seems similar enough in nature. They were testing and seeing the bug in 4.3.3, and it appears you are on 4.2.2.

Unfortunately, the version my provider runs is 4.2.3, so I cannot test to see if this is indeed the case.
myraleemarshall From: myraleemarshall Date: November 25th, 2003 05:02 pm (UTC) (Direct Link)

I hope you made some progress figuring this out...

Not much else I can say... I'm confused, but that's not really all that unusual.
zonereyrie From: zonereyrie Date: November 25th, 2003 05:32 pm (UTC) (Direct Link)
:-) Yeah, I think I found a way to make things work. Today was mostly shot with meetings. Bleah.
5 STDOUT || STDIN