Page 1 of 1

is_array says array is not an array!

Posted: Tue Oct 12, 2010 8:37 pm
by nickweavers
It is late, and I may be missing something very obvious here, but I am having trouble accessing the telephone values in some xml because when there is more than one number, simpleXml creates $xmlObj->TelephoneNumbers->TelephoneNumber as an array, but when there is only one, it creates it as SimpleXMLElement Object. If I try to use is_array() on $xmlObj->TelephoneNumbers->TelephoneNumber to determine whether I loop over it or not, the value I get back is false even though print_r() tells me it is an array, and if I actually use foreach on it, it behaves like an array. Can anyone tell me why is_array returns false?

My small testcase is below, followed by the results:

Code: Select all

<?php
function xmlentities($string) {
    return str_replace ( array ( '&', ' ', '"', "'", '<', '>' ), array ( '&', '&nbsp;' , '"', '&apos;' , '<' , '>' ), $string );
}

function is_array_abled(&$x)
{
    return (bool)($x instanceof ArrayAccess or is_array($x));
}

$xml = <<<EOD
<Applicants>
    <TelephoneNumbers>
        <TelephoneNumber>
            <Number>01244123456</Number>
            <Type>Notification</Type>
        </TelephoneNumber>
        <TelephoneNumber>
            <Number>78787654321</Number>
            <Type>Mobile</Type>
        </TelephoneNumber>
    </TelephoneNumbers>
</Applicants>
EOD;

printf("<h3>XML:</h3>");
print(nl2br(xmlentities($xml)));
$xmlObj = simplexml_load_string($xml);
printf("<h3>SimpleXML Object:</h3>");
print("<pre>");
print_r($xmlObj);
print("</pre>");

if(is_array($xmlObj->TelephoneNumbers->TelephoneNumber)) {
	$result = 'true';
} else {
	$result = 'false';
}

printf("is_array(\$xmlObj->TelephoneNumbers->TelephoneNumber) gives: %s<br><br>", $result);

// Try printing both sets of numbers
print("But using a foreach loop still works and we can print out the numbers...<br>");
foreach ($xmlObj->TelephoneNumbers->TelephoneNumber as $phoneObj) {
	printf("Phone: %s, Number: %s<br>", $phoneObj->Type, $phoneObj->Number);
}
?>
Produces:

Code: Select all

XML:
<Applicants>
    <TelephoneNumbers>
        <TelephoneNumber>
            <Number>01244123456</Number>
            <Type>Notification</Type>
        </TelephoneNumber>
        <TelephoneNumber>
            <Number>78787654321</Number>
            <Type>Mobile</Type>
        </TelephoneNumber>
    </TelephoneNumbers>
</Applicants>
SimpleXML Object:

SimpleXMLElement Object
(
    [TelephoneNumbers] => SimpleXMLElement Object
        (
            [TelephoneNumber] => Array
                (
                    [0] => SimpleXMLElement Object
                        (
                            [Number] => 01244123456
                            [Type] => Notification
                        )

                    [1] => SimpleXMLElement Object
                        (
                            [Number] => 78787654321
                            [Type] => Mobile
                        )

                )

        )

)

is_array($xmlObj->TelephoneNumbers->TelephoneNumber) gives: false

But using a foreach loop still works and we can print out the numbers...
Phone: Notification, Number: 01244123456
Phone: Mobile, Number: 78787654321
TIA.

Re: is_array says array is not an array!

Posted: Tue Oct 12, 2010 8:44 pm
by Jonah Bron
Try print_r()ing the value of just $xmlObj->TelephoneNumbers->TelephoneNumber ?

Re: is_array says array is not an array!

Posted: Tue Oct 12, 2010 9:18 pm
by nickweavers
I think the problem is with is_array(). The count() function seems to tell me something I can use; when $xmlObj->TelephoneNumbers->TelephoneNumber is a simpleXML Object it returns 1, and if it is an array (because the xml had more than one Telephone tag entry) it returns a number greater than one matching the number of Telephone tag entries.

Re: is_array says array is not an array!

Posted: Tue Oct 12, 2010 9:32 pm
by John Cartwright
$xmlObj->TelephoneNumbers->TelephoneNumber would actually represent a SimpleXMLElement, which contains an array of child elements. It is being reported as an array, and still works as an array is because it implements Traversable.

To get your desired results, you would need to either check if its an instance of Traversable, or cast it to an array.

Code: Select all

if ($xmlObj->TelephoneNumbers->TelephoneNumber instanceof Traversable) {}

//or 

// Would actually always return true, since we are casting it directly to an array
// Therefore, would be more appropriate to cast and use count()
if (is_array((array)$xmlObj->TelephoneNumbers->TelephoneNumber)) {}

Re: is_array says array is not an array!

Posted: Thu Mar 13, 2014 6:55 am
by aramix
The problem is that it is an object not array. So you should use is_object() instead.