PHP Conference Japan 2024

xml_parse

(PHP 4, PHP 5, PHP 7, PHP 8)

xml_parse開始解析 XML 文件

描述

xml_parse(XMLParser $parser, string $data, bool $is_final = false): int

xml_parse() 解析 XML 文件。會多次呼叫已設定事件的處理常式。

參數

parser

要使用的 XML 解析器的參考。

data

要解析的資料區塊。可以藉由多次呼叫 xml_parse() 並傳遞新資料來逐步解析文件,只要在解析最後資料時設定 is_final 參數為 true 即可。

is_final

如果設定且為 true,則 data 是在此解析中傳送的最後資料。

回傳值

成功時回傳 1,失敗時回傳 0。

對於解析失敗的情況,可以使用 xml_get_error_code()xml_error_string()xml_get_current_line_number()xml_get_current_column_number()xml_get_current_byte_index() 取得錯誤資訊。

注意:

某些錯誤 (例如實體錯誤) 會在資料結尾回報,因此只有在設定 is_final 且為 true 時才會回報。

變更記錄

版本 描述
8.0.0 parser 現在需要 XMLParser 實例;先前,需要有效的 xml 資源

範例

範例 #1 分塊解析大型 XML 文件

此範例示範如何以區塊方式讀取和解析大型 XML 文件,因此不必將整個文件保留在記憶體中。為了簡潔起見,省略了錯誤處理。

<?php
$stream
= fopen('large.xml', 'r');
$parser = xml_parser_create();
// 在此設定處理常式
while (($data = fread($stream, 16384))) {
xml_parse($parser, $data); // 解析目前的區塊
}
xml_parse($parser, '', true); // 完成解析
xml_parser_free($parser);
fclose($stream);
新增筆記

使用者貢獻的筆記 2 筆筆記

21
neoyahuu at yahoo dot com
16 年前
除了傳遞 URL 之外,我們可以將 XML 內容傳遞給這個類別 (您可以
想要先使用 CURL、Socks 或 fopen 來擷取它),而不是使用
陣列,我使用分隔符號 '|' 來識別要取得的資料 (為了讓
取得複雜的 XML 資料更簡短)。以下是我的類別,內建 fopen
您可以傳遞 URL,也可以改傳遞內容

附註:感謝這個很棒的協助頁面。

<?php

class xx_xml {

// XML 解析器變數
var $parser;
var
$name;
var
$attr;
var
$data = array();
var
$stack = array();
var
$keys;
var
$path;

// 你可以傳遞 url 或內容。
// 參數請使用 'url' 或 'contents'
var $type;

// 具有預設參數值的函式
function xx_xml($url='http://www.example.com', $type='url') {
$this->type = $type;
$this->url = $url;
$this->parse();
}

// 解析 XML 資料
function parse()
{
$data = '';
$this->parser = xml_parser_create();
xml_set_object($this->parser, $this);
xml_set_element_handler($this->parser, 'startXML', 'endXML');
xml_set_character_data_handler($this->parser, 'charXML');

xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false);

if (
$this->type == 'url') {
// 如果使用 type = 'url',現在我們用 fopen 開啟 XML

if (!($fp = @fopen($this->url, 'rb'))) {
$this->error("無法開啟 {$this->url}");
}

while ((
$data = fread($fp, 8192))) {
if (!
xml_parse($this->parser, $data, feof($fp))) {
$this->error(sprintf('XML 錯誤於第 %d 行,第 %d 列',
xml_get_current_line_number($this->parser),
xml_get_current_column_number($this->parser)));
}
}
} else if (
$this->type == 'contents') {
// 現在我們可以傳遞內容,或許你想使用 CURL、SOCK 或其他方法。
$lines = explode("\n",$this->url);
foreach (
$lines as $val) {
if (
trim($val) == '')
continue;
$data = $val . "\n";
if (!
xml_parse($this->parser, $data)) {
$this->error(sprintf('XML 錯誤於第 %d 行,第 %d 列',
xml_get_current_line_number($this->parser),
xml_get_current_column_number($this->parser)));
}
}
}
}

function
startXML($parser, $name, $attr) {
$this->stack[$name] = array();
$keys = '';
$total = count($this->stack)-1;
$i=0;
foreach (
$this->stack as $key => $val) {
if (
count($this->stack) > 1) {
if (
$total == $i)
$keys .= $key;
else
$keys .= $key . '|'; // 分隔符號
}
else
$keys .= $key;
$i++;
}
if (
array_key_exists($keys, $this->data)) {
$this->data[$keys][] = $attr;
} else
$this->data[$keys] = $attr;
$this->keys = $keys;
}

function
endXML($parser, $name) {
end($this->stack);
if (
key($this->stack) == $name)
array_pop($this->stack);
}

function
charXML($parser, $data) {
if (
trim($data) != '')
$this->data[$this->keys]['data'][] = trim(str_replace("\n", '', $data));
}

function
error($msg) {
echo
"<div align=\"center\">
<font color=\"red\"><b>錯誤:
$msg</b></font>
</div>"
;
exit();
}
}

?>

以下是如何擷取 XML 資料的範例
p/s:範例用於擷取天氣資訊

<?php
include_once "xx_xml.class.php";

// 我使用簡單的 curl(原始碼在類別中)來取得內容

$pageurl = "http://xml.weather.yahoo.com/forecastrss?p=MYXX0008&u=c";
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_URL, $pageurl );
$thecontents = curl_exec ( $ch );
curl_close($ch);

// 我們想要傳遞已準備好的 XML 內容,而不是 URL
// 但如果你想使用 URL,請跳過上面的 curl 函式,並使用這個
// $xx4 = new xx_xml("url here",'url');

$xx4 = new xx_xml($thecontents,'contents');
// 如你所見,我們使用分隔符號 '|' 而不是長陣列
$Code = $xx4->data ['rss|channel|item|yweather:condition']['code'] ;
$Celcius = $xx4->data ['rss|channel|item|yweather:condition']['temp'] ;
$Text = $xx4->data ['rss|channel|item|yweather:condition']['text'] ;
$Cityname = $xx4->data ['rss|channel|yweather:location']['city'] ;

?>

希望這對您有所幫助。
5
lz_speedy at web dot de
15 年前
看過最好用的 xml2array 函式
<?php
function xml2array($url, $get_attributes = 1, $priority = 'tag')
{
$contents = "";
if (!
function_exists('xml_parser_create'))
{
return array ();
}
$parser = xml_parser_create('');
if (!(
$fp = @ fopen($url, 'rb')))
{
return array ();
}
while (!
feof($fp))
{
$contents .= fread($fp, 8192);
}
fclose($fp);
xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8");
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
xml_parse_into_struct($parser, trim($contents), $xml_values);
xml_parser_free($parser);
if (!
$xml_values)
return;
//Hmm...
$xml_array = array ();
$parents = array ();
$opened_tags = array ();
$arr = array ();
$current = & $xml_array;
$repeated_tag_index = array ();
foreach (
$xml_values as $data)
{
unset (
$attributes, $value);
extract($data);
$result = array ();
$attributes_data = array ();
if (isset (
$value))
{
if (
$priority == 'tag')
$result = $value;
else
$result['value'] = $value;
}
if (isset (
$attributes) and $get_attributes)
{
foreach (
$attributes as $attr => $val)
{
if (
$priority == 'tag')
$attributes_data[$attr] = $val;
else
$result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr'
}
}
if (
$type == "open")
{
$parent[$level -1] = & $current;
if (!
is_array($current) or (!in_array($tag, array_keys($current))))
{
$current[$tag] = $result;
if (
$attributes_data)
$current[$tag . '_attr'] = $attributes_data;
$repeated_tag_index[$tag . '_' . $level] = 1;
$current = & $current[$tag];
}
else
{
if (isset (
$current[$tag][0]))
{
$current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
$repeated_tag_index[$tag . '_' . $level]++;
}
else
{
$current[$tag] = array (
$current[$tag],
$result
);
$repeated_tag_index[$tag . '_' . $level] = 2;
if (isset (
$current[$tag . '_attr']))
{
$current[$tag]['0_attr'] = $current[$tag . '_attr'];
unset (
$current[$tag . '_attr']);
}
}
$last_item_index = $repeated_tag_index[$tag . '_' . $level] - 1;
$current = & $current[$tag][$last_item_index];
}
}
elseif (
$type == "complete")
{
if (!isset (
$current[$tag]))
{
$current[$tag] = $result;
$repeated_tag_index[$tag . '_' . $level] = 1;
if (
$priority == 'tag' and $attributes_data)
$current[$tag . '_attr'] = $attributes_data;
}
else
{
if (isset (
$current[$tag][0]) and is_array($current[$tag]))
{
$current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
if (
$priority == 'tag' and $get_attributes and $attributes_data)
{
$current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
}
$repeated_tag_index[$tag . '_' . $level]++;
}
else
{
$current[$tag] = array (
$current[$tag],
$result
);
$repeated_tag_index[$tag . '_' . $level] = 1;
if (
$priority == 'tag' and $get_attributes)
{
if (isset (
$current[$tag . '_attr']))
{
$current[$tag]['0_attr'] = $current[$tag . '_attr'];
unset (
$current[$tag . '_attr']);
}
if (
$attributes_data)
{
$current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
}
}
$repeated_tag_index[$tag . '_' . $level]++; //0 and 1 index is already taken
}
}
}
elseif (
$type == 'close')
{
$current = & $parent[$level -1];
}
}
return (
$xml_array);
}
?>

返回一個格式正確的陣列,其結構如同 XML 文件。

<root>
<child1>
<child1child1/>
</child1>
</root>

建立一個類似這樣的陣列
array[root][child1][child1child1]

lg
To Top