PHP 8.4.0 RC4 available for testing

xml_parse

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

xml_parseCommence l'analyse d'un document XML

Description

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

xml_parse() analyse un document XML. Les gestionnaires pour les événements configurés sont appelés autant de fois que nécessaire.

Liste de paramètres

parser

Une référence sur l'analyseur XML à utiliser.

data

Une partie des données à analyser. Un document peut être analysé morceau par morceau par appels successifs à xml_parse() avec de nouvelles données, aussi longtemps que le paramètre is_final est défini et true lorsque les dernières données sont analysées.

is_final

Si défini et vaut true, data sera le dernier morceau de données envoyées à l'analyseur.

Valeurs de retour

Retourne 1 en cas de succès ou 0 en cas d'échec.

Lors d'un échec d'analyse, la cause de l'erreur peut être obtenue grâce aux fonctions xml_get_error_code(), xml_error_string(), xml_get_current_line_number(), xml_get_current_column_number() et xml_get_current_byte_index().

Note:

Quelques erreurs (dont les erreurs d'entités) sont reportées à la fin des données, ceci uniquement si is_final vaut true.

Historique

Version Description
8.0.0 parser attend une instance de XMLParser désormais; auparavent, une resource xml était attendue.

Exemples

Exemple #1 Analyse de gros documents XML par morceaux

Cet exemple montre comment les gros documents XML peuvent être lus et analysés en morceaux, permettant ainsi de ne pas conserver en mémoire la totalité du document. Aucun gestionnaire d'erreur n'a été positionné pour rendre l'exemple plus concis.

<?php
$stream
= fopen('large.xml', 'r');
$parser = xml_parser_create();
// set up the handlers here
while (($data = fread($stream, 16384))) {
xml_parse($parser, $data); // analyse du morceau courant
}
xml_parse($parser, '', true); // finalisation de l'analyse
xml_parser_free($parser);
fclose($stream);
add a note

User Contributed Notes 2 notes

up
21
neoyahuu at yahoo dot com
16 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
15 years ago
Best seen xml2array function ever
<?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);
}
?>

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