从 SimpleXMLElement 对象中获取值
Posted
技术标签:
【中文标题】从 SimpleXMLElement 对象中获取值【英文标题】:Get value from SimpleXMLElement Object 【发布时间】: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
,它返回一个对象。我怎样才能获得价值?
【问题讨论】:
Forcing a SimpleXML Object to a string, regardless of context 的可能重复项 2017 更新:SO 不再在顶部显示最佳答案。 The best answer is here. @rinogo 您可能不小心单击了答案块顶部的排序选项卡之一。您链接到的答案有 345 票,因此如果您将排序设置为“投票”,则显示在顶部。 谢谢,@IMSoP!你是对的 - 我一定在某个时候点击了“活动”(对于旧问题的答案过时有用,顺便说一句) - 很高兴知道我需要将它改回“投票”! :) 【参考方案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()
【讨论】:
或sprintf
与%s
格式。或echo
和输出缓冲,或或或或...
如何在 PHP 中将对象转换为 XML? @sglessard
@Gem 你可能想要某种序列化 - 见***.com/questions/137021/php-object-as-xml-document【参考方案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_digit 和 preg_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 对象 (...<0>
不是一个有效的 XML 标签,所以这永远不会发生。一些有效的 XML 名称不是有效的 PHP 名称,例如 <foo-bar>
,但可以使用 ->'foo-bar'
语法处理。或者您的意思是访问类似命名元素列表中的0
th 元素?那只是$parent->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->code[0]
和 $lat = $xml->code[0]->lat
@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,嗯,这是一个公平的观点。我应该提供一个解释;当时对我来说这似乎很明显,以至于我没有想到。然而,至少对我有利的是,这个页面上的任何人都已经知道上下文并且不需要解释,因为他们已经知道发生了什么。一个人已经对我的答案投了赞成票,否则我现在会反对这一事实证明了这一点。以后我会更好地发布解释。
另外,我几乎可以保证我会先尝试您的建议,但没有奏效,所以我不得不另找一个。【参考方案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);
【讨论】:
以上是关于从 SimpleXMLElement 对象中获取值的主要内容,如果未能解决你的问题,请参考以下文章