tags:

views:

50

answers:

1

Hi,

I'm having difficulty extracting a single node value from a nodelist.

My code takes an xml file which holds several fields, some containing text, file paths and full image names with extensions.

I run an expath query over it, looking for the node item with a certain id. It then stores the matched node item and saves it as $oldnode

Now my problem is trying to extract a value from that $oldnode. I have tried to var_dump($oldnode) and print_r($oldnode) but it returns the following: "object(DOMElement)#8 (0) { } "

Im guessing the $oldnode variable is an object, but how do I access it?

I am able to echo out the whole node list by using: echo $oldnode->nodeValue;

This displays all the nodes in the list.

Here is the code which handles the xml file. line 6 is the line in question...

 $xpathexp = "//item[@id=". $updateID ."]";
            $xpath = new DOMXpath($xml);
            $nodelist = $xpath->query($xpathexp);
            if((is_null($nodelist)) || (! is_numeric($nodelist))) {
              $oldnode = $nodelist->item(0);
              echo $oldnode->nodeValue;
              //$imgUpload = strchr($oldnode->nodeValue, ' ');
              //$imgUpload = strrchr($imgUpload, '/');
              //explode('/',$imgUpload);

              //$imgUpload = trim($imgUpload); 


              $newItem = new DomDocument;
              $item_node = $newItem ->createElement('item');

               //Create attribute on the node as well
              $item_node ->setAttribute("id", $updateID);

              $largeImageText = $newItem->createElement('largeImgText');
              $largeImageText->appendChild( $newItem->createCDATASection($largeImgText));
              $item_node->appendChild($largeImageText);

              $urlANode = $newItem->createElement('urlA');
              $urlANode->appendChild( $newItem->createCDATASection($urlA));
              $item_node->appendChild($urlANode);

              $largeImg = $newItem->createElement('largeImg');
              $largeImg->appendChild( $newItem->createCDATASection($imgUpload));
              $item_node->appendChild($largeImg);

              $thumbnailTextNode = $newItem->createElement('thumbnailText');
              $thumbnailTextNode->appendChild( $newItem->createCDATASection($thumbnailText));
              $item_node->appendChild($thumbnailTextNode);

              $urlB = $newItem->createElement('urlB');
              $urlB->appendChild( $newItem->createCDATASection($urlA));
              $item_node->appendChild($urlB);

              $thumbnailImg = $newItem->createElement('thumbnailImg');
              $thumbnailImg->appendChild( $newItem->createCDATASection(basename($_FILES['thumbnailImg']['name'])));
              $item_node->appendChild($thumbnailImg);

              $newItem->appendChild($item_node);

              $newnode = $xml->importNode($newItem->documentElement, true);

                       // Replace
              $oldnode->parentNode->replaceChild($newnode, $oldnode);

              // Display
              $xml->save($xmlFileData);
                               //header('Location: index.php?a=112&id=5');

Any help would be great.

Thanks

A: 

Wasn't it supposed to be echo $oldnode->firstChild->nodeValue;? I remember this because technically you need the value from the text node.. but I might be mistaken, it's been a while. You could give it a try?

After our discussion in the comments on this answer, I came up with this solution. I'm not sure if it can be done cleaner, perhaps. But it should work.

$nodelist = $xpath->query($xpathexp);
if((is_null($nodelist)) || (! is_numeric($nodelist))) {
    $oldnode = $nodelist->item(0);

    $largeImg       = null;
    $thumbnailImg   = null;
    foreach( $oldnode->childNodes as $node ) {
        if( $node->nodeName == "largeImg" ) {
            $largeImg       = $node->nodeValue;
        } else if( $node->nodeName == "thumbnailImg" ) {
            $thumbnailImg   = $node->nodeValue;
        }
    }

    var_dump($largeImg);
    var_dump($thumbnailImg);
}

You could also use getElementsByTagName on the $oldnode, then see if it found anything (and if a node was found, $oldnode->getElementsByTagName("thumbnailImg")->item(0)->nodeValue). Which might be cleaner then looping through them.

CharlesLeaf
yeah that grabs the first child value.. which is great.. But how can I traverse through the object and select the item I want? Also, How do I get an output of the whole of the object?
Owzzz
I am not sure what you mean, you are already selecting the item that you want using your Xpath are you not? And what output are you expecthing of the 'whole of the object', can you maybe give a example? (maybe on pastebin.com?)
CharlesLeaf
the xpath is selecting an item with id of a particular value. That item (node) has several nodes within it. An example of the node list in the xml file is as follows: http://pastebin.com/R8qmbg9F ... so by using your line: $oldnode->firstChild->nodeValue; it grabs the value of <largeImgText> node
Owzzz
But you are already selecting the node from within that item by using item(0), or are there multiple nodes inside thát node? Because if $oldnode is a DOMElement, you could maybe take a look at the `childNodes` to find the one you are looking for? (probably loop through, check for the nodeName, then get the value). Just saw your link, I'll go check it out.
CharlesLeaf
Owzzz
No there are several item(s) and so what the xpath does is retrieves the item with the same id. the line: $oldnode = $nodelist->item(0); stores the value of the first item (item(0)) of which there would only be one returned from the xpath. So the $oldnode should hold something like the xml i showed you above: pastebin.com/R8qmbg9F
Owzzz
See my updated example, does that deliver what you want? :) It goes through the childNodes and saves the two nodes you want to get in variables (and I defaulted the variables to null so you can check if they were found or not).
CharlesLeaf
For some reason, the first one (largeImg) is returning a string(0) so for some reason the value of the image is not being parsed to the variable... I'm also getting a error: Warning: DOMDocument::createCDATASection() expects parameter 1 to be string, object given in /home/csfearless/public_html/manager/processors/execute_module.processor.php(114) : eval()'d code on line 84... it looks to me like the createDATASection does not like accepting just a single variable ($largeImg) the lines in question is: http://pastebin.com/v24GeinT
Owzzz
You are overwriting the value of `$largeImg` in this case with the newly created DOMElement. The string(0) is strange however, as it should return null if it isn't available, so there probably is a empty CDATA section in that scenario? In the test-case with your example XML I can only get string(0) by having the empty CDATA, removing largeImg nodes returns NULL.
CharlesLeaf
I think I'm over the worst of it now.. but Im trying to use an if statment to only add the new largeImg if it's not empty would this work.. http://pastebin.com/u3qRUpte at the moment I'm getting a syntax error, unexpected T_IF, expecting ')' on that block of code...
Owzzz
You can't put a IF statement within the (). However, using a `Tertiary Operator` you can. Or you could put the IF around the whole appendChild. http://pastebin.com/kGYwXZRh
CharlesLeaf
Thanks, I've used that one.. perosnally Im not a fan of that way as it's not very legible.. but if needs must :S It kind of works now... but my logic is wrong somwhere which means if the largeImg is empty then it does not create the new node with the new value in it. yet if there is a value in largeImg then when a new value is added to the variable it replaces it. So there's a small issue there somewhere...
Owzzz
Well you don't have to use it, you could simply do the if/else around the entire line if( ... ) { ...->appendChild() } else { ...->appendChild() } ;) As for logic, first thing is the comparisement to "null", that's different than comparing to `null` (no quotes). I think you need if( $largeImgNode == null || $largeImgNode == "" ) { // use $largeImg } else { // use $largeImgNode, because it's not empty }. But maybe it's an idea to mark the answer as solved, as this is not really part of your original problem?
CharlesLeaf
yes consider it done... will look into the logic.. thanks again for your help on this..
Owzzz