2011-07-22 11 views
8

Oto mój kod:Dlaczego SimpleXML zmienia moją tablicę na pierwszy element tablicy, kiedy jej używam?

$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; 

wyjściowa:

All of the XML: 

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

     ) 

) 




Just the 'lol' array: 

SimpleXMLElement Object 
(
    [0] => hello 
) 

Dlaczego to wyjście tylko [0] zamiast cała tablica? Nie rozumiem tego.

Odpowiedz

5

To dlatego, że masz dwa elementy LOL. W celu uzyskania dostępu do drugiego trzeba to zrobić:

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

to daje "tam"

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

daje "cześć"

Dzieci() Sposób SimpleXMLElement da ci obiekt zawierający wszystkie elementy potomne elementu, na przykład:

$xml->testing->children(); 

dostarczy Ci n obiekt zawierający wszystkie dzieci "testowania" SimpleXMLElement.

Jeśli trzeba iteracyjne, można użyć następującego kodu:

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

znajduje się więcej informacji na temat SimpleXMLElement tutaj:

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

+0

Czy to pomogło w rozwiązaniu problemu? –

+1

@ Yattatron to w ogóle nie odpowiada na pytanie "dlaczego". jak mówisz, '$ lol [1]' = "tam" i '$ lol [0]' = "cześć", więc dlaczego 'print_r ($ lol)' nie wydrukuje '0 =>" cześć ", 1 => "tam" '?? – chiliNUT

+0

@chiliNUT Masz bardzo ważny punkt. Będę myślał i trochę poprawił moją odpowiedź. –

6

Co sugeruje @Yottatron to prawda, ale nie we wszystkich przypadkach, jak pokazuje ten przykład:

jeśli twój XML byłby taki:

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

wyjście SimpleXML byłoby:

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

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

    ) 

) 

i pisząc

$xml->lol->lolelem 

można się spodziewać Twój wynik będzie

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

ale zamiast tego, byś Uzyskaj:

SimpleXMLElement Object 
(
    [0] => Lol1 
) 

i

$xml->lol->children() 

dostaniemy:

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

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

) 

Co trzeba zrobić, jeśli chcesz tylko lolelem użytkownika:

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

Daje to wynik (nie zgodnie z oczekiwanym kształtem, ale zawiera właściwe elementy)

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

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

) 
0

Ran w tej kwestii ...

Xpath może być trochę powolny, dzięki czemu można osiągnąć ten sam efekt w prosty dla pętli.

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

co możesz zrobić, to stosując kodowanie json/dekodowania

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

Z prawdziwego argumentu można zadzwonić zamiast używania -> Użyj [nazwa]

więc przykładem byłby:

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

jeśli masz więcej niż 1 element, to będzie on typowy w @ Atrybutach, jeśli elementy będą s atrybuty. Można temu zapobiec, używając: $title = $title['@attributes']

Mam nadzieję, że to pomoże.

1

Ah tak, pamiętam prosty XML prawie robiący moją głowę z tym parsującym problemem tablic Spróbuj poniższy kod. Daje ci tablicę elementów LOL, lub, jeśli masz tylko jeden element LOL, zwróci to również w tablicy.

Główną zaletą tego jest to, że możesz zrobić coś takiego jak foreach ($ lol jako element $) i nadal będzie działać na pojedynczym (lub na 0) elemencie LOL.

<?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); 
?> 
Powiązane problemy