Ottieni valore dall'oggetto SimpleXMLElement


197

Ho qualcosa del genere:

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

Dovrebbe scaricare XML da geonames. Se lo faccio print_r($xml)ottengo:

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
                )

Faccio come puoi vedere $xml->code[0]->late restituisce un oggetto. Come posso ottenere il valore?



@kubas puoi selezionare una risposta?
kqw,

1
Aggiornamento 2017: SO non visualizza più la migliore risposta in alto. La risposta migliore è qui .
Rinogo,

2
@rinogo Probabilmente hai fatto accidentalmente clic su una delle schede di ordinamento nella parte superiore del blocco di risposta. La risposta a cui hai collegato ha 345 voti, quindi viene visualizzata in alto se l'ordinamento è impostato su "voti".
IMSoP,

1
Grazie, @IMSoP! Hai ragione - a un certo punto devo aver fatto clic su "attivo" (utile per vecchie domande con risposte obsolete, a proposito) - buono a sapersi, devo cambiarlo in "voti"! :)
rinogo,

Risposte:


426

Devi lanciare l'oggetto SimpleXML su una stringa.

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

9
Ho appena notato se json_encode l'oggetto xml e poi json_decode lo ottieni uno stdObject nidificato da trattare, abbastanza utile per quando sei pigro e lavori con strutture semplici: D
Louis,

1
domanda stupida, ma non è un insetto? vedi php.net/simplexml#95762 perché non devi trasmettere il tipo su alcuni campi ma su altri devi?
CG

7
Questa risposta sta ancora dando un calcio ancora più difficile nel 2016!
Hirdesh Vishwdewa,

4
non posso credere che sia così complicato. perché dovrebbero creare una classe chiamata "getName" ma non "getValue"? perché dovrebbero stampare una stringa vuota se la stampassi invece di convertirla manualmente in (stringa). PERCHÉ??
user151496,

1
@ user151496 Tecnicamente, il cast della stringa non ti dà il "valore", ma il "contenuto del testo". Ma sì, un metodo con un nome specifico sarebbe più rilevabile. Una volta che ti ci abitui, però, in realtà non è più difficile da usare .
IMSoP,

91

Puoi anche usare il metodo magico __toString ()

$xml->code[0]->lat->__toString()

5
O sprintfcon il %sformato. O echoe buffer di output, o o o o ...
hakre,

Come posso convertire l'oggetto in XML in PHP? @sglessard
Gem

17

Se sai che il valore dell'elemento XML è un numero float (latitudine, longitudine, distanza), puoi usare (float)

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

Inoltre, (int)per il numero intero:

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

15

se non conosci il valore di XML Element, puoi usarlo

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

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

Funziona quando è necessario determinare se il valore è un numero, perché (string)restituirà sempre stringa e is_int($value)restituiscefalse


Qualsiasi modo per verificare anche la presenza di valori booleani diversi da: (stringa) $ value == 'true' || (stringa) $ value == 'false'?
Talisin,

12

Per me è più facile usare le matrici che gli oggetti,

Quindi, converto un oggetto Xml,

$xml = simplexml_load_file('xml_file.xml');    
$json_string = json_encode($xml);    
$result_array = json_decode($json_string, TRUE);

3
La conversione in JSON e poi di nuovo nello stesso contesto è incredibilmente inefficiente a meno che tu non abbia davvero fretta. Lavorare con gli oggetti non è difficile e se preferisci davvero le matrici, devi convertire l'oggetto in una matrice in modo nativo.
William,

Non capisco mai perché la gente faccia questo: butti via tutte le funzionalità di SimpleXML, solo così puoi scrivere $xml['foo'][0]['bar'][0]['@attributes']['baz']invece di $xml->foo->bar['baz'].
IMSoP,

2

Questa è la funzione che mi ha sempre aiutato a convertire i valori relativi all'xml in array

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

    return $out;
}

Questo getterà via, o si romperà, tra le altre cose: qualsiasi attributo, qualsiasi cosa in uno spazio dei nomi, qualsiasi blocco CDATA. Tutto solo per poter perdere i metodi di praticità che SimpleXML ti ha offerto in primo luogo.
IMSoP,

1

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

restituisce elemento sotto il puntatore corrente dell'array, che è 0, quindi otterrai valore


1

puoi usare "{}" per accedere alla tua proprietà, quindi puoi fare ciò che desideri. Salvalo o visualizza il contenuto.

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

Dal tuo esempio lei è il codice

        $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'];
               ....

            }     

        }

3
Non è necessario usarlo a {}meno che non ci siano caratteri speciali come trattini. $xml->{'key'}è solo un modo più brutto di scrivere $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/>';
}

2
Questa risposta è priva di qualsiasi spiegazione e quindi manca l'intuizione chiave che è che echocostringe $va diventare una stringa anziché un oggetto, proprio come (string)$vfarebbe.
IMSoP,

0

puoi convertire l'array con questa funzione

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

Puoi, ma perché dovresti?
IMSoP,

Perché se index è un numero, potrebbe essere un problema. Ti piace questa $ variabile-> codice-> 0? Oggetto SimpleXMLElement ([code] => Array ([0] => Oggetto SimpleXMLElement (...
nixis

<0>non è un tag XML valido, quindi ciò non accadrà mai. Alcuni nomi XML validi non sono nomi PHP validi, come <foo-bar>, ma che possono essere gestiti con la ->{'foo-bar'}sintassi. O intendi semplicemente accedere 0all'elemento th in un elenco di elementi simili? Questo è solo $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;
   }
}

Non sono sicuro di cosa stia cercando di mostrare questo frammento di codice, ma sembra che sia un modo molto contorto (e sbagliato) di scrivere $codeZero = $xml->code[0]e$lat = $xml->code[0]->lat
IMSoP,

@IMSoP, lo stai votando senza nemmeno provare il codice? Non l'avrei pubblicato se non avesse funzionato. Il tuo suggerimento non consente un foreach, che è più pulito di un semplice ciclo. Non ricordo più tutti i dettagli, ma ha funzionato quando altre soluzioni no.
Craned l'

Ho votato verso il basso principalmente perché non ha alcuna spiegazione di ciò che sta facendo. Se anche tu non lo capisci quando lo rileggi, come dovrebbe essere utile a chiunque altro? Per quanto riguarda l'uso di un foreach, certo che puoi: foreach ( $xml->code as $code ) { $lat = (string)$code->lat; echo $lat; }Ma quello che stai facendo un loop qui è "tutti i figli del primo <code>elemento"; che non ha molto senso per me. Per chiarire, $xml->code->children()è una scorciatoia per $xml->code[0]->children(), non "bambini chiamati code".
IMSoP

@IMSoP, Beh, questo è un punto giusto. Avrei dovuto fornire una spiegazione; probabilmente mi è sembrato così ovvio al momento che non mi è venuto in mente. Tuttavia, a mio favore, almeno, è il fatto che chiunque sia in questa pagina conosce già il contesto e non avrà bisogno di una spiegazione perché sa già cosa sta succedendo. Ciò è dimostrato dal fatto che una persona ha già votato a favore della mia risposta o che ora sarei in negativo. Farò meglio a pubblicare una spiegazione in futuro.
Craned l'

Inoltre, posso quasi garantire che avrei provato prima il tuo suggerimento, e non ha funzionato, quindi ho dovuto trovarne un altro.
allungato l'

-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);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.