|
|||||||||
|
|
|
۩ Дата
|
Offline Пользователь Профиль Журнал Группа: Форумчанин Сообщений: 95 Пользователь №: 155 На форуме: Репутация: нет |
Парсинг XML для тех кто в танке:
[email protected] Добрый день! Данную тему предлагаю тем, кто еще ни разу не встречался с XML парсингом. Сам только что с ним познакомился и хочу поделиться с тамими же как я чайниками тем, что у меня получается. Хочу надеятся, что им это поможет. Пусть профи не ругаются, если я чего не понимаю в XML и парсинге. К каждому утверждению, сделанному мною далее предлагаю делать добавку - мне так кажется. Ну, а если кажется, то перекрестимся и начнем... ;0) Парсинг, фактически, это разбор некоторого файла на состовляющие элементы для того, что бы потом эти элементы использовать в своих корыстных целях. XML это язык разметки, *цензура*ожий на HTML, но более обширный по своим пременениям. XML часто используют для передачи данных от одной системы к другой. Взаимодействие между разнородными системами, как правило, не определено, а потому потребовался обобщенный способ передачи данных. Под системами я, в основном, подразумеваю базы данных. Для парсинга в PHP можно использовать встроенные функции: $xml_parser = xml_parser_create(); xml_parser_set_option($xml_parser, НАЗВАНИЕ_ОПЦИИ, ЗНАЧЕНИЕ); xml_set_element_handler($xml_parser, "FunctName1", "FunctName2"); xml_set_character_data_handler($xml_parser, "FunctName3"); xml_parse($xml_parser, $data, feof($fp)) xml_parser_free($xml_parser); Если надо подробнее найдите эти ф-ии в доках. Предположим, что некоторая система сгенерировала следующий файл с данными: *** one.xml *** Jhon Smith Mega Book 123-456-87 fantastic Will Duglas Ha, Ha and Ha! 436-434-76 poems 13$ Klark Rodriges it't simple book
Если запустите index.php, то ничего не увидете. Пусть мы хотим увидеть названия тегов и данные в них. Измените функции след. образом. function startElement($parser, $name, $attrs) { print "Открыт тег ". $name . " "; } function endElement($parser, $name) { print "Закрыт тег " . $name . " "; } function characterData($parser, $data) { print "".$data. " "; } Запускаем index.php. Видим на странице след. результат: Открыт тег BOOKDB Открыт тег BOOK Открыт тег AUTHOR Jhon Smith Закрыт тег AUTHOR Открыт тег BOOKNAME Mega Book Закрыт тег BOOKNAME Открыт тег CODE 123-456-87 Закрыт тег CODE Открыт тег GANRE fantastic Закрыт тег GANRE Закрыт тег BOOK . // прочие данные из one.xml . Открыт тег PRICE 15$ Закрыт тег PRICE Закрыт тег BOOK Закрыт тег BOOKDB Все остальное достаточно просто, вы можете определить, как поступать с любым из элементов: вывести на страницу, не вывести, выделить его жирным или сделать из него ссылку - все это ваша фантазия. Основа у вас есть, как это все работает можно понять и самому ( я же понял... надеюсь ;0) ). На этом практически все, но еще немного об атрибутах тегов. Атрибуты открывающего тега: Иногда в первом теге определяют атрибуты, ну, например, в HTML так размечена таблица: <table width="400" border="1" cellspacing="0" cellpadding="0" > <tr > <td >1111</td > <td >2222</td > <td >3333</td > </tr > </table > Здесь width="400" border="1" cellspacing="0" cellpadding="0" - это атрибуты тега и их значения. Эти данные так же можно извлеч при парсинге, т.к. ф-ия отвечающая за открывающий тег обозначена след. образом: function startElement($parser, $name, $attrs) Здесь $name - имя самого открывающего тега, а $attrs - это массив атрибутов. О работе с массивами писать не буду ;0) . Если в теге определен хотя бы один атрибут, то этот массив будет не пустой. ****************************** Кстати, не обязвтельно ф-ия startElement() должна иметь такое имя, можно назвать ее и по другому, только зарегистрируйте ее в ф-ии : // Указываем ф-ии обработки начального тега и конечного тега (см. выше) xml_set_element_handler($xml_parser, "ИМЯ_ФУНКЦИИ1", "ИМЯ_ФУНКЦИИ2"); ****************************** Определите ф-ии обработки след. образом: function startElement($parser, $name, $attrs) { print " TEG is "; print "".$name . ""; // Каждый атрибут представим в виде пары // имя атрибута $n и его значение $v и печатаем эти данные foreach ( $attrs as $n => $v) { print " {". $n ."} = " . $v; } print " "; } function endElement($parser, $name) { print " TEG " . $name ." is closed " ; print " "; } function characterData($parser, $data) { print "".$data." "; } Дальше можно сделать следующее. Возмите html файл и прогоните его через этот парсер, посмотриче, что получится. А получится довольно интересно, например: TEG is A {HREF} = index.html Front page TEG A is closed При парсинге можно находит на указанной странице все ссылки и сохранять их адреса. Зачем это может пригодится не знаю, но возможность такая есть ;0) Главное при парсинге HTML, да и любой другой разметки, что бы она соответствовала стандарту. Т.е. теги не тр*цензура*ющие в HTML закрытия: , , и и некоторые другие, были записаны по след. стандарту: , , и . А атрибуты тегов обязательно оформлялись в кавычки, вот так: <table width="400" border="1" cellspacing="0" cellpadding="0" > а не так: <table width=400 border=1 cellspacing=0 cellpadding=0 > Иначе парсер выдаст ошибку и заглохнет. Ну, вроде, все... строго не судите... удачи! |
|
|
Offline Я ВЕЗУЧ Профиль Журнал Группа: Форумчанин * Сообщений: 1122 Пользователь №: 6 На форуме: Репутация: нет |
2killich спасибо за статью :)
2Admin было бы неплохо скопировать ее сюды http://www.phpforum.ru/printpages.php |
|
|
Offline Новичок Профиль Журнал Группа: Пользователь Сообщений: 29 Пользователь №: 705 На форуме: Репутация: нет |
Понравилось. Просто и поучительно.
-------------------- |
|
|
Unregistered |
Пробовал использовать скрипт на подобном xml с Colibri.ru.
Там в теге встречаются символы - <BR> В массив записывается только текст находящийся после последнего вхождения в тег символов - <BR> Хочется всю инфу из тега. Как это сделать. |
|
|
Offline Здесь живет Профиль Журнал Группа: Форумчанин Сообщений: 460 Пользователь №: 856 На форуме: Репутация: нет |
Коллеги, с появлением PHP5 я бы рекомендовал все-таки обратить взгляд на SimpleXML. Код, который делает все тоже самое будет раза в три короче и читабельнее. Не говоря уж о поддержке XPath. -------------------- |
|
|
Unregistered |
А если можно подскажите как будет выглядеть данный код на XPath.
Вопрос: необходимо из Xml-файла размером 33 мега, вытащить информацию по 1 книге с определенным значением в теге id. Как это можно сделать быстрее по времени выполнения скрипта. |
|
|
Unregistered |
Изменил вышеуказанный скрипт с целью получения инфы по книге с атрибутом id=111406 в теге <offer>.<br>Ничего не выводит, даже почему-то значение переменной $kod не выводит, если ставлю print ($kod) в функциях.<br>Помогите, плиз.<br><br>
function startElement($parser, $name, $attrs) { foreach ( $attrs as $n => $v) { if (($name=='offer') && (($n=='id') && ($v==111406))) $kod=1; } } function endElement($parser, $name) { // Эта ф-ия работает при встрече закрывающего тега if (($name=='offer') && ($kod==1)) $kod=0; } function characterData($parser, $data) { // Эта ф-ия работает с данными внутри тега if ($kod==1) print "<b>".$data. "</b> "; } |
|
|
Offline Пользователь Профиль Журнал Группа: Форумчанин Сообщений: 56 Пользователь №: 3445 На форуме: Репутация: нет |
нужна помощ допустим у меня есть xml :
Цитата
<?xml version="1.0" encoding="windows-1251"?> <!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN" "http://my.netscape.com/publish/formats/rss-0.91.dtd"> <rss version="2.0"> <channel> <title>Lenta.ru: НОВОСТИ, 09.11.2007</title> <link>http://lenta.ru/</link> <description>Ежедневная интернет-газета. Новости со всего мира на русском языке</description> <item> <title>Польским премьером стал лидер оппозиции</title> <link>http://lenta.ru/news/2007/11/09/tusk/</link> <description>Президент Польши Лех Качиньский назначил главой правительства Дональда Туска и поручил ему сформировать новый кабинет. По закону у лидера оппозиционной партии "Гражданская платформа" есть 14 дней на решение кадровых вопросов, но Туск пообещал назвать новых министров уже на следующей неделе.</description> <pubDate>Fri, 09 Nov 2007 17:43:26 +0300</pubDate> <category>В мире</category> </item> <item> <title>В поезде "Юность" бомба не обнаружена</title> <link>http://lenta.ru/news/2007/11/09/evac1/</link> <description>Оперативники, обследовавшие все 20 вагонов фирменного поезда "Юность" сообщением Петербург-Москва, не обнаружили взрывного устройства. Неизвестный мужчина, сообщивший о бомбе дежурному Московского вокзала, объявлен в розыск. Состав был остановлен на станции Тосно, а около тысячи пассажиров эвакуированы.</description> <pubDate>Fri, 09 Nov 2007 17:07:52 +0300</pubDate> <category>В России</category> </item> <item> <title>Лондонский террорист признал себя виновным в попытке взрыва в метро</title> <link>http://lenta.ru/news/2007/11/09/plead/</link> <description>Манфо Кваку Азиеду, один из шести обвиняемых по делу о подготовке серии взрывов на лондонском транспорте 21 июля 2005 года, признан виновным в заговоре с целью осуществления теракта. На процессе он признал выдвинутые против него обвинения. Четверо сообщников Азиду в июле 2007 года уже были осуждены на 40 лет.</description> <pubDate>Fri, 09 Nov 2007 19:20:20 +0300</pubDate> <category>В мире</category> </item> </channel> </rss> мне надо пропарсить и записать все это в массивы и при этом я не знаю какая глубина и какие теги в xml всю инфу надо выдерать только между тегами "item" но это для примеря я поги их и не знать. --------------------
Как я завидую безмозглым!
|
|
|
Offline Здесь живет Профиль Журнал Группа: Форумчанин Сообщений: 4152 Пользователь №: 17 На форуме: Репутация: +12/-1 |
DOM - http://pyha.ru/forum/topic/32.0 так же есть специальные библиотеки именно для RSS. --------------------
Блог ГО | Кинсбург.ру
|
|
|
Offline Пользователь Профиль Журнал Группа: Форумчанин Сообщений: 56 Пользователь №: 3445 На форуме: Репутация: нет |
все навоял разобрался немного
Код
class Acid {
var $name; // имя aa var $symbol; // трёхбуквенный символ var $code; // однобуквенный код var $type; // hydrophobic, charged или neutral function Acid ($aa) { foreach ($aa as $k=>$v) $this->$k = $aa[$k]; } } function readDatabase($filename) { global $m; // читать xml БД $data = implode("",file($filename)); $parser = xml_parser_create(); 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,$data,$values,$tags); xml_parser_free($parser); foreach ($tags as $key0=>$val0) { if ($m<count($val0)){ $m=count($val0); $tg = $key0; } } // цикл по этим структурам foreach ($tags as $key=>$val) { if ($key == "$tg") { $molranges = $val; // каждая пара вхождений массива это нижняя и верхняя // границы диапазона для определения for ($i=0; $i < count($molranges); $i+=2) { $offset = $molranges[$i] + 1; $len = $molranges[$i + 1] - $offset; $tdb[] = parse(array_slice($values, $offset, $len)); } } else { continue; } } return $tdb; } function parse($mvalues) { for ($i=0; $i < count($mvalues); $i++) $mol[$mvalues[$i]["tag"]] = $mvalues[$i]["value"]; return new Acid($mol); } $db = readDatabase("lenta.xml"); for ($i=0;$i<count($db);$i++){ foreach ($db[$i] as $key=>$val){ if ($val){ echo "$key -> $val <br>"; } } echo "<br>"; } --------------------
Как я завидую безмозглым!
|
|
[x] Дата
|
Offline Новичок Профиль Журнал Группа: Пользователь Сообщений: 8 Пользователь №: 16724 На форуме: Репутация: нет |
Подскажите пожалуйста. Имеется следующий скрипт:
$parser = xml_parser_create(""); xml_set_element_handler( $parser, "start_handler", "end_handler" ); xml_set_character_data_handler( $parser, "character_handler" ); xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, 0 ); $file = file_get_contents($document); xml_parse( $parser, $file) or die ( format_error( $parser ) ); xml_parser_free( $parser ); function start_handler( $p, $name, $atts ) { global $open_stack; $open_stack[] = array($name, ""); } function character_handler( $p, $txt ) { global $open_stack; $cur_index = count($open_stack)-1; $open_stack[$cur_index][1] = $open_stack[$cur_index][1] . $txt; } function end_handler( $p, $name) { global $open_stack; $el = array_pop( $open_stack ); // ОБЩИЕ ЭЛЕМЕНТЫ // простой текст if ( $name == "p") { echo "<p/>$el[1]</p/>"; } // простые ссылки // ссылка-текст с указанием пути к ресурсу внутри сайта if ( $name == "ahref") { echo "<a href=rus.php?link=$el[1]>"; } // ссылка-текст с названием страницы if ( $name == "atext") { echo "$el[1]</a/>"; } // глобальная ссылка-текст к ресурсу if ( $name == "webref") { echo "<a href=\"$el[1]\">"; } // текст глобальной ссылки if ( $name == "webtext") { echo "$el[1]</a/>"; } // текст-постскриптум if ( $name == "ps") { echo "<p class=\"ps\"/>$el[1]</p/>"; } // НОВОСТИ // дата if ( $name == "datenews") { echo "<br/>"; echo "<div align=\"left\"/>"; echo "<i class=\"news\"/>$el[1]</i/>"; echo "</div/>"; } // заголовок if ( $name == "hnews") { echo "<br/>"; echo "<h2 class=\"news\"/>$el[1]</h2/>"; } // текст if ( $name == "pnews") { echo "<p class=\"news\"/>$el[1]</p/>"; echo "</div/>"; } // изображения if ( $name == "imagenews") { echo "<img class=\"news\">$el[1]</img>"; } if ( $name == "news") { echo "<div class=\"news\"/>"; echo "<hr/ class=\"news\">"; echo "</div/>"; } // КОНЦЕРТЫ // дата if ( $name == "dateconzert") { echo "<br/>"; echo "<div align=\"left\">"; echo "<i class=\"conzert\"/>$el[1]</i>"; //echo "</div/>"; } // заголовок if ( $name == "hconzert") { echo "<h2 class=\"conzert\"/>$el[1]</h2/>"; } // текст if ( $name == "pconzert") { echo "<p class=\"conzert\"/>$el[1]</p/>"; echo "</div/>"; } // изображения if ( $name == "imgconzert") { echo "<img class=\"conzerts\">$el[1]</img>"; } if ( $name == "conzert") { echo "<div/>"; echo "<hr/ class=\"conzert\">"; echo "</div/>"; } // ГОСТЕВАЯ // дата if ( $name == "dateguest") { echo "<br/>"; echo "<div align=\"left\"/>"; echo "<p class=\"guestdate\"/>$el[1]</p/>"; } // имя if ( $name == "nameguest") { echo "<h2 class=\"guest\"/>Гость: $el[1]</h2/>"; } // город if ( $name == "cityguest") { echo "<h2 class=\"guest2\"/>Страна/город: $el[1]</h2/>"; } // текст if ( $name == "pguest") { echo "<p class=\"guest\"/>$el[1]</p/>"; } // ответ администратора if ( $name == "padmin") { echo "<p class=\"admin\"/>$el[1]</p/>"; echo "</div/>"; } if ( $name == "comment") { echo "<div/>"; echo "<hr/ class=\"guest\" align=\"center\">"; echo "</div/>"; } /////////////////////////////////////////////////////////////////////////////////// } function format_error ( $p ) { $code = xml_get_error_code( $p ); $str = xml_error_string( $code ); $line = xml_get_current_line_number ( $p ); return "Ошибка XML ($code): $str в строке $line"; } Как его изменить, чтобы он выводил документ наоборот, т.е. первым выводилась информация в последнем <news>, <comment>, затем в предпоследнем, пред-предпоследнем и так до первого? p.s.: пытался применить "array_reverse", никак не помогло - или переворачивает не те теги, или php выдает ошибки. |
|
|
Offline Новичок Профиль Журнал Группа: Пользователи Сообщений: 1 Пользователь №: 16984 На форуме: Репутация: нет |
у меня вопрос, если можно...
я сделал парсер наподобие того, что в первом посте. но хотел бы парсить не какой-то фаил, который к примеру у меня на винте находится (one.xml), а интернетовскую страницу. ну допустим вот эту http://lenta.ru/news/2007/11/09/tusk/ я пока совсем начинающий пользователь и не представляю как добраться до этого xml-файла. то есть какой путь указывать в $file = подскажите пожалуйста |