PHP 的 simplexml_load_string/simplexml_load_file 很方便, 很簡單的就能把 XML parse 成 PHP Object, 然後就看要怎麼處理資料, 再處理即可~
- simplexml_load_string : 丟 XML 進去即可
- simplexml_load_file : 丟 URL 進去也吃, 拿來 Parse XML/RSS Feed 超方便
做簡單的處理都沒什麼異常, 但是現在遇到要將 Object value 轉換成一般 PHP Array 的 key -> value 型態就遇到問題了. 不曉得是我不會用還是怎麼樣, 查不到正確該怎麼解, 所以寫起來紀錄一下.(希望有正確解法, 還請指導.. Orz)
註: PHP Version: PHP 5.2.3
先來看一段簡單的程式範例(原始程式):
<?php
$data = <<<EOF
<?xml version="1.0" encoding="UTF-8"?>
<response>
<status>0</status>
<result>
<doc>
<str name="title">title value</str>
<str name="description">description value</str>
</doc>
</result>
</response>
EOF;$xml = simplexml_load_string($data);
$results = array();
foreach ($xml->result->doc as $story) {
$xmlarray = array();
try {
foreach ($story as $item) {
$name = $item->attributes()->name;
$value = $item->attributes()->{0};
$xmlarray[$name] = $value; // have "Illegal offset type" error.
}
} catch (Exception $e) {
echo 'Problem handling XML array.';
}
print_r($xmlarray);
}
?>
此程式目的是要 讀取 $data 的 XML, 然後轉換成 $xmlarray, 並指定 $xmlarray 的 KEY 是 Tag attribute name 的值, VALUE 就是 name Tag 包起來的值, 或者直接看希望的執行結果 如下:
Array
(
[title] => title
[description] => description
)
但是執行結果是 $xmlarray 都是空的, 主要是出現下述 Warning:
Warning: Illegal offset type in xml.php on line 24
然後 var_dump($name) 來看看, 是 Object 的結構如下:
object(SimpleXMLElement)#9 (1) {
[0]=>
string(5) "title"
}
很明顯就是要在存取進 object 的 [0] 即可, 但是發現我試著 $name[0], $name->{0}, 就是一直沒辦法單獨把值拿出來(用 $name[0], $name->{0} 用 var_dump() 都是同樣上述狀況), 而且一樣都是出現Illegal offset type
的問題.
再來當然就網路找來找去, 似乎都沒有想說怎麼解(或許是我找的能力太差 Orz), 所以先放棄, 後來腦筋轉到型態轉換
這邊去(想說型態一直轉不過來, 那我就強迫換型態好了).........就開始做做邪惡的事情囉~
於是我就對 $name 做 strval(), 沒想到一試就成功了~ 😛
所以程式改寫如下($data 沒變, 只修改最裡面 foreach, 先用 strval() 轉換型態):
<?php
$data = <<<EOF
<?xml version="1.0" encoding="UTF-8"?>
<response>
<status>0</status>
<result>
<doc>
<str name="title">title value</str>
<str name="description">description value</str>
</doc>
</result>
</response>
EOF;$xml = simplexml_load_string($data);
$results = array();
foreach ($xml->result->doc as $story) {
$xmlarray = array();
try {
foreach ($story as $item) {
$name = $item->attributes()->name;
$value = $item->attributes()->{0};
$name = strval($name); // 這邊用 $name/$name->{0} 都一樣
$value = strval($value); // 這邊用 $value/$value->{0} 都一樣
$xmlarray[$name] = $value;
}
} catch (Exception $e) {
echo 'Problem handling XML array.';
}
print_r($xmlarray);
}
?>
這樣子執行後, $xmlarray 就是我們要的結果囉~ 😛
感謝 lp81sam 提供正解:
<?php
$data = <<<EOF
<?xml version="1.0" encoding="UTF-8"?>
<response>
<status>0</status>
<result>
<doc>
<str name="title">title value</str>
<str name="description">description value</str>
</doc>
</result>
</response>
EOF;$xml = simplexml_load_string($data);
$results = array();
foreach ($xml->result->doc as $story) {
$xmlarray = array();
try {
foreach ($story as $item) {
$$name = $item->getAttribute('name'); // use getAttribute()
$value = $item->getAttribute(0);
}
} catch (Exception $e) {
echo 'Problem handling XML array.';
}
print_r($xmlarray);
}
?>
getAttribute() 內部運行的模式大概如下:
public function getAttribute($name){
foreach($this->attributes() as $key=>$val){
if($key == $name){
return (string)$val;
}// end if
}// end foreach
}// end function getAttribute
所以可以用 getAttribute() 去抓值, 或者跑 foreach 取值都可以 🙂
昨天剛好遇到這樣的困擾
剛好在www.php.net上看到有別種寫法
提供給你參考
http://www.php.net/manual/en/function.simplexml-load-string.php
http://www.php.net/manual/en/function.simplexml-element-attributes.php
Attributes() as $key=>$val)
{
if($key == $name)
return (string)$val;
}
}
}
...
略
...
try {
foreach ($story as $item) {
$name = $item->getAttribute('name');
$value = $item->getAttribute(0);
$xmlarray[$name] = $value;
}
}
.....略......
}
?>
原來如此, 我懂了... 主要是 getAttribute() 吧 🙂
getAttribute() 的內部運作是:
function getAttribute($name){
foreach($this->attributes() as $key=>$val) {
}
}
所以使用 foreach($this->attributes() as $key=>$val) 就可以把每個值拉出來, 然後再自行做處理.
或者就是用 getAttribute() 直接拉值就可以了~~~