Obtenir la valeur de l'objet SimpleXMLElement


197

J'ai quelque chose comme ça:

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

Il est censé télécharger XML à partir de noms géographiques. Si print_r($xml)je reçois:

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
                )

Je fais ce que vous voyez $xml->code[0]->latet cela renvoie un objet. Comment puis-je obtenir la valeur?



@kubas pouvez-vous sélectionner une réponse?
kqw

1
Mise à jour 2017: SO n'affiche plus la meilleure réponse en haut. La meilleure réponse est ici .
rinogo

2
@rinogo Vous avez probablement accidentellement cliqué sur l'un des onglets de tri en haut du bloc de réponses. La réponse à laquelle vous avez lié a 345 votes, indique donc en haut si le tri est défini sur "votes".
IMSoP

1
Merci, @IMSoP! Vous avez raison - je dois avoir cliqué sur "actif" à un moment donné (utile pour les vieilles questions avec des réponses obsolètes, btw) - bon à savoir, je dois le changer de nouveau en "votes"! :)
rinogo

Réponses:


426

Vous devez convertir un objet simpleXML en une chaîne.

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

9
Juste remarqué si vous json_encode l'objet xml puis json_decode, vous obtenez un stdObject imbriqué à traiter, très pratique lorsque vous êtes paresseux et travaillez avec des structures simples: D
Louis

1
question idiote, mais n'est-ce pas un bug? voir php.net/simplexml#95762 pourquoi vous n'avez pas à transtyper du type sur certains champs mais sur d'autres vous le devez?
gcb

7
Cette réponse frappe encore plus fort en 2016!
Hirdesh Vishwdewa

4
je ne peux pas croire que ce soit si compliqué. pourquoi feraient-ils une classe appelée "getName" mais pas "getValue"? pourquoi imprimeraient-ils une chaîne vide si vous l'imprimiez au lieu de la convertir manuellement en (chaîne). POURQUOI??
user151496

1
@ user151496 Techniquement, le transtypage de chaîne ne vous donne pas la "valeur", mais le "contenu texte". Mais oui, une méthode spécifiquement nommée serait plus découvrable. Une fois que vous vous y êtes habitué, ce n'est pas plus difficile à utiliser .
IMSoP

91

Vous pouvez également utiliser la méthode magique __toString ()

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

5
Ou sprintfavec le %sformat. Ou echoet tampon de sortie, ou ou ou ou ou ...
hakre

Comment puis-je convertir l'objet en XML en PHP? @sglessard
Gem

17

Si vous savez que la valeur de l'élément XML est un nombre flottant (latitude, longitude, distance), vous pouvez utiliser (float)

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

Aussi, (int)pour un nombre entier:

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

15

si vous ne connaissez pas la valeur de XML Element, vous pouvez utiliser

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

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

Cela fonctionne lorsque vous devez déterminer si la valeur est un nombre, car (string)renvoie toujours une chaîne et is_int($value)renvoiefalse


N'importe quelle manière de vérifier également les booléens autres que: (string) $ value == 'true' || (chaîne) $ value == 'false'?
Talisin

12

Pour moi, c'est plus facile à utiliser des tableaux que des objets,

Donc, je convertis un objet Xml,

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

3
Convertir en JSON puis revenir dans le même contexte est incroyablement inefficace à moins que vous ne soyez vraiment pressé. Travailler avec des objets n'est pas difficile, et si vous préférez vraiment les tableaux, vous devez convertir l'objet en tableau nativement.
William

Je ne comprends jamais pourquoi les gens font ça - vous jetez toutes les fonctionnalités de SimpleXML, juste pour pouvoir écrire à la $xml['foo'][0]['bar'][0]['@attributes']['baz']place de $xml->foo->bar['baz'].
IMSoP

2

C'est la fonction qui m'a toujours aidé à convertir les valeurs liées au xml en tableau

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

    return $out;
}

Cela supprimera, ou rompra, entre autres: tous les attributs, tout dans un espace de noms, tous les blocs CDATA. Tout cela pour que vous puissiez perdre les méthodes pratiques que SimpleXML vous a proposées en premier lieu.
IMSoP

1

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

il retourne l'élément sous le pointeur actuel du tableau, qui est 0, donc vous obtiendrez une valeur


1

vous pouvez utiliser le '{}' pour accéder à votre propriété, puis vous pouvez faire ce que vous voulez. Enregistrez-le ou affichez le contenu.

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

D'après votre exemple, c'est le code

        $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
Il n'est pas nécessaire de l'utiliser {}sauf s'il y a des caractères spéciaux comme des tirets. $xml->{'key'}est juste une façon plus laide d'écrire $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
Cette réponse manque d'explication, et manque donc la vision clé qui est que les echoforces $vdeviennent une chaîne plutôt qu'un objet, tout comme le (string)$vferait.
IMSoP

0

vous pouvez convertir un tableau avec cette fonction

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

Vous pouvez, mais pourquoi voudriez-vous?
IMSoP

Parce que si l'index est un nombre, cela peut être un problème. Vous aimez ce $ variable-> code-> 0? Objet SimpleXMLElement ([code] => Array ([0] => Objet SimpleXMLElement (...
nixis

<0>n'est pas une balise XML valide, donc cela ne se produira jamais. Quelques noms XML valides ne sont pas des noms PHP valides, comme <foo-bar>, mais cela peut être géré avec la ->{'foo-bar'}syntaxe. Ou voulez-vous simplement dire accéder à l' 0élément e dans une liste d'éléments nommés similaires? C'est juste $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;
   }
}

Je ne suis pas sûr de ce que cet extrait de code essaie de montrer, mais il semble que ce soit une façon très compliquée (et erronée) d'écrire $codeZero = $xml->code[0]et$lat = $xml->code[0]->lat
IMSoP

@IMSoP, vous votez cela sans même essayer le code? Je ne l'aurais pas posté si ça n'avait pas marché. Votre suggestion ne permet pas une boucle foreach, qui est plus propre qu'une simple boucle for. Je ne me souviens plus de tous les détails, mais cela a fonctionné lorsque d'autres solutions ne l'ont pas été.
grue

J'ai voté principalement parce qu'il n'a aucune explication de ce qu'il fait. Si même vous ne le comprenez pas lorsque vous le relisez, comment est-il censé être utile à quelqu'un d'autre? En ce qui concerne l'utilisation d'un foreach, vous pouvez bien sûr: foreach ( $xml->code as $code ) { $lat = (string)$code->lat; echo $lat; }Mais ce que vous parcourez ici, c'est "tous les enfants du premier <code>élément"; ce qui n'a pas beaucoup de sens pour moi. Pour clarifier, $xml->code->children()c'est un raccourci $xml->code[0]->children(), pas "des enfants appelés code".
IMSoP

@IMSoP, Eh bien, c'est un bon point. J'aurais dû fournir une explication; cela me semblait probablement si évident à l'époque que cela ne m'est pas venu à l'esprit. Cependant, en ma faveur, au moins, est le fait que celui qui est sur cette page connaît déjà le contexte et n'aura pas besoin d'explication parce qu'il sait déjà ce qui se passe. Cela est prouvé par le fait qu'une personne a déjà voté pour ma réponse ou je serais maintenant dans le négatif. Je ferai mieux de publier une explication à l'avenir.
grue

De plus, je peux presque garantir que j'aurais essayé votre suggestion en premier, et cela n'a pas fonctionné, j'ai donc dû en trouver une autre.
grue

-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);
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.