Nhận giá trị từ Đối tượng SimpleXMLEuity


197

Tôi có một cái gì đó như thế này:

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

Nó được cho là tải xuống XML từ tên địa lý. Nếu tôi làm print_r($xml)tôi nhận được:

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
                )

Tôi làm như bạn có thể thấy $xml->code[0]->latvà nó trả về một đối tượng. Làm thế nào tôi có thể nhận được giá trị?



@kubas bạn có thể chọn một câu trả lời?
kqw

1
Cập nhật 2017: SO không còn hiển thị câu trả lời tốt nhất ở đầu trang. Câu trả lời tốt nhất là ở đây .
rinogo

2
@rinogo Có lẽ bạn đã vô tình nhấp vào một trong các tab sắp xếp ở đầu khối câu trả lời. Câu trả lời bạn liên kết đến có 345 phiếu bầu, vì vậy hãy hiển thị ở đầu nếu bạn đã sắp xếp thành "phiếu".
IMSoP

1
Cảm ơn, @IMSoP! Bạn đã đúng - Tôi đã nhấp vào "hoạt động" tại một số điểm (hữu ích cho các câu hỏi cũ với câu trả lời đã lỗi thời, btw) - thật tốt khi biết tôi cần thay đổi lại thành "phiếu bầu"! :)
rinogo

Câu trả lời:


426

Bạn phải truyền đối tượng SimpleXML thành một chuỗi.

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

9
Chỉ cần chú ý nếu bạn json_encode đối tượng xml và sau đó json_decode, bạn sẽ nhận được một stdObject lồng nhau để xử lý, khá tiện lợi khi bạn lười biếng và làm việc với các cấu trúc đơn giản: D
Louis

1
Câu hỏi ngớ ngẩn, nhưng đó không phải là một lỗi? xem php.net/simplexml#95762 tại sao bạn không phải nhập kiểu trên một số lĩnh vực nhưng trên các lĩnh vực khác bạn phải làm?
gcb

7
Câu trả lời này vẫn còn rất khó khăn trong năm 2016!
Hirdesh Vishwdewa

4
Tôi không thể tin rằng điều này quá phức tạp. tại sao họ lại tạo một lớp gọi là "getName" mà không phải là "getValue"? tại sao họ sẽ in chuỗi rỗng nếu bạn in nó thay vì chuyển đổi thủ công thành (chuỗi). TẠI SAO??
dùng151496

1
@ user151496 Về mặt kỹ thuật, chuỗi ký tự không cung cấp cho bạn "giá trị", mà là "nội dung văn bản". Nhưng vâng, một phương pháp được đặt tên cụ thể sẽ dễ khám phá hơn. Tuy nhiên, khi bạn đã quen với điều này, nó thực sự không khó sử dụng hơn .
IMSoP

91

Bạn cũng có thể sử dụng phương thức ma thuật __toString ()

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

5
Hoặc sprintfvới %sđịnh dạng. Hoặc echovà đầu ra bộ đệm, hoặc hoặc hoặc ...
hakre

Làm thế nào tôi có thể chuyển đổi đối tượng thành XML trong PHP? @sglessard
Đá quý

17

Nếu bạn biết rằng giá trị của phần tử XML là số float (vĩ độ, kinh độ, khoảng cách), bạn có thể sử dụng (float)

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

Ngoài ra, (int)đối với số nguyên:

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

15

nếu bạn không biết giá trị của Phần tử XML, bạn có thể sử dụng

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

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

Nó hoạt động khi bạn cần xác định xem giá trị có phải là số không, vì (string)sẽ luôn trả về chuỗi và is_int($value)trả vềfalse


Bất kỳ cách nào để kiểm tra boolean ngoài: (chuỗi) $ value == 'true' || (chuỗi) $ value == 'false'?
Talisin

12

Đối với tôi nó dễ sử dụng mảng hơn các đối tượng,

Vì vậy, tôi chuyển đổi một Xml-Object,

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

3
Chuyển đổi sang JSON và sau đó quay lại trong cùng một bối cảnh là vô cùng kém hiệu quả trừ khi bạn thực sự vội vàng. Làm việc với các đối tượng không khó và nếu bạn thực sự thích các mảng, bạn phải chuyển đổi đối tượng thành một mảng nguyên bản.
William

Tôi không bao giờ hiểu tại sao mọi người làm điều này - bạn vứt bỏ tất cả các tính năng của SimpleXML, chỉ để bạn có thể viết $xml['foo'][0]['bar'][0]['@attributes']['baz']thay vì $xml->foo->bar['baz'].
IMSoP

2

Đây là hàm luôn giúp tôi chuyển đổi các giá trị liên quan đến xml thành mảng

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

    return $out;
}

Điều này sẽ vứt bỏ hoặc phá vỡ, trong số những thứ khác: bất kỳ thuộc tính, bất cứ thứ gì trong một không gian tên, bất kỳ khối CDATA nào. Tất cả chỉ để bạn có thể mất các phương thức tiện lợi mà SimpleXML cung cấp cho bạn ngay từ đầu.
IMSoP

1

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

nó trả về phần tử dưới con trỏ hiện tại của mảng là 0, vì vậy bạn sẽ nhận được giá trị


1

bạn có thể sử dụng '{}' để truy cập vào tài sản của mình và sau đó bạn có thể làm như bạn muốn. Lưu nó hoặc hiển thị nội dung.

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

Từ ví dụ của bạn, cô ấy là mã

        $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
Không cần sử dụng {}trừ khi có các ký tự đặc biệt như dấu gạch nối trong đó. $xml->{'key'}chỉ là một cách viết xấu hơn $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
Câu trả lời này không có bất kỳ lời giải thích nào, và do đó bỏ lỡ cái nhìn sâu sắc quan trọng đó là echobuộc $vphải trở thành một chuỗi chứ không phải là một đối tượng, giống như (string)$vsẽ làm.
IMSoP

0

bạn có thể chuyển đổi mảng với chức năng này

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

Bạn có thể, nhưng tại sao bạn muốn?
IMSoP

Bởi vì nếu chỉ số là một con số, nó có thể là một vấn đề. Giống như biến $ này-> mã-> 0? Đối tượng SimpleXMLEuity ([code] => Mảng ([0] => Đối tượng SimpleXMLEuity (...
nixis

<0>không phải là thẻ XML hợp lệ, vì vậy điều đó sẽ không bao giờ xảy ra. Một vài tên XML hợp lệ không phải là tên PHP hợp lệ, như thế <foo-bar>, nhưng có thể được xử lý bằng ->{'foo-bar'}cú pháp. Hay bạn chỉ có nghĩa là truy cập 0phần tử thứ trong một danh sách các phần tử được đặt tên tương tự? Đó chỉ là $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;
   }
}

Tôi không chắc đoạn mã này đang cố hiển thị là gì, nhưng có vẻ như đó là một cách viết rất phức tạp (và sai) $codeZero = $xml->code[0]$lat = $xml->code[0]->lat
IMSoP

@IMSoP, bạn đang bỏ phiếu này mà không cần thử mã? Tôi sẽ không đăng nó nếu nó không hoạt động. Đề xuất của bạn không cho phép một foreach, mà sạch hơn một vòng lặp đơn giản. Tôi không nhớ tất cả các chi tiết nữa, nhưng nó đã hoạt động khi các giải pháp khác không có.
vươn

Tôi đã bỏ phiếu chủ yếu vì nó không có lời giải thích về những gì nó đang làm. Nếu thậm chí bạn không hiểu nó khi bạn đọc lại, thì nó được coi là hữu ích với bất kỳ ai khác? Đối với việc sử dụng một foreach, chắc chắn bạn có thể: foreach ( $xml->code as $code ) { $lat = (string)$code->lat; echo $lat; }Nhưng những gì bạn đang lặp ở đây là "tất cả những đứa trẻ của <code>yếu tố đầu tiên "; Điều đó không có ý nghĩa nhiều với tôi. Để làm rõ, $xml->code->children()là viết tắt cho $xml->code[0]->children(), không phải "trẻ em được gọi code".
IMSoP

@IMSoP, Vâng, đó là một điểm công bằng. Tôi nên đã cung cấp một lời giải thích; điều đó có vẻ quá rõ ràng đối với tôi vào thời điểm nó không xảy ra với tôi. Tuy nhiên, theo tôi, ít nhất, thực tế là bất cứ ai ở trên trang này đều biết bối cảnh và sẽ không cần một lời giải thích vì họ đã biết chuyện gì đang xảy ra. Điều này được chứng minh bằng thực tế là một người đã bỏ phiếu cho câu trả lời của tôi hoặc bây giờ tôi sẽ ở trạng thái tiêu cực. Tôi sẽ làm tốt hơn trong việc đăng một lời giải thích trong tương lai.
vươn

Ngoài ra, tôi gần như có thể đảm bảo rằng tôi đã thử đề xuất của bạn trước và nó không hoạt động nên tôi phải tìm một đề xuất khác.
vươn

-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);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.