Uzyskaj wartość z obiektu SimpleXMLElement

197

Mam coś takiego:

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

Ma pobierać XML z nazw geograficznych. Jeśli to zrobię print_r($xml), dostanę:

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
                )

Robię, jak widzisz, $xml->code[0]->lati zwraca obiekt. Jak mogę uzyskać wartość?

kubas
źródło
@kubas czy możesz wybrać odpowiedź?
kqw
1
Aktualizacja 2017: SO nie wyświetla już najlepszej odpowiedzi u góry. Najlepsza odpowiedź jest tutaj .
rinogo
2
@ rinogo Prawdopodobnie przypadkowo kliknąłeś jedną z kart sortowania u góry bloku odpowiedzi. Odpowiedź, do której linkujesz, ma 345 głosów, więc u góry widać, jeśli sortowanie jest ustawione na „głosy”.
IMSoP
1
Dzięki, @IMSoP! Masz rację - w pewnym momencie musiałem kliknąć „aktywne” (przydatne w przypadku starych pytań z nieaktualnymi odpowiedziami, btw) - dobrze wiedzieć, że muszę zmienić to z powrotem na „głosy”! :)
rinogo,

Odpowiedzi:

426

Musisz rzutować obiekt simpleXML na ciąg.

$value = (string) $xml->code[0]->lat;
Luis Melgratti
źródło
9
Właśnie zauważyłem, że jeśli json_encode obiekt xml, a następnie json_decode, otrzymujesz zagnieżdżony obiekt stdObject, z którym możesz sobie poradzić, całkiem przydatny, gdy jesteś leniwy i pracujesz z prostymi strukturami: D
Louis
1
głupie pytanie, ale czy to nie błąd? zobacz php.net/simplexml#95762 dlaczego nie musisz rzucać tekstu na niektóre pola, a na inne musisz?
gcb
7
Ta odpowiedź wciąż uderza w tyłek jeszcze mocniej w 2016 roku!
Hirdesh Vishwdewa,
4
nie mogę uwierzyć, że to takie skomplikowane. dlaczego mieliby tworzyć klasę o nazwie „getName”, a nie „getValue”? dlaczego mieliby drukować pusty ciąg, jeśli wydrukowałeś go zamiast przekonwertować go ręcznie na (ciąg). CZEMU??
user151496,
1
@ user151496 Technicznie rzecz biorąc, rzutowany ciąg nie daje „wartości”, ale „treść tekstową”. Ale tak, konkretnie nazwana metoda byłaby łatwiejsza do wykrycia. Kiedy już się do tego przyzwyczaisz, nie jest to wcale trudniejsze w użyciu .
IMSoP,
90

Możesz także użyć magicznej metody __toString ()

$xml->code[0]->lat->__toString()
sglessard
źródło
5
Lub sprintfw %sformacie. Lub echobuforowanie danych wyjściowych, lub lub lub lub ...
hakre
Jak mogę przekonwertować obiekt na XML w PHP? @sglessard
Gem
17

Jeśli wiesz, że wartością elementu XML jest liczba zmiennoprzecinkowa (szerokość, długość i odległość), możesz użyć (float)

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

Ponadto w (int)przypadku liczby całkowitej:

$value = (int) $xml->code[0]->distance;
Kursy
źródło
15

jeśli nie znasz wartości elementu XML, możesz użyć

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

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

Działa, gdy trzeba ustalić, czy wartość jest liczbą, ponieważ (string)zawsze zwróci ciąg i is_int($value)zwracafalse

Vladkras
źródło
Dowolny sposób sprawdzenia również wartości logicznej inny niż: (ciąg) $ wartość == „prawda” || (ciąg) $ wartość == „fałsz”?
Talisin
12

Dla mnie łatwiej jest używać tablic niż obiektów,

Konwertuję obiekt Xml,

$xml = simplexml_load_file('xml_file.xml');    
$json_string = json_encode($xml);    
$result_array = json_decode($json_string, TRUE);
dazzafact
źródło
3
Konwersja do JSON, a następnie powrót w tym samym kontekście, jest niezwykle nieefektywna, chyba że naprawdę się spieszysz. Praca z obiektami nie jest trudna, a jeśli naprawdę wolisz tablice, powinieneś natywnie przekonwertować obiekt na tablicę.
William
Nigdy nie rozumiem, dlaczego ludzie to zrobić - wyrzucić wszystkie cechy SimpleXML, tak więc można napisać $xml['foo'][0]['bar'][0]['@attributes']['baz']zamiast $xml->foo->bar['baz'].
IMSoP,
2

Ta funkcja zawsze pomogła mi przekonwertować wartości związane z XML na tablicę

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

    return $out;
}
pal4life
źródło
Spowoduje to wyrzucenie lub zerwanie między innymi: dowolnymi atrybutami, czymkolwiek w przestrzeni nazw, dowolnymi blokami CDATA. Wszystko po to, abyś mógł stracić metody wygody oferowane przez SimpleXML.
IMSoP
1

próbować current($xml->code[0]->lat)

zwraca element pod bieżącym wskaźnikiem tablicy, który wynosi 0, więc otrzymasz wartość

Bendeberia
źródło
1

możesz użyć „{}”, aby uzyskać dostęp do swojej nieruchomości, a następnie możesz zrobić, co chcesz. Zapisz lub wyświetl treść.

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

Z twojego przykładu jest to kod

        $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
źródło
3
Nie trzeba go używać, {}chyba że są w nim znaki specjalne, takie jak łączniki. $xml->{'key'}to po prostu brzydszy sposób pisania $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
źródło
2
W tej odpowiedzi nie ma żadnego wyjaśnienia, dlatego brakuje w niej kluczowej wiedzy, która echozmusza $vdo stania się ciągiem, a nie przedmiotem, tak jak (string)$vby to było.
IMSoP
0

Za pomocą tej funkcji można przekonwertować tablicę

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
źródło
Możesz, ale dlaczego miałbyś chcieć?
IMSoP
Ponieważ jeśli indeks jest liczbą, może to stanowić problem. Podobnie jak ta $ zmienna-> kod-> 0? Obiekt SimpleXMLElement ([kod] => Tablica ([0] => Obiekt SimpleXMLElement (...
nixis,
<0>nie jest prawidłowym znacznikiem XML, więc nigdy by się nie zdarzyło. Kilka prawidłowych nazw XML nie jest prawidłowymi nazwami PHP, na przykład <foo-bar>, ale można to obsłużyć za pomocą ->{'foo-bar'}składni. A może chodzi ci o dostęp do 0elementu th na liście podobnych nazwanych elementów? To jest po prostu $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;
   }
}
wyciągnięty
źródło
Nie jestem pewien, co ten fragment kodu próbuje pokazać, ale wygląda na to, że jest to bardzo skomplikowany (i zły) sposób pisania $codeZero = $xml->code[0]i$lat = $xml->code[0]->lat
IMSoP
@IMSoP, głosujesz nad tym, nawet nie próbując kodu? Nie opublikowałbym tego, gdyby to nie zadziałało. Twoja sugestia nie pozwala na foreach, które są czystsze niż prosta pętla for. Nie pamiętam już wszystkich szczegółów, ale zadziałało, gdy inne rozwiązania nie.
wyciągnął
Głosowałem głównie, ponieważ nie ma wyjaśnienia, co robi. Jeśli nawet go nie rozumiesz, kiedy go odczytujesz, jak może być przydatny dla kogokolwiek innego? Jeśli chodzi o korzystanie z foreach, na pewno możesz: foreach ( $xml->code as $code ) { $lat = (string)$code->lat; echo $lat; }Ale to, co zapętlasz tutaj, to „wszystkie dzieci pierwszego <code>elementu”; co nie ma dla mnie większego sensu. Dla wyjaśnienia $xml->code->children()jest skrótem $xml->code[0]->children(), a nie „dzieci powołane code”.
IMSoP,
@IMSoP, cóż, to słuszna kwestia. Powinienem był wyjaśnić; prawdopodobnie wydawało mi się to wtedy tak oczywiste, że nie przyszło mi to do głowy. Jednak przynajmniej na moją korzyść jest fakt, że ktokolwiek jest na tej stronie, zna już kontekst i nie potrzebuje wyjaśnienia, ponieważ już wie, co się dzieje. Dowodzi tego fakt, że jedna osoba już głosowała za moją odpowiedzią, inaczej byłbym negatywny. Zrobię lepiej, publikując wyjaśnienie w przyszłości.
wyciągnął
Mogę też prawie zagwarantować, że najpierw wypróbowałbym twoją sugestię, która nie zadziałała, więc musiałem znaleźć inną.
wyciągnął
-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
źródło