【问题标题】:Get value from SimpleXMLElement Object从 SimpleXMLElement 对象中获取值
【发布时间】:2011-02-21 11:50:40
【问题描述】:

我有这样的事情:

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

它应该从 geonames 下载 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,它返回一个对象。我怎样才能获得价值?

【问题讨论】:

  • 2017 更新:SO 不再在顶部显示最佳答案。 The best answer is here.
  • @rinogo 您可能不小心单击了答案块顶部的排序选项卡之一。您链接到的答案有 345 票,因此如果您将排序设置为“投票”,则显示在顶部。
  • 谢谢,@IMSoP!你是对的 - 我一定在某个时候点击了“活动”(对于旧问题的答案过时有用,顺便说一句) - 很高兴知道我需要将它改回“投票”! :)

标签: php simplexml


【解决方案1】:

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

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

【讨论】:

  • 刚刚注意到如果你对 xml 对象进行 json_encode 然后 json_decode 它你会得到一个嵌套的 stdObject 来处理,当你懒惰和使用简单的结构时非常方便:D
  • 愚蠢的问题,但这不是错误吗?请参阅php.net/simplexml#95762 为什么您不必在某些字段上强制转换类型,而在其他字段上却必须?
  • 这个答案在 2016 年仍然会更加激烈!
  • 我不敢相信这是这么复杂。为什么他们会创建一个名为“getName”而不是“getValue”的类?如果您打印它而不是手动将其转换为(字符串),他们为什么会打印空字符串。为什么??
  • @user151496 从技术上讲,字符串转换不是给你“价值”,而是“文本内容”。但是,是的,一个专门命名的方法会更容易被发现。但是,一旦您习惯了这一点,它实际上并不难使用
【解决方案2】:

你也可以使用魔术方法__toString()

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

【讨论】:

【解决方案3】:

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

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

另外,(int) 表示整数:

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

【讨论】:

    【解决方案4】:

    如果你知道 XML Element 的值,你可以使用

    $value = (string) $xml->code[0]->lat;
    
    if (ctype_digit($value)) {
        // the value is probably an integer because consists only of digits
    }
    

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

    【讨论】:

    • 除以下之外的任何方式来检查布尔值:(string)$value == 'true' || (string)$value == 'false'?
    • 请注意,这并不总是正确的。它仅对具有自然(正)整数的字符串有效。所以,它们必须在一个字符串中。它们不能是浮点数或负数,因为小数分隔符、减号等将被评估为假。所以,ctype_digitpreg_match('/^\d+$/', $var) 如果你想检查它是否是一个数值,包括浮点数和否定,请改用is_numeric()
    【解决方案5】:

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

    所以,我转换了一个 Xml-Object,

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

    【讨论】:

    • 转换为 JSON 然后返回相同的上下文是非常低效的,除非你真的很着急。使用对象并不难,如果你真的更喜欢数组,你应该将对象原生地转换为数组。
    • 我不明白为什么人们会这样做——你抛弃了 SimpleXML 的所有功能,只是为了写 $xml['foo'][0]['bar'][0]['@attributes']['baz'] 而不是 $xml->foo->bar['baz']
    【解决方案6】:

    这是一直帮我把xml相关的值转换成数组的函数

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

    【讨论】:

    • 这将丢弃或中断,其中包括:任何属性、命名空间中的任何内容、任何 CDATA 块。这一切只是为了让您失去 SimpleXML 最初为您提供的便利方法。
    【解决方案7】:

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

    它返回数组当前指针下的元素,为0,所以你会得到值

    【讨论】:

      【解决方案8】:

      您可以使用“{}”来访问您的属性,然后您可以随心所欲地进行操作。 保存或显示内容。

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

      【讨论】:

      • 没有必要使用{},除非其中有连字符等特殊字符。 $xml->{'key'} 只是写 $xml->key 的一种更丑陋的方式。
      【解决方案9】:
      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/>';
      }
      

      【讨论】:

      • 这个答案没有任何解释,因此错过了echo 强制$v 成为字符串而不是对象的关键见解,就像(string)$v 一样。
      【解决方案10】:

      你可以用这个函数转换数组

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

      【讨论】:

      • 可以,但为什么要这样做?
      • 因为如果index是一个数字,可能会出问题。像这样 $variable->code->0 ? SimpleXMLElement 对象 ( [code] => 数组 ( [0] => SimpleXMLElement 对象 (...
      • &lt;0&gt; 不是一个有效的 XML 标签,所以这永远不会发生。一些有效的 XML 名称不是有效的 PHP 名称,例如 &lt;foo-bar&gt;,但可以使用 -&gt;{'foo-bar'} 语法处理。或者您的意思是访问类似命名元素列表中的0th 元素?那只是$parent-&gt;childName[0]
      【解决方案11】:
      $codeZero = null;
      foreach ($xml->code->children() as $child) {
         $codeZero = $child;
      }
      
      $lat = null;
      foreach ($codeZero->children() as $child) {
         if (isset($child->lat)) {
            $lat = $child->lat;
         }
      }
      

      【讨论】:

      • 我不确定这段代码 sn-p 试图显示什么,但看起来这是一种非常复杂(且错误)的写法 $codeZero = $xml-&gt;code[0]$lat = $xml-&gt;code[0]-&gt;lat
      • @IMSoP,您甚至没有尝试代码就投了反对票?如果它不起作用,我就不会发布它。您的建议不允许使用 foreach,这比简单的 for 循环更干净。我不记得所有细节了,但是当其他解决方案不记得时它起作用了。
      • 我投了反对票,主要是因为它没有解释它在做什么。如果你读回来的时候连你都看不懂,那它对别人有什么用呢?至于使用 foreach,当然可以:foreach ( $xml-&gt;code as $code ) { $lat = (string)$code-&gt;lat; echo $lat; } 但是你在这里循环的是“第一个 &lt;code&gt; 元素的所有子元素”;这对我来说没有多大意义。澄清一下,$xml-&gt;code-&gt;children()$xml-&gt;code[0]-&gt;children() 的简写,而不是“称为code 的孩子”。
      • @IMSoP,嗯,这是一个公平的观点。我应该提供一个解释;当时对我来说这似乎很明显,以至于我没有想到。然而,至少对我有利的是,这个页面上的任何人都已经知道上下文并且不需要解释,因为他们已经知道发生了什么。一个人已经对我的答案投了赞成票,否则我现在会反对这一事实证明了这一点。以后我会更好地发布解释。
      • 另外,我几乎可以保证我会先尝试您的建议,但没有奏效,所以我不得不另找一个。
      【解决方案12】:
      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);
      

      【讨论】:

        猜你喜欢
        • 2015-11-28
        • 1970-01-01
        • 1970-01-01
        • 2010-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-04
        • 1970-01-01
        相关资源
        最近更新 更多