PHP Conference Japan 2024

simplexml_load_file

(PHP 5, PHP 7, PHP 8)

simplexml_load_file將 XML 檔案解析為物件

描述

simplexml_load_file(
    string $filename,
    ?string $class_name = SimpleXMLElement::class,
    int $options = 0,
    string $namespace_or_prefix = "",
    bool $is_prefix = false
): SimpleXMLElement|false

將指定檔案中格式正確的 XML 文件轉換為物件。

參數

filename

XML 檔案的路徑

class_name

您可以使用這個可選參數,讓 simplexml_load_file() 傳回指定類別的物件。該類別應延伸 SimpleXMLElement 類別。

options

位元 ORlibxml 選項常數

namespace_or_prefix

命名空間前綴或 URI。

is_prefix

如果 namespace_or_prefix 是前綴,則為 true;如果是 URI,則為 false;預設為 false

傳回值

傳回 object 類別 SimpleXMLElement 的物件,其中屬性包含 XML 文件中的資料,失敗時則傳回 false

警告

此函式可能傳回布林值 false,但也可能傳回非布林值且計算結果為 false。請閱讀關於 布林值 的章節以取得更多資訊。使用 === 運算子測試此函式的傳回值。

錯誤/例外

對於在 XML 資料中找到的每個錯誤,都會產生一個 E_WARNING 錯誤訊息。

提示

使用 libxml_use_internal_errors() 來抑制所有 XML 錯誤,並使用 libxml_get_errors() 來在之後逐一查看這些錯誤。

範例

範例 1:解析 XML 文件

<?php
// 檔案 test.xml 包含一個具有根元素的 XML 文件
// 且至少有一個元素 /[root]/title。

if (file_exists('test.xml')) {
$xml = simplexml_load_file('test.xml');

print_r($xml);
} else {
exit(
'Failed to open test.xml.');
}
?>

此腳本將在成功時顯示

SimpleXMLElement Object
(
  [title] => Example Title
  ...
)

此時,您可以開始使用 $xml->title 和任何其他元素。

參見

新增註解

使用者貢獻的註解 30 個註解

61
ricardo at ricardomartins dot info
12 年前
有時我們的 xml 具有連字號節點,例如

<my_xml>
<some-node>value</some-node>
</my_xml>

您需要使用
<?php
$simpleXmlObj
->{'some-node'}
?>

而不是
<?php
$simpleXmlObj
->some-node;
?>
33
wouter at code-b dot nl
17 年前
若要正確地從 CDATA 擷取值,請務必使用轉型運算子將 SimpleXML Element 轉換為字串值

<?php
$xml
= '<?xml version="1.0" encoding="UTF-8" ?>
<rss>
<channel>
<item>
<title><![CDATA[Tom & Jerry]]></title>
</item>
</channel>
</rss>'
;

$xml = simplexml_load_string($xml);

// echo 會為您執行轉型
echo $xml->channel->item->title;

// 但 vardump (或 print_r) 不會!
var_dump($xml->channel->item->title);

// 因此將 SimpleXML Element 轉換為 'string' 可解決此問題
var_dump((string) $xml->channel->item->title);
?>

以上將會輸出

Tom & Jerry

object(SimpleXMLElement)#4 (0) {}

string(11) "Tom & Jerry"
11
sirgrayjn at gmail dot com
8 年前
// 如果您遷移或使用本機,請小心
// 進行測試/開發。

// Windows 目錄分隔符號:"\" 和 "/"
// 您可以混用分隔符號 "C:\somedir\www/img/bg.jpg"。

// 混合分隔符號路徑在其他函式中運作良好
// 但 simplexml_load_file() 無法處理混合分隔符號。

// 範例
include("C:\dir\my.php"); // 運作 (windows)
include("C:\dir/my.php"); // 運作 (windows) 混合使用
include("C:/dir/my.php"); // 可行 (Windows, Linux)
simplexml_load_file("C:\dir\my.php"); // 可行
simplexml_load_file("C:\dir/my.php"); // 使用混合路徑會失敗
simplexml_load_file("C:/dir/my.php"); // 可行
7
neil art neilanddeb dort com
15 年前
因為我的 XML 檔案編碼是 UTF-8,而
我的網頁編碼是 iso-8859-1,所以我得到了一些奇怪的字元,例如 ’ 而不是正確的單引號。

這個問題的解決方案很難找到,但實作起來卻非常容易。

http://uk3.php.net/manual/en/function.iconv.php

使用 iconv() 函數,您可以將編碼從一種轉換為另一種,TRANSLIT 選項似乎最適合我的需求。這是我的範例

<?php
// 將字串從 utf-8 轉換為 iso8859-1
$horoscope = iconv( "UTF-8", "ISO-8859-1//TRANSLIT", $horoscope );
?>

我在這個頁面上找到了解決方案...
http://tinyurl.com/lm39xc
希望這有幫助
1
visualmind at nospam dot php dot net
2 年前
有時可能會忽略這一點,但如果您的 XML 節點格式如下
<prefix:element />

您需要確保將 [namespace 或 prefix] 參數和 [isPrefix] 參數設定為 true。此外,在重新呼叫元素時,如果已設定前綴,則需要避免新增前綴,因此在上面的範例中,「prefix:element」應新增為「element」,但在儲存時將自動新增前綴。

如果在載入或物件建構期間未設定前綴,則載入將無法正確取得節點,並且您也無法直接重新呼叫元素,因此 $xml->{'prefix:element'} 也將無法運作。
3
mario
16 年前
如果您希望物件中包含 CDATA,您應該使用 LIBXML_NOCDATA

<?php
$xml
= simplexml_load_file($file_xml, 'SimpleXMLElement',LIBXML_NOCDATA);

print_r($xml);
?>
2
raduispas at gmail dot com
14 年前
如果您想檢查此函數何時失敗,請務必使用 === 而不是 == 來比較傳回值

<?php
$url
= 'http://www.example.com';
$xml = simpleXML_load_file($url,"SimpleXMLElement",LIBXML_NOCDATA);
if(
$xml === FALSE)
{
//處理錯誤
}
else {
//執行其他操作 }
?>

否則,即使文件沒問題,您也可能會一直得到 FALSE。希望這對某人有幫助 ;)
1
siraic at gmail dot com
1 年前
LibXML 通常會使用檔案大小的十倍記憶體來讀取檔案,而此記憶體使用量大部分超出 PHP 保護的記憶體限制。
0
tg at debian dot org
2 年前
儘管其文件說明,此函數並非接受所有路徑名稱。

$ php -r 'print_r( simplexml_load_file("%25.xml"));'
PHP 警告:simplexml_load_file():I/O 警告:無法載入外部實體 "%25.xml",在命令列程式碼第 1 行
0
Rich
9 年前
我偶然發現了這一點:包含簡單字串的單一元素會變成字串,但包含*空格*的單一元素會變成陣列,其中包含一個元素,即字串空格。

我確信對於 XML 神秘學家來說,這是明智而美妙的,但它真的讓我感到困惑,而且我認為它可能會讓其他人感到困惑。

<?php
$parsed
= simplexml_load_string('<container><space> </space><blank></blank><string>hello</string></container>');
$content = json_decode(json_encode($parsed),TRUE);
var_dump($content);
/* 輸出為:
array(3) {
'space' => array(1) { ← 沒有預期到這個!
[0] => 字串(1) " "
}
'blank' => array(0) { }
'string' => 字串(5) "hello"
}
*/
0
l [DOT] anzinger [AT] gmail [DOT] com
16 年前
如果您不希望 CDATA 值被逸出,只需使用 LIBXML_NOCDATA 作為第三個參數來載入 XML 即可。

注意:此功能需要 PHP 版本 >= 5.1.0 才能運作。

範例

<?php simplexml_load_file('xmldatei.xml', null, LIBXML_NOCDATA); ?>
0
info at evasion dot cc
18 年前
假設您已將 XML 檔案載入 $simpleXML_obj。
結構如下

SimpleXMLElement 物件
(

[node1] => SimpleXMLElement 物件
(
[subnode1] => value1
[subnode2] => value2
[subnode3] => value3
)

[node2] => SimpleXMLElement 物件
(
[subnode4] => value4
[subnode5] => value5
[subnode6] => value6
)

)

當在物件中搜尋特定節點時,您可以使用此函數

<?php

function &getXMLnode($object, $param) {
foreach(
$object as $key => $value) {
if(isset(
$object->$key->$param)) {
return
$object->$key->$param;
}
if(
is_object($object->$key)&&!empty($object->$key)) {
$new_obj = $object->$key;
$ret = getCfgParam($new_obj, $param);
}
}
if(
$ret) return (string) $ret;
return
false;
}
?>

因此,如果您想要取得 subnode4 的值,您可以使用如下的函數

<?php
$result
= getXMLnode($simpleXML_obj, 'subnode4');
echo
$result;
?>

它會顯示 "value4"
-1
fdouteaud at gmail dot com
18 年前
如果您使用來自 simplexml 的資料直接饋送到您的 MySQL 資料庫 (使用 MYSQLi 和綁定參數),請小心。

來自 simplexml 的資料是物件,而 MySQLi 的綁定參數函數不喜歡這樣!(它會導致一些記憶體洩漏,並可能導致 Apache/PHP 崩潰)

為了正確執行此操作,您必須在將值傳遞給 MySQLi 的綁定方法之前,將它們轉換為正確的類型 (字串、整數...)。
我在文件中沒有找到這個資訊,這讓我頭痛不已。
-1
tuxedobob
9 年前
有時您可能會嘗試載入檔案,並且它會抱怨實體並拋出剖析器錯誤。

如果是這種情況,請檢查以確保有問題的檔案不包含沒有對應實體參考的 & 符號 (&)。

如果確實如此,或者如果您想要謹慎起見,那麼不要使用 simplexml_load_file,請嘗試此操作

$file = file_get_contents('stuff.xml');
$temp = preg_replace('/&(?!(quot|amp|pos|lt|gt);)/', '&amp;', $file);
$xml = simplexml_load_string($temp) or die("xml 載入失敗");

將檔案讀取到字串中,在任何不屬於字元實體的 '&' 後面新增 'amp;',然後將字串剖析為 xml。
-2
kannan at 99deals dot in
12 年前
如果您的某些節點包含特殊字元,則無法正確載入

例如,請參閱下面的節點
<node:number>1538-7445</node:number>
<node:coverDisplayDate>Sep 1 2012 12:00:00:000AM</node:coverDisplayDate>

您必須將 : 變更為其他特殊字元,例如 '-',才能正確轉換

正確的節點
<node-number>1538-7445</node-number>
<node-coverDisplayDate>Sep 1 2012 12:00:00:000AM</node-coverDisplayDate>

我在偵錯時浪費了寶貴的時間。請注意這一點。?
-2
fusionstream at gmail dot com
12 年前
如果您載入許多檔案,這可能會減慢頁面載入時間。

若要設定逾時,請使用 file_get_context,然後使用 simplexml_load_string

<?php

$fp
= fopen('http://www.example.com/rss', false, stream_create_context(array('http' => array('timeout', '1.5'))));

if (
$fp) {
print_r( simplexml_load_string($fp) );
} else {
echo
"The request timed out";
}
?>
-1
php at werner dash ott dot de
17 年前
使 SimpleXMLElement 物件可儲存於 Session 中。

除了無法在 session 中存活之外,當嘗試重新進入 session 時,SimpleXMLElement 物件甚至可能會讓 session_start() 函式崩潰!

為了提出這個問題的解決方案,我使用了如下模式。核心概念是在 session 呼叫之間,將 SimpleXMLElement 轉換為字串表示形式,反之亦然,這樣當然可以儲存於 session 中。

<?php
//
// SimpleXMLElement 物件的 session 儲存處理
// (適用於/使用 PHP 5.1.5 和 PHP 5.2.1 測試)
// myClass 模式允許方便地存取
// XML 結構,同時可儲存於 session 中
//
class myClass
{
private
$o_XMLconfig = null;
private
$s_XMLconfig = '';

public function
__construct($args_configfile)
{
$this->o_XMLconfig = simplexml_load_file($args_configfile);
$this->s_XMLconfig = $this->o_XMLconfig->asXML();
}
// __construct()

public function __destruct()
{
$this->s_XMLconfig = $this->o_XMLconfig->asXML();
unset(
$this->o_XMLconfig); // 這個物件否則會讓
// 後續的 session_start() 呼叫崩潰!
} // __destruct()

public function __wakeup()
{
$this->o_XMLconfig = simplexml_load_string($this->s_XMLconfig);
}
// __wakeup()

} // class myClass
?>
-2
jamie at splooshmedia dot co dot uk
14 年前
簡單包裝 simplexml_load_file 以規避當 XML 伺服器逾時或返回 500 錯誤等情況時產生的惱人錯誤訊息。

<?php
function loadXML2($domain, $path, $timeout = 30) {

/*
用法:

$xml = loadXML2("127.0.0.1", "/path/to/xml/server.php?code=do_something");
if($xml) {
// 已載入 xml 文件
} else {
// 失敗。顯示友好的錯誤訊息。
}
*/

$fp = fsockopen($domain, 80, $errno, $errstr, $timeout);
if(
$fp) {
// 發出請求
$out = "GET $path HTTP/1.1\r\n";
$out .= "Host: $domain\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);

// 取得回應
$resp = "";
while (!
feof($fp)) {
$resp .= fgets($fp, 128);
}
fclose($fp);
// 檢查狀態是否為 200
$status_regex = "/HTTP\/1\.\d\s(\d+)/";
if(
preg_match($status_regex, $resp, $matches) && $matches[1] == 200) {
// 將 xml 載入為物件
$parts = explode("\r\n\r\n", $resp);
return
simplexml_load_string($parts[1]);
}
}
return
false;

}
?>
-3
sean at aliencreations dot com
13 年前
如果您發現使用 simplexml_load_file() 時收到 500 錯誤,但您可以透過瀏覽器手動存取 xml/rss 訂閱源,則您的腳本可能被使用者代理偵測器封鎖。

在您的 xml 呼叫之前新增此程式碼以解決此問題

<?php

ini_set
("user_agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");
ini_set("max_execution_time", 0);
ini_set("memory_limit", "10000M");

$rss = simplexml_load_file($feed_url);

?>
-1
genialbrainmachine at NOSPAM dot tiscali dot it
19 年前
Micro$oft Word 使用非標準字元,這會在 simplexml_load_file 的使用上產生問題。
許多系統在其 ISO-8859-1 實作中包含非標準的 Word 字元。因此,包含該字元的 XML 文件對於許多瀏覽器來說可能看起來是格式良好的 (亦即)。但是,如果您嘗試使用 simplexml_load_file 載入這類文件,您會遇到一些麻煩..
我認為這與 htmlentites 中討論的問題完全相同。以下 htmlentitles 的注意事項在此也很有趣 (依相反順序給出,以確保歷史)
http://it.php.net/manual/en/function.htmlentities.php#26379
http://it.php.net/manual/en/function.htmlentities.php#41152
http://it.php.net/manual/en/function.htmlentities.php#42126
http://it.php.net/manual/en/function.htmlentities.php#42511
-3
Nanuit at ossi dot at
13 年前
一個在 Proxy 後面使用 simplexml_load_file 時非常有用的函式

<?php
function getXMLfromURL($url) {
$Proxy = getenv("HTTP_PROXY");

if (
strlen($Proxy) > 1) {
$r_default_context = stream_context_get_default ( array
(
'http' => array(
'proxy' => $Proxy,
'request_fulluri' => True,
),
)
);
libxml_set_streams_context($r_default_context);
}
$daten = simplexml_load_file($url);
return (
$daten);
}
?>

其中 HTTP_PROXY 設定為例如:tcp://proxy:8080
-2
Kyle
17 年前
關於 2006 年 4 月 7 日的匿名使用者

有一種方法可以取回 HTML 標籤。例如

<?xml version="1.0"?>
<intro>
Welcome to <b>Example.com</b>!
</intro>

<?php
// 我使用 @,這樣如果載入失敗,它就不會在錯誤訊息中輸出 XML 的內容。該內容可能是密碼,所以這樣做只是為了安全。
$xml = @simplexml_load_file('content_intro.xml');
if (
$xml) {
// asXML() 將保留 HTML 標籤,但它也會保留父標籤 <intro>,所以我使用 str_replace 將它們剝離。如果您有很多標籤,您顯然也可以使用 preg_replace。
$intro = str_replace(array('<intro>', '</intro>'), '', $xml->asXML());
} else {
$error = "無法載入 intro XML 檔案。";
}
?>

使用這種方法,某人可以更改 content_intro.xml 中的 intro,並確保 HTML 格式良好,不會破壞整個網站設計。
-3
cryonyx at cerebrate dot ru
16 年前
如果您有一個 XML 檔案,其中在同一層級上有一系列相同名稱的元素,simplexml 會錯誤地處理它們,並且不允許使用 foreach() 遍歷陣列。就我而言,這是由 PHP xml_parser 引起的 (請參閱:http://ru2.php.net/manual/ru/function.xml-parser-create.php#53188)。

為了避免這種情況,只需使用 count() 並使用 for() 遍歷陣列。

範例

<params>
<param>
<name>version.shell</name>
<value>1.0</value>
</param>
<param>
<name>version.core</name>
<value>1.0</value>
</param>
<param>
<name>file.lang</name>
<value>vc.lang</value>
</param>
...
</params>

<?php
$filename
= '...';
$xml = simplexml_load_file($filename);
$p_cnt = count($xml->param);
for(
$i = 0; $i < $p_cnt; $i++) {
$param = $xml->param[$i];
...;
}
?>
-4
skutter at imprecision dot net
18 年前
看來 SimpleXML 不支援 CDATA... 我拼湊出這個小小的正規表示式函式,在嘗試使用 simplexml_load_file / simplexml_load_string 等函式來解析 XML 之前,先處理 CDATA。希望這對某些人有所幫助,並且非常想聽聽更好的解決方案。(當然,除了*不*使用 SimpleXML 之外!;)

它會尋找任何 <![CDATA [此處的文字和 HTML 等]]> 元素,對封裝的資料執行 htmlspecialchar() 處理,然後去除 "<![CDATA [" 和 "]]>" 標籤。

<?php
function simplexml_unCDATAise($xml) {
$new_xml = NULL;
preg_match_all("/\<\!\[CDATA \[(.*)\]\]\>/U", $xml, $args);

if (
is_array($args)) {
if (isset(
$args[0]) && isset($args[1])) {
$new_xml = $xml;
for (
$i=0; $i<count($args[0]); $i++) {
$old_text = $args[0][$i];
$new_text = htmlspecialchars($args[1][$i]);
$new_xml = str_replace($old_text, $new_text, $new_xml);
}
}
}

return
$new_xml;
}

//用法:
$xml = '您的 XML 包含 CDATA...';
$xml = simplexml_unCDATAise($xml);
$xml_object = simplexml_load_string($xml);
?>
-3
Smokey
14 年前
對於巢狀和同名的值,我製作了這個小程式碼片段,用於從 Google 的地理編碼中取得和顯示多個值,當找不到精確的匹配時,它會以下列格式傳回所有接近的匹配項(這是它們輸出的簡化版本)

<Response>
<Placemark id="1">
<address>紐約 24, NY, 美國</address>
<AddressDetails>
..................
</AddressDetails>
<Point>
<coordinates>-73.5850086,40.7207442,0</coordinates>
</Point>
</Placemark>
<Placemark id="2">
<address>紐約 27, NY, 美國</address>
<AddressDetails>
...................
</AddressDetails>
<Point>
<coordinates>-72.8987835,40.8003588,0</coordinates>
</Point>
</Placemark>
<Placemark id="3">
<address>雪松廣場學校, 20 Cedar Pl, 揚克斯, NY 10705, 美國</address>
<AddressDetails>
..................
</AddressDetails>
<Point>
<coordinates>-73.8966320,40.9256520,0</coordinates>
</Point>
</Placemark>
</Response>

<?php
// 取得並分解結果,然後將其儲存在 $var 中
$Address = "99999 parkplace, 紐約, NY";
$urladdress = urlencode($Address);
$Base_url = "http://maps.google.com/maps/geo?q=";
$urlParts = "&output=xml";
$urlrequest = $Base_url . $urladdress . $urlParts;
$xml = simplexml_load_file($urlrequest);
$num = "0";
foreach (
$xml->Response->Placemark as $value){
$num++;
$GeoFindAdd{$num} = $value->address;
$GeoFindCords{$num} = $value->Point->coordinates;
}

// 簡單顯示結果
echo "找到 ",$num," 個可能的地理資料集 <br>";
$CountNumResults = "0";
for ( ;
$num > 0; $num--){
$CountNumResults++;
echo
$countnum,"<br> 地址 = ",$GeoFindAdd{$num},"<br> 座標 = ",$GeoFindCords{$num},"<br>";
}
echo
"結束";
?>
-3
Anonymous
18 年前
使用此腳本時發現,simplexml_load_file() 會移除 XML 檔案內部的任何 HTML 格式,而且也只會載入有限的層數。如果您的 XML 檔案太深,它將傳回布林值 false。
-3
info at evasion dot cc
18 年前
抱歉,之前的函式中有錯誤
<?php
function &getXMLnode($object, $param) {
foreach(
$object as $key => $value) {
if(isset(
$object->$key->$param)) {
return
$object->$key->$param;
}
if(
is_object($object->$key)&&!empty($object->$key)) {
$new_obj = $object->$key;
// 必須在那裡使用 getXMLnode 函式(遞迴)
$ret = getXMLnode($new_obj, $param);

}
}
if(
$ret) return (string) $ret;
return
false;
}
?>
-3
rex111 at bigmir dot net
8 年前
取得所有標籤及其值。(遞迴)

<?php
$xml
= simplexml_load_file('settings.xml');

function
all_tag($xml){
$i=0; $name = "";
foreach (
$xml as $k){
$tag = $k->getName();
$tag_value = $xml->$tag;
if (
$name == $tag){ $i++; }
$name = $tag;
echo
$tag .' '.$tag_value[$i].'<br />';
// 遞迴
all_tag($xml->$tag->children());
}
}

all_tag($xml);
?>
-5
mark
19 年前
如果物件的屬性為空,則不會建立陣列。以下是正確傳輸的 object2array 版本。

<?php
function object2array($object)
{
$return = NULL;

if(
is_array($object))
{
foreach(
$object as $key => $value)
$return[$key] = object2array($value);
}
else
{
$var = get_object_vars($object);

if(
$var)
{
foreach(
$var as $key => $value)
$return[$key] = ($key && !$value) ? NULL : object2array($value);
}
else return
$object;
}

return
$return;
}
?>
-4
knl at bitflop dot com
15 年前
如果你需要將 SimpleXML 的資料解析到 session 變數中,記得先將資料定義為字串。

如果你不這麼做,你會收到 "節點已不存在" 的警告,指向你的 session_start() 函式。

這樣做會成功

<?php

$new_version
= simplexml_load_file('http://example.com/version.xml');
$_SESSION['current_version'] = (string)$new_version->version;

?>
To Top