Wert vom SimpleXMLElement-Objekt abrufen

197

Ich habe so etwas:

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

Es soll XML von Geonamen herunterladen. Wenn ich das print_r($xml)bekomme, bekomme ich:

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
                )

Ich mache, wie Sie sehen können, $xml->code[0]->latund es gibt ein Objekt zurück. Wie kann ich den Wert erhalten?

Kubas
quelle
@kubas kannst du eine Antwort auswählen?
kqw
1
Update 2017: SO zeigt oben nicht mehr die beste Antwort an. Die beste Antwort ist hier .
Rinogo
2
@rinogo Sie haben wahrscheinlich versehentlich auf eine der Sortierregisterkarten oben im Antwortblock geklickt. Die Antwort, mit der Sie verlinkt haben, hat 345 Stimmen. Wird also oben angezeigt, wenn die Sortierung auf "Stimmen" eingestellt ist.
IMSoP
1
Danke, @IMSoP! Sie haben Recht - ich muss irgendwann auf "aktiv" geklickt haben (nützlich für alte Fragen mit veralteten Antworten, übrigens) - gut zu wissen, dass ich es wieder in "Stimmen" ändern muss! :)
Rinogo

Antworten:

426

Sie müssen simpleXML Object in eine Zeichenfolge umwandeln.

$value = (string) $xml->code[0]->lat;
Luis Melgratti
quelle
9
Gerade bemerkt, wenn Sie das XML-Objekt json_encode und dann json_decode es, erhalten Sie ein verschachteltes stdObject, mit dem Sie umgehen können, sehr praktisch, wenn Sie faul sind und mit einfachen Strukturen arbeiten: D
Louis
1
dumme Frage, aber ist das nicht ein Fehler? siehe php.net/simplexml#95762 warum müssen Sie nicht auf einigen Feldern schreiben, sondern auf anderen?
GCB
7
Diese Antwort ist auch 2016 noch schwieriger!
Hirdesh Vishwdewa
4
Ich kann nicht glauben, dass das so kompliziert ist. Warum sollten sie eine Klasse namens "getName" erstellen, aber nicht "getValue"? Warum sollten sie leere Zeichenfolgen drucken, wenn Sie sie drucken, anstatt sie manuell in (Zeichenfolge) zu konvertieren? WARUM??
user151496
1
@ user151496 Technisch gesehen gibt Ihnen die Zeichenfolge nicht den "Wert", sondern den "Textinhalt". Aber ja, eine speziell benannte Methode wäre besser erkennbar. Wenn Sie daran gewöhnen, aber es ist nicht wirklich jeder zu härteren Einsatz .
IMSoP
90

Sie können auch die magische Methode __toString () verwenden

$xml->code[0]->lat->__toString()
sglessard
quelle
5
Oder sprintfmit dem %sFormat. Oder echound Ausgabepufferung, oder oder oder oder ...
hakre
Wie kann ich das Objekt in PHP in XML konvertieren? @sglessard
Gem
17

Wenn Sie wissen, dass der Wert des XML-Elements eine Gleitkommazahl (Breite, Länge, Entfernung) ist, können Sie verwenden (float)

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

Auch (int)für die Ganzzahl:

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

Wenn Sie den Wert von XML Element nicht kennen, können Sie ihn verwenden

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

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

Es funktioniert, wenn Sie feststellen müssen, ob der Wert eine Zahl ist, da (string)immer eine Zeichenfolge zurückgegeben und is_int($value)zurückgegeben wirdfalse

vladkras
quelle
Jede Möglichkeit, auch nach anderen Booleschen Werten zu suchen als: (Zeichenfolge) $ value == 'true' || (Zeichenfolge) $ value == 'false'?
Talisin
12

Für mich ist es einfacher, Arrays als Objekte zu verwenden.

Also konvertiere ich ein XML-Objekt,

$xml = simplexml_load_file('xml_file.xml');    
$json_string = json_encode($xml);    
$result_array = json_decode($json_string, TRUE);
dazzafact
quelle
3
Die Konvertierung in JSON und dann wieder im selben Kontext ist unglaublich ineffizient, es sei denn, Sie haben es wirklich eilig. Die Arbeit mit Objekten ist nicht schwer, und wenn Sie Arrays wirklich bevorzugen, sollten Sie das Objekt nativ in ein Array konvertieren.
William
Ich verstehe nie, warum die Leute das tun - Sie werfen alle Funktionen von SimpleXML weg, nur damit Sie $xml['foo'][0]['bar'][0]['@attributes']['baz']stattdessen schreiben können $xml->foo->bar['baz'].
IMSoP
2

Dies ist die Funktion, die mir immer geholfen hat, die XML-bezogenen Werte in ein Array zu konvertieren

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

    return $out;
}
pal4life
quelle
Dies wird unter anderem wegwerfen oder damit brechen: alle Attribute, alles in einem Namespace, alle CDATA-Blöcke. Alles nur, damit Sie die Komfortmethoden verlieren können, die SimpleXML Ihnen in erster Linie angeboten hat.
IMSoP
1

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

Es gibt ein Element unter dem aktuellen Zeiger des Arrays zurück, der 0 ist, sodass Sie einen Wert erhalten

Bendeberia
quelle
1

Sie können das '{}' verwenden, um auf Ihr Eigentum zuzugreifen, und dann können Sie tun, was Sie möchten. Speichern Sie es oder zeigen Sie den Inhalt an.

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

Aus Ihrem Beispiel ist sie der 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'];
               ....

            }     

        }
Zakaria Charik
quelle
3
Es ist nicht erforderlich, es zu verwenden, es {}sei denn, es gibt Sonderzeichen wie Bindestriche. $xml->{'key'}ist nur eine hässlichere Art zu schreiben $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
quelle
2
Diese Antwort ist nicht erklärbar und es fehlt daher die entscheidende Erkenntnis, dass echoKräfte $veher zu einer Zeichenfolge als zu einem Objekt werden müssen, genau wie (string)$vdies der Fall wäre.
IMSoP
0

Mit dieser Funktion können Sie ein Array konvertieren

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
quelle
Sie können, aber warum sollten Sie wollen?
IMSoP
Denn wenn Index eine Zahl ist, kann dies ein Problem sein. Wie diese $ Variable-> Code-> 0? SimpleXMLElement-Objekt ([Code] => Array ([0] => SimpleXMLElement-Objekt (...
Nixis
<0>ist kein gültiges XML-Tag, das würde also niemals passieren. Einige gültige XML-Namen sind keine gültigen PHP-Namen <foo-bar>, aber das kann mit ->{'foo-bar'}Syntax behandelt werden. Oder meinen Sie einfach den Zugriff auf das 0th-Element in einer Liste ähnlich benannter Elemente? Das ist nur so $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;
   }
}
reckte sich
quelle
Ich bin nicht sicher, was dieses Code-Snippet zu zeigen versucht, aber es sieht so aus, als wäre es eine sehr verworrene (und falsche) Schreibweise $codeZero = $xml->code[0]und$lat = $xml->code[0]->lat
IMSoP
@IMSoP, stimmen Sie ab, ohne den Code auszuprobieren? Ich hätte es nicht gepostet, wenn es nicht funktioniert hätte. Ihr Vorschlag lässt keine foreach zu, die sauberer ist als eine einfache for-Schleife. Ich erinnere mich nicht mehr an alle Details, aber es hat funktioniert, als andere Lösungen es nicht taten.
Craned
Ich habe meistens abgewählt, weil es keine Erklärung dafür gibt, was es tut. Wenn selbst Sie es beim Zurücklesen nicht verstehen, wie soll es dann für andere nützlich sein? Was die Verwendung eines foreach angeht, können Sie sicher: foreach ( $xml->code as $code ) { $lat = (string)$code->lat; echo $lat; }Aber was Sie hier durchlaufen, sind "alle Kinder des ersten <code>Elements"; Das macht für mich nicht viel Sinn. Zu verdeutlichen, $xml->code->children()ist Abkürzung für $xml->code[0]->children(), nicht "Kinder genannt code".
IMSoP
@IMSoP, Nun, das ist ein fairer Punkt. Ich hätte eine Erklärung geben sollen; es schien mir damals wahrscheinlich so offensichtlich, dass es mir nicht in den Sinn kam. Zu meinen Gunsten ist jedoch zumindest die Tatsache, dass jeder auf dieser Seite den Kontext bereits kennt und keine Erklärung benötigt, da er bereits weiß, was passiert. Dies wird durch die Tatsache bewiesen, dass eine Person meine Antwort bereits positiv bewertet hat, oder ich würde jetzt negativ sein. Ich werde es in Zukunft besser machen, eine Erklärung zu veröffentlichen.
Craned
Außerdem kann ich fast garantieren, dass ich Ihren Vorschlag zuerst ausprobiert hätte, und es hat nicht funktioniert, also musste ich einen anderen finden.
Craned
-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
quelle