Dapatkan nilai dari Objek SimpleXMLElement

197

Saya punya sesuatu seperti ini:

$url = "http://ws.geonames.org/findNearbyPostalCodes?country=pl&placename=";
$url .= rawurlencode($city[$i]);

$xml = simplexml_load_file($url);
echo $url."\n";
$cityCode[] = array(
    'city' => $city[$i], 
    'lat' => $xml->code[0]->lat, 
    'lng' => $xml->code[0]->lng
);

Seharusnya mengunduh XML dari geonames. Jika saya melakukannya print_r($xml)saya mendapatkan:

SimpleXMLElement Object
(
    [code] => Array
        (
            [0] => SimpleXMLElement Object
                (
                    [postalcode] => 01-935
                    [name] => Warszawa
                    [countryCode] => PL
                    [lat] => 52.25
                    [lng] => 21.0
                    [adminCode1] => SimpleXMLElement Object
                        (
                        )

                    [adminName1] => Mazowieckie
                    [adminCode2] => SimpleXMLElement Object
                        (
                        )

                    [adminName2] => Warszawa
                    [adminCode3] => SimpleXMLElement Object
                        (
                        )

                    [adminName3] => SimpleXMLElement Object
                        (
                        )

                    [distance] => 0.0
                )

Saya lakukan seperti yang Anda lihat $xml->code[0]->latdan mengembalikan objek. Bagaimana saya bisa mendapatkan nilainya?

kubas
sumber
@ Kubas, bisakah Anda memilih jawaban?
kqw
1
Pembaruan 2017: SO tidak lagi menampilkan jawaban terbaik di atas. Jawaban terbaik ada di sini .
rinogo
2
@rinogo Anda mungkin secara tidak sengaja mengklik salah satu tab penyortiran di bagian atas blok jawaban. Jawaban yang Anda tautkan memiliki 345 suara, jadi tunjukkan di bagian atas jika Anda mengurutkan yang diatur ke "suara".
IMSoP
1
Terima kasih, @IMSoP! Anda benar - saya harus mengklik "aktif" di beberapa titik (berguna untuk pertanyaan lama dengan jawaban yang sudah ketinggalan zaman, btw) - bagus untuk mengetahui saya perlu mengubahnya kembali ke "suara"! :)
rinogo

Jawaban:

426

Anda harus melemparkan objek simpleXML ke string.

$value = (string) $xml->code[0]->lat;
Luis Melgratti
sumber
9
Hanya perhatikan jika Anda json_encode objek xml dan kemudian json_decode Anda mendapatkan stdObject bersarang untuk berurusan dengan, cukup berguna untuk ketika Anda sedang malas & bekerja dengan struktur sederhana: D
Louis
1
pertanyaan konyol, tapi bukankah itu bug? lihat php.net/simplexml#95762 mengapa Anda tidak harus membuat tipe pada beberapa bidang tetapi pada yang lain Anda harus?
gcb
7
Jawaban ini masih lebih sulit di tahun 2016!
Hirdesh Vishwdewa
4
Saya tidak percaya ini sangat rumit. mengapa mereka membuat kelas yang disebut "getName" tetapi tidak "getValue"? mengapa mereka mencetak string kosong jika Anda mencetaknya alih-alih dikonversi secara manual ke (string). MENGAPA??
user151496
1
@ user151496 Secara teknis, pemeran string tidak memberi Anda "nilai", tetapi "konten teks". Tapi ya, metode yang diberi nama khusus akan lebih mudah ditemukan. Namun, begitu Anda terbiasa dengan hal ini, sebenarnya tidak lebih sulit untuk digunakan .
IMSoP
91

Anda juga dapat menggunakan metode ajaib __toString ()

$xml->code[0]->lat->__toString()
sglessard
sumber
5
Atau sprintfdengan %sformat. Atau echodan output buffering, atau atau atau ...
hakre
Bagaimana saya bisa mengkonversi objek ke XML di PHP? @sglessard
Permata
17

Jika Anda tahu bahwa nilai elemen XML adalah angka float (lintang, bujur, jarak), Anda bisa menggunakan (float)

$value = (float) $xml->code[0]->lat;

Juga, (int)untuk bilangan bulat:

$value = (int) $xml->code[0]->distance;
KursusWeb
sumber
15

jika Anda tidak tahu nilai Elemen XML, Anda bisa menggunakannya

$value = (string) $xml->code[0]->lat;

if (ctype_digit($value)) {
    // the value is probably an integer because consists only of digits
}

Ini berfungsi ketika Anda perlu menentukan apakah nilai adalah angka, karena (string)akan selalu mengembalikan string dan is_int($value)mengembalikanfalse

vladkras
sumber
Cara apa pun untuk memeriksa juga boolean selain: (string) $ value == 'true' || (string) $ value == 'false'?
Talisin
12

Bagi saya lebih mudah menggunakan array daripada objek,

Jadi, saya mengonversi Xml-Object,

$xml = simplexml_load_file('xml_file.xml');    
$json_string = json_encode($xml);    
$result_array = json_decode($json_string, TRUE);
mempesona
sumber
3
Konversi ke JSON dan kemudian kembali dalam konteks yang sama sangat tidak efisien kecuali Anda benar-benar terburu-buru. Bekerja dengan objek tidak sulit, dan jika Anda benar-benar lebih suka array, Anda harus mengkonversi objek ke array secara native.
William
Saya tidak pernah mengerti mengapa orang melakukan hal ini - Anda membuang semua fitur SimpleXML, hanya agar Anda dapat menulis $xml['foo'][0]['bar'][0]['@attributes']['baz']bukan $xml->foo->bar['baz'].
IMSoP
2

Ini adalah fungsi yang selalu membantu saya mengonversi nilai terkait xml ke array

function _xml2array ( $xmlObject, $out = array () ){
    foreach ( (array) $xmlObject as $index => $node )
        $out[$index] = ( is_object ( $node ) ) ? _xml2array ( $node ) : $node;

    return $out;
}
pal4life
sumber
Ini akan membuang, atau memutuskan, antara lain: atribut apa pun, apa pun dalam ruang nama, blok CDATA apa pun. Semuanya agar Anda dapat kehilangan metode kenyamanan yang ditawarkan SimpleXML kepada Anda.
IMSoP
1

mencoba current($xml->code[0]->lat)

ia mengembalikan elemen di bawah pointer array saat ini, yaitu 0, sehingga Anda akan mendapatkan nilai

Bendeberia
sumber
1

Anda dapat menggunakan '{}' untuk mengakses properti Anda, dan kemudian Anda dapat melakukan seperti yang Anda inginkan. Simpan atau tampilkan konten.

    $varName = $xml->{'key'};

Dari contoh Anda dia adalah kode

        $filePath = __DIR__ . 'Your path ';
        $fileName = 'YourFilename.xml';

        if (file_exists($filePath . $fileName)) {
            $xml = simplexml_load_file($filePath . $fileName);
            $mainNode = $xml->{'code'};

            $cityArray = array();

            foreach ($mainNode as $key => $data)        {
               $cityArray[..] = $mainNode[$key]['cityCode'];
               ....

            }     

        }
Zakaria Charik
sumber
3
Tidak perlu menggunakan {}kecuali ada karakter khusus seperti tanda hubung di sana. $xml->{'key'}hanyalah cara penulisan yang lebih jelek $xml->key.
IMSoP
0
header("Content-Type: text/html; charset=utf8");
$url  = simplexml_load_file("http://URI.com");

 foreach ($url->PRODUCT as $product) {  
    foreach($urun->attributes() as $k => $v) {
        echo $k." : ".$v.' <br />';
    }
    echo '<hr/>';
}
Şahin Solmaz
sumber
2
Jawaban ini kurang penjelasan, dan karena itu melewatkan wawasan kunci yang echomemaksa $vuntuk menjadi string daripada objek, seperti yang (string)$vakan terjadi.
IMSoP
0

Anda dapat mengonversi array dengan fungsi ini

function xml2array($xml){
$arr = array();

foreach ($xml->children() as $r)
{
    $t = array();
    if(count($r->children()) == 0)
    {
        $arr[$r->getName()] = strval($r);
    }
    else
    {
        $arr[$r->getName()][] = xml2array($r);
    }
}
return $arr;
}
nixis
sumber
Anda bisa, tetapi mengapa Anda mau?
IMSoP
Karena jika indeks adalah angka, itu mungkin masalah. Suka $ variable-> code-> 0 ini? SimpleXMLElement Object ([code] => Array ([0] => SimpleXMLElement Object (...
nixis
<0>bukan tag XML yang valid, jadi itu tidak akan pernah terjadi. Beberapa nama XML yang valid bukan nama PHP yang valid <foo-bar>, tetapi itu dapat ditangani dengan ->{'foo-bar'}sintaks. Atau maksud Anda hanya mengakses 0elemen ke dalam daftar elemen bernama serupa? Itu baru saja $parent->childName[0].
IMSoP
0
$codeZero = null;
foreach ($xml->code->children() as $child) {
   $codeZero = $child;
}

$lat = null;
foreach ($codeZero->children() as $child) {
   if (isset($child->lat)) {
      $lat = $child->lat;
   }
}
derek
sumber
Saya tidak yakin apa yang ingin ditampilkan cuplikan kode ini, tetapi sepertinya ini cara penulisan yang sangat berbelit-belit (dan salah) $codeZero = $xml->code[0]dan$lat = $xml->code[0]->lat
IMSoP
@ IMSoP, Anda memilih ini tanpa mencoba kodenya? Saya tidak akan mempostingnya jika tidak berhasil. Saran Anda tidak memungkinkan untuk foreach, yang lebih bersih daripada sederhana untuk loop. Saya tidak ingat semua detail lagi, tetapi itu berhasil ketika solusi lain tidak.
derek
Saya menolak sebagian besar karena tidak memiliki penjelasan tentang apa yang dilakukannya. Jika bahkan Anda tidak memahaminya ketika Anda membacanya kembali, bagaimana itu seharusnya bermanfaat bagi orang lain? Sedangkan untuk menggunakan foreach, pasti Anda bisa: foreach ( $xml->code as $code ) { $lat = (string)$code->lat; echo $lat; }Tapi apa yang Anda putar di sini adalah "semua anak-anak dari <code>elemen pertama "; yang tidak masuk akal bagi saya. Untuk memperjelas, $xml->code->children()adalah singkatan $xml->code[0]->children(), bukan "anak-anak dipanggil code".
IMSoP
@ IMSoP, Yah, itu poin yang adil. Saya seharusnya memberikan penjelasan; mungkin tampak begitu jelas bagi saya pada saat itu sehingga tidak terpikir oleh saya. Namun, paling menguntungkan saya, setidaknya, adalah fakta bahwa siapa pun yang ada di halaman ini sudah mengetahui konteksnya dan tidak perlu penjelasan karena mereka sudah tahu apa yang terjadi. Ini dibuktikan oleh fakta bahwa satu orang sudah memberikan suara saya pada jawaban saya atau sekarang saya akan berada dalam posisi negatif. Saya akan lebih baik memposting penjelasan di masa depan.
derek
Juga, saya hampir dapat menjamin saya akan mencoba saran Anda terlebih dahulu, dan itu tidak berhasil sehingga saya harus mencari yang lain.
derek
-2
foreach($xml->code as $vals )
{ 
    unset($geonames);
    $vals=(array)$vals;
    foreach($vals as $key => $value)
      {
        $value=(array)$value;
        $geonames[$key]=$value[0];
      }
}
print_r($geonames);
Amal Jo Antony
sumber