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-ресурс (resource).

Примеры

Пример #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 notes

up
21
neoyahuu at yahoo dot com
17 years ago
Instead of passing a URL, we can pass the XML content to this class (either you
 want to use CURL, Socks or fopen to retrieve it first) and instead of using 
 array, I'm using separator '|' to identify which data to get (in order to make 
 it short to retrieve a complex XML data). Here is my class with built-in fopen 
 which you can pass URL or you can pass the content instead :

p/s : thanks to this great help page.

<?php

class xx_xml {

    // XML parser variables
    var $parser;
    var $name;
    var $attr;
    var $data  = array();
    var $stack = array();
    var $keys;
    var $path;
    
    // either you pass url atau contents. 
    // Use 'url' or 'contents' for the parameter
    var $type;

    // function with the default parameter value
    function xx_xml($url='http://www.example.com', $type='url') {
        $this->type = $type;
        $this->url  = $url;
        $this->parse();
    }
    
    // parse XML data
    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') {
            // if use type = 'url' now we open the XML with fopen
            
            if (!($fp = @fopen($this->url, 'rb'))) {
                $this->error("Cannot open {$this->url}");
            }

            while (($data = fread($fp, 8192))) {
                if (!xml_parse($this->parser, $data, feof($fp))) {
                    $this->error(sprintf('XML error at line %d column %d', 
                    xml_get_current_line_number($this->parser), 
                    xml_get_current_column_number($this->parser)));
                }
            }
        } else if ($this->type == 'contents') {
            // Now we can pass the contents, maybe if you want 
            // to use CURL, SOCK or other method.
            $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 error at line %d column %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 . '|'; // The saparator
            }
            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>Error: $msg</b></font>
            </div>";
        exit();
    }
}

?>

And example of retrieving XML data:
p/s: example use to retrieve weather

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

// Im using simple curl (the original is in class) to get the contents

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

// We want to pass only a ready XML content instead of URL
// But if you want to use URL , skip the curl functions above and use this 
// $xx4 = new xx_xml("url here",'url');

$xx4 = new xx_xml($thecontents,'contents'); 
// As you can see, we use saparator '|' instead of long array
$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'] ;

?>

Hope this helps.
up
5
lz_speedy at web dot de
16 years ago
Best seen xml2array function ever<?phpfunction 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);}?>Returns a well formed array like the structure of the xml-document<root> <child1>  <child1child1/> </child1></root>create an array like array[root][child1][child1child1]lg
To Top