| ||
|
Парсване на XML през PHP.![]() XML файловете са много "модерни" и удобни в днешния Интернет свят, могат да служат за много и различни цели, от просто маркиране на дадена файлова система, до сложна комуникация между два различни сървъра. Всеки решил да се занимава с разработването на уеб рано или късно ще му се наложи да работи именно с такъв тип файлове. За урока предполагаме, че имаме дърво от директории с неограничена дълбочина, като във всяка директория (без основната) има по един xml файл, който маркира съдържанието на съответната директория (в случая на примерите - книги), всички xml файлове са със сходна структура и имат някой задължителни елементи. Отбележете, че може би няма да е лоша идея да си вземете под ръка PHP Manual-а за да погледнете някой от функциите ползвани в по-долните примери. Има и доста коментари по кодовете така, че им обърнете внимание. На края на урока има и линк към цялата работеща система, с подробно описание какви настройки да нпарваите за да тръгне, предварително се изивнявам, че всички файлове са с коментари на английски ( колкото и лош да е той), но ситуацията го изискваше ![]() Опис на файловете: Основни: bpclass.php -- файла, който съдържа класа на самият парсър inclu_fns.php -- файла, който съдържа библиотеката от функции, който ще ползваме merged.php -- файла, с чиято помощ ще можем да направим един голям общ XML файл Конфигурационни: config.php -- файла, който съдържа основните настройки, без който "системата" няма да работи db_info.php -- файла, който съдържа данни за връзката с базата данни ТРЯБВА ДА СЕ НАМИРА ИЗВЪН ПАПКАТА public_html Допълнителни: bottom.php -- съдържа, фуутъра на страницата top.php -- съдържа, хедъра на страницата index.php -- единствения файл, с който борави потребителя И така...време е да се мятаме ![]() Започваме с основния BookParser клас, който се намира в bpclass.php. <?php class BookParser { var $_mode; var $_url; var $_content; var $_stack = array();//краен масив на всички намерени обекти във файла var $_names = array();//Тук съхраняваме всички времени имена на получените обекти function set_BP($mode, $url, $file_content) { $this->_content = $file_content; $this->_mode = $mode; $this->_url = $url; } function parser() { $this->parseXML(); return $this->_stack; } // Основния метод, който парсва всички обекти/елементи на XMl файла function parseXML() { $xml_parser = xml_parser_create("UTF-8"); //Казваме на парсъра, че нашите файлове са с UTF кодировка, доста е важно ако искаме да се държи нормално и с файлове, които съдържат не само латински букви xml_parser_set_option($xml_parser, XML_OPTION_SKIP_WHITE, 1); //Задаваме опции на парсъра xml_set_object($xml_parser, $this); xml_set_element_handler($xml_parser, "startElementHandler", "endElementHandler");//Показваме на парсъра кои методи да вика в определени ситуации xml_set_character_data_handler($xml_parser, 'cdataHandler');//същото като горното if ($this->_mode != 'all') { if (@!($fp = fopen($this->_url, "rb"))) { die("Could not open XML input"); } while ($data = fread($fp, 4096)) { if (@!xml_parse($xml_parser, $data, feof($fp))) { die(sprintf("XML error: %s at line %d", xml_error_string(xml_get_error_code($xml_parser)), xml_get_current_line_number($xml_parser))); } } } elseif($this->_mode == 'all') { if (@!xml_parse($xml_parser, $this->_content, feof($fp))) { die(sprintf("XML error: %s at line %d", xml_error_string(xml_get_error_code($xml_parser)), xml_get_current_line_number($xml_parser))); } } xml_parser_free($xml_parser); } // Метод, към който се обръщаме когато парсъра достигне началото на обект function startElementHandler($parser, $name, $attrs) { array_push($this->_names, $name); if ($name == 'BOOKCONTAINER') { $this->_currentBook = array(); $this->_currentBook['num'] = -1; } elseif ($name == 'BOOK') { $this->_currentBook['num']++; } } // Метод, към който се обръщаме когато парсъра достигне стойноста на обекта function cdataHandler($parser, $cdata) { $cdata = trim($cdata); $this->_currentName = array_slice($this->_names, -1, 1); $this->_currentName = $this->_currentName[0]; if (empty($this->_stack['BOOK' . $this->_currentBook['num']][$this-> _currentName])) { if (!empty($cdata)) $this->_stack['BOOK' . $this->_currentBook['num']][$this->_currentName] = $cdata; } else { if (!empty($cdata)) $this->_stack['BOOK' . $this->_currentBook['num']][$this->_currentName] .= $cdata; } } // Метод към който парсъра се обръща, когато стигне края на обект function endElementHandler($parser, $name) { //в нашия простоват пример нямаме нужда да правим нищо } } ?> Този клас е ядрото на цялата система, тук се извършват няколко доста прости, но и важни неща. Първо ще обърна внимание на двата метода, които ще се "викат" от този клас, това са set_BP($mode, $url, $file_content) и parser(). Първият метод, очевидно подава на класа някой витални за него данни: $mode показва на класа дали ще парсваме само един XML файл или ще ги вземем всичките веднъж, $url съвсем ясно задава пътя към дадения файл, а $file_content подава съдържанието на всички файлове при положение че mode е указало това. Методът parser() извиква големият метод parseXML() и връща неговия резултат.
|
|