从SimpleXMLElement对象获取价值


197

我有这样的事情:

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

应该从地名下载XML。如果print_r($xml)我知道了:

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
                )

正如您所看到的$xml->code[0]->lat,它返回一个对象。我如何获得价值?



@kubas您可以选择一个答案吗?
kqw

1
2017年更新:因此不再在顶部显示最佳答案。 最好的答案在这里
rinogo

2
@rinogo您可能不小心单击了答案栏顶部的排序选项卡之一。链接到的答案具有345票,因此如果您将排序设置为“投票”,则会在顶部显示。
IMSoP '17

1
谢谢@IMSoP!您是对的-我一定在某个时候单击了“活动”(对带有过时答案的旧问题很有用,顺便说一句)-很高兴知道我需要将其更改回“投票”!:)
rinogo

Answers:


426

您必须将simpleXML对象转换为字符串。

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

9
只是注意到,如果您先对xml对象进行json_encode编码,然后对它进行json_decode,则会得到一个嵌套的stdObject来处理,这在您懒惰和使用简单结构时非常有用:D
Louis

1
愚蠢的问题,但这不是错误吗?参见php.net/simplexml#95762,为什么不必在某些字段上强制转换类型,但必须在其他字段上强制转换类型呢?
gcb 2014年

7
这个答案在2016年仍然更加严峻!
Hirdesh Vishwdewa '16

4
我不敢相信这是如此复杂。他们为什么要创建一个名为“ getName”而不是“ getValue”的类?他们为什么会打印空字符串(如果您将其打印出来,而不是手动将其转换为(字符串))。为什么??
user151496 '16

1
@ user151496从技术上讲,字符串转换不是为您提供“值”,而是给您“文本内容”。但是,是的,一种特别命名的方法会更容易发现。不过,一旦习惯了它,实际上并没有变得更难使用了
IMSoP

90

您还可以使用魔术方法__toString()

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

5
sprintf采用%s格式。或echo和输出缓冲,或或或或...
hakre 2012年

如何在PHP中将对象转换为XML?@sglessard
宝石

17

如果您知道XML元素的值是浮点数(纬度,经度,距离),则可以使用 (float)

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

另外,(int)对于整数:

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

15

如果您知道XML元素的值,则可以使用

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

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

当您需要确定value是否为数字时,它会起作用,因为(string)它将始终返回字符串并is_int($value)返回false


除了(string)$ value =='true'||以外,还可以通过其他方式检查布尔值。(string)$ value =='假'?
塔里辛2014年

12

对我来说,数组比对象更容易使用,

因此,我转换了一个Xml对象,

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

3
除非您真的很着急,否则先转换为JSON,然后再返回到相同的上下文中,效率会非常低。使用对象并不难,如果您真的更喜欢数组,则应该将对象本地转换为数组。
威廉

我从来不明白为什么人们会这样做-您放弃了SimpleXML的所有功能,只是为了$xml['foo'][0]['bar'][0]['@attributes']['baz']代替而编写$xml->foo->bar['baz']
IMSoP

2

这是一直帮助我将xml相关值转换为数组的函数

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

    return $out;
}

这将扔掉或破坏其他东西:任何属性,名称空间中的任何内容,任何CDATA块。这样一来,您就完全可以失去SimpleXML首先为您提供的便捷方法。
IMSoP

1

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

它返回数组当前指针下的元素,该指针为0,因此您将获得值


1

您可以使用“ {}”来访问您的媒体资源,然后可以根据需要进行操作。保存或显示内容。

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

根据您的示例,她就是代码

        $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
{}除非其中有连字符之类的特殊字符,否则无需使用。$xml->{'key'}只是一种丑陋的写作方式$xml->key
IMSoP '17

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
这个答案没有任何解释,因此错过了关键的见解,即echo迫使人们像$v对待字符串一样而不是对象(string)$v
IMSoP

0

您可以使用此函数转换数组

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

您可以,但是为什么要这么做?
IMSoP

因为如果index是数字,则可能是一个问题。像这样$ variable-> code-> 0吗?SimpleXMLElement对象([code] =>数组([0] => SimpleXMLElement对象(...
nixis

<0>不是有效的XML标记,因此永远不会发生。一些有效的XML名称不是有效的PHP名称,例如<foo-bar>,但是可以使用->{'foo-bar'}语法进行处理。还是只意味着访问0相似命名元素列表中的th元素?就是这样$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;
   }
}

我不确定该代码段试图显示什么,但是看起来这是一种非常复杂(错误的)的编写方式,$codeZero = $xml->code[0]而且$lat = $xml->code[0]->lat
-IMSoP

@IMSoP,您在不尝试使用代码的情况下就投了反对票?如果它不起作用,我不会发布它。您的建议不允许使用foreach,这比简单的for循环还干净。我已经不记得所有的细节了,但是当其他解决方案不起作用时,它就起作用了。
伸长了脖子

我之所以投票否决,主要是因为它没有任何解释。如果连读起来都不懂,那对其他人又有什么用呢?至于使用foreach,请确保您可以:foreach ( $xml->code as $code ) { $lat = (string)$code->lat; echo $lat; }但是您在这里循环的是“第一个<code>元素的所有子元素”;这对我来说没有多大意义。要澄清的$xml->code->children()是的简称$xml->code[0]->children(),而不是“被称为子代code”。
IMSoP

@IMSoP,嗯,这很公平。我应该提供一个解释;在我看来,这似乎很明显,以至于我没有想到。但是,至少对我有利的是,此页面上的任何人都已经知道上下文,并且不需要解释,因为他们已经知道发生了什么。一个人已经投票赞成我的答案,或者我现在会否定这一事实,证明了这一点。以后我会更好地发表解释。
伸长了脖子

另外,我几乎可以保证我会首先尝试您的建议,但是该建议没有效果,因此我不得不另找一个。
伸长了脖子

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.