2

I am writing a function to decrypt the contents of a SimpleXML object in place.

function xmlWalkerDecrypt(&$xmlObj, $aesKey) { 
    if ($xmlObj->count()>0){
        foreach($xmlObj as &$child){      //line 154
            xmlWalkerDecrypt($child, $aesKey);
        }
    }
    else{
        $xmlObj = companyAES($xmlObj, $aesKey, 'decrypt');
    }
} 

This is throwing a the following error in WAMP: Fatal error: An iterator cannot be used with foreach by reference in C:\wamp\www\_assets\walk.php on line 154

Is it possible to iterate through a SimpleXML object for the purpose of editing by reference, rather than outputting?

I've also tried:

function xmlWalkerDecrypt(&$xmlObj, $aesKey) { 
if ($xmlObj->count()>0){
    foreach($xmlObj->children() as &$child){      //line 154
        xmlWalkerDecrypt($child, $aesKey);
    }
}
else{
    $xmlObj = companyAES($xmlObj, $aesKey, 'decrypt');
}
} 

but that produces the following error:

Fatal error: Cannot create references to elements of a temporary array expression in C:\wamp\www_assets\myFile.php on line 154`

hakre
  • 193,403
  • 52
  • 435
  • 836
yumcha
  • 63
  • 1
  • 4
  • Shouldn't &$child be $child? – santa Jun 13 '13 at 17:15
  • I tried that as well, but the edit from the else clause did not affect the original object, i.e. the $child object is a new and separate object. – yumcha Jun 13 '13 at 18:25
  • possible duplicate of [PHP array\_walk\_recursive() for SimpleXML objects?](http://stackoverflow.com/questions/17095484/php-array-walk-recursive-for-simplexml-objects) – IMSoP Jun 14 '13 at 11:39

2 Answers2

0

I am not sure what companyAES does to the variables passed to it but here are 2 points that might help:

  1. Parameter 1 for xmlWalkerDecrypt does not need to be declared as a reference because all objects in PHP are passed by reference so there is no need to put that in your function declaration. You might think array() is an object but it isn't, but new ArrayObject() would create an object. See http://php.net/manual/en/class.arrayobject.php

  2. You cannot modify a SimpleXMLElement, you can only read from or add attributes/children to it. If you need to modify the XML nodes once they are loaded/added you should use DOMDocument & it's related classes.

Precastic
  • 3,742
  • 1
  • 24
  • 29
  • Two clarifications: Firstly, `new Array()` doesn't work in PHP (you can't even create a custom class with that name), so `array()` is *never* an object. Secondly, there is a subtle difference between object pointers and references, but you are right that for the most part an object can be thought of as "always passed by reference". – IMSoP Jun 14 '13 at 11:35
  • 1
    Actually, a third point: you can modify a SimpleXMLElement - `$foo[0] = 'hello'` will overwrite the text content to be the string `hello`. You can't do *much* modification, but some is possible. – IMSoP Jun 14 '13 at 11:36
  • @IMSoP You are right on both counts: 1. I meant the ArrayObject object. I have updated my answer. 2. There is a huge difference between references & pointers but not in PHP from a user point of view - you can't explicitly create a pointer variable as with other languages like C++ – Precastic Jun 14 '13 at 15:01
  • I was talking about "object pointers"/"object references", not "pointers" in a C-sense; I don't know a good unambiguous term for them. The key point is they are a *second* level of indirection distinct from variable references. You *can* assign an object variable by reference in PHP, and it does mean something different from assigning it by value. Try this: `$a = new stdClass; $b =& $a; $b = 1; echo $a;` (compared to the same with `=` in place of `=&`). – IMSoP Jun 14 '13 at 15:26
0

You most likely have the issue that you need to self-refence the element to change it:

$xmlObj[0] = companyAES($xmlObj, $aesKey, 'decrypt');
       ###

This is documented in an earlier question:

Then additionally it's not necessary to pass those SimpleXMLElement objects by reference. So you can spare the aliasing within the foreach and the parameter definition :

function xmlWalkerDecrypt(SimpleXMLElement $xmlObj, $aesKey) { 

    ...

    foreach ($xmlObj->children() as $child) {

    ...

That should do it, this effectively takes care of the reported problem by the error message. Only existing variables can be aliased (&), not temporary array expressions.

Community
  • 1
  • 1
hakre
  • 193,403
  • 52
  • 435
  • 836