开发者

Why does SimpleXML change my array to the array's first element when I use it?

Here is my code:

$string = <<<XML
<?xml version='1.0'?> 
<test>
 <testing>
  <lol>hello</lol>
  <lol>there</lol>
 </testing>
</test>
XML;
$xml = simplexml_load_string($string);
echo "All of the XML:\n";
print_r $xml;
echo "\n\nJust the 'lol' array:";
print_r $xml->testing->lol;

Output:

All of the XML:

SimpleXMLElement Object
(
    [testing] => SimpleXMLElement Object
        (
            [lol] => Array
                (
                    [0] => hello
                    [1] => there
                )

        )

)




Just the 'lol' array:

SimpleXMLElement Object
(
    [0] => hello
)

开发者_JS百科Why does it output only the [0] instead of the whole array? I dont get it.


What @Yottatron suggested is true, but not at all the cases as this example shows :

if your XML would be like this:

<?xml version='1.0'?>
<testing>
    <lol>
        <lolelem>Lol1</lolelem>
        <lolelem>Lol2</lolelem>
        <notlol>NotLol1</lolelem>
        <notlol>NotLol1</lolelem>
    </lol>
</testing>

Simplexml's output would be:

SimpleXMLElement Object
(
[lol] => SimpleXMLElement Object
    (
        [lolelem] => Array
            (
                [0] => Lol1
                [1] => Lol2
            )

        [notlol] => Array
            (
                [0] => NotLol1
                [1] => NotLol1
            )

    )

)

and by writing

$xml->lol->lolelem

you'd expect your result to be

Array
(
     [0] => Lol1
     [1] => Lol2
)

but instead of it, you would get :

SimpleXMLElement Object 
(
    [0] => Lol1
)

and by

$xml->lol->children()

you would get:

SimpleXMLElement Object
(
[lolelem] => Array
    (
        [0] => Lol1
        [1] => Lol2
    )

[notlol] => Array
    (
        [0] => NotLol1
        [1] => NotLol1
    )

)

What you need to do if you want only the lolelem's:

$xml->xpath("//lol/lolelem")

That gives this result (not as expected shape but contains the right elements)

Array
(
    [0] => SimpleXMLElement Object
    (
        [0] => Lol1
    )

    [1] => SimpleXMLElement Object
    (
        [0] => Lol2
    )

)


It's because you have two lol elements. In order to access the second you need to do this:

$xml->testing->lol[1];

this will give you "there"

$xml->testing->lol[0];

Will give you "hello"

The children() method of the SimpleXMLElement will give you an object containing all the children of an element for example:

$xml->testing->children();

will give you an object containing all the children of the "testing" SimpleXMLElement.

If you need to iterate, you can use the following code:

foreach($xml->testing->children() as $ele)
{
    var_dump($ele);
}

There is more information about SimpleXMLElement here:

http://www.php.net/manual/en/class.simplexmlelement.php


what you might want to do is using the Json encode/decode

$jsonArray = Json_decode(Json_encode($xml), true);

With the true argument you can call instead of using -> use [name]

so an example would be:

$xml = file("someXmlFile.xml");
$jsonArray = Json_decode(Json_encode($xml), true);
foreach(jsonArray['title'] as $title){
   Do something with $titles
}

if you have more than 1 element it will typical put in an @attributes if the elements has attributes. This can be countered by using: $title = $title['@attributes']

Hope it could help.


Ah yes, I remember simple XML nearly doing my head in with this parsing arrays issue Try the below code. It will give you an array of LOL elements, or, if you've just got a single LOL element, it will return that in an array as well.

The main advantage of that is you can do something like foreach ($lol as $element) and it will still work on a single (or on 0) LOL element.

<?php
$string = <<<XML
<?xml version='1.0'?> 
   <test>
     <testing>
      <lol>hello</lol>
      <lol>there</lol>
     </testing>
   </test>
XML;

$xml = simplexml_load_string($string);
echo "<pre>";
echo "All of the XML:\n";
print_r($xml);

echo "\n\nJust the 'lol' array:\n";

$test_lols = $xml->testing->children();              
$childcount = count($test_lols);
if ($childcount < 2) {
    $lol = array($test_lols->lol);                   
}
else {
    $lol = (array) $test_lols;
    $lol = $lol['lol'];
    }

print_r($lol);
?>


Ran into this issue...

Xpath can be a little slow, so you can achieve the same effect with a simple for loop.

for ($i = 0; $i < count($xml->testing->lol); $i++) {
    print_r($xml->testing->lol[$i]);
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜