xml_parse
(PHP 4, PHP 5, PHP 7)
xml_parse — Запускает разбор XML документа
Описание
$parser
, string $data
[, bool $is_final
= false
] )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
.
- PHP Руководство
- Функции по категориям
- Индекс функций
- Справочник функций
- Обработка XML
- XML-анализатор
- utf8_decode
- utf8_encode
- xml_error_string
- xml_get_current_byte_index
- xml_get_current_column_number
- xml_get_current_line_number
- xml_get_error_code
- xml_parse_into_struct
- xml_parse
- xml_parser_create_ns
- xml_parser_create
- xml_parser_free
- xml_parser_get_option
- xml_parser_set_option
- xml_set_character_data_handler
- xml_set_default_handler
- xml_set_element_handler
- xml_set_end_namespace_decl_handler
- xml_set_external_entity_ref_handler
- xml_set_notation_decl_handler
- xml_set_object
- xml_set_processing_instruction_handler
- xml_set_start_namespace_decl_handler
- xml_set_unparsed_entity_decl_handler
Коментарии
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.
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