За последние 24 часа нас посетили 18662 программиста и 1828 роботов. Сейчас ищут 1144 программиста ...

Как устроен парсер XML?

Тема в разделе "Прочие вопросы по PHP", создана пользователем vuzy, 13 мар 2010.

  1. vuzy

    vuzy Активный пользователь

    С нами с:
    11 мар 2010
    Сообщения:
    199
    Симпатии:
    0
    Адрес:
    киев
    Господа програмисты столкнулся с такой задачей как парсинг XML.
    Посылается на отдаленный сервер GET запрос с необходимой информацией и возвращает некий XML код

    HTML:
    1.  
    2. <site>
    3. <people>
    4.         <login>вася</login>
    5.         <sex>1</sex>
    6.         <date_registration>23.02.2010</date_registration>
    7. </people>
    8. <people>
    9.         <login>надя</login>
    10.         <sex>0</sex>
    11.         <date_registration>12.03.2010</date_registration>
    12. </people>
    13. <people>
    14.         <login>admin</login>
    15.         <sex>1</sex>
    16.         <date_registration>01.01.2000</date_registration>
    17. </people>
    18. </site>
    19.  
    Нужно этот код получить и обработать после чего все записать в соответствующем порядке в базу данных. после чего вывести его пользователю.

    Подскажите в каком направлении следует капать? с помощью каких функций это реализируется?
    если не сложно приведите какойнибудь простенький пример. Я хочу научится =)
     
  2. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
  3. vuzy

    vuzy Активный пользователь

    С нами с:
    11 мар 2010
    Сообщения:
    199
    Симпатии:
    0
    Адрес:
    киев
    Загуглил ничего хорошего не нашел... все рассказывают о XML что такое и с чем едят и примеры создания на яваскрипте...
    нашел что то похожее для php но там нужна какая то функция типа domxml_open_mem() а она у меня не поддерживается может есть что то другое так что б подошли следующие библиотеки:
    php_sockets.dll
    php_xmlrpc.dll
    php_xsl.dll
    последнее может вообще не в тему но на XML похоже...
     
  4. lexa

    lexa Активный пользователь

    С нами с:
    22 июл 2007
    Сообщения:
    1.746
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    vuzy, пользуй SimpleXML он проще и начиная с пятой версии PHP входит в стандартный набор, т.е. доп. модули не нужны.

    PHP:
    1. <?
    2. $xml = simplexml_load_file('ссылка на сайт, откуда приходит XML');
    3. $result = $xml->xpath('/people');
    4.  
    5. echo $result[0]['login']; // вася
    На самом деле $result не массив в плане is_array($result) == false, но ведёт себя похоже. Можно использовать с foreach.

    P.S. Не знаю, надо ли было написать ответ так: на самом деле $result итерабильный объект с ArrayAccess? :)[/img]
     
  5. vuzy

    vuzy Активный пользователь

    С нами с:
    11 мар 2010
    Сообщения:
    199
    Симпатии:
    0
    Адрес:
    киев
    Такой умной фразы я бы не понял =)

    PHP:
    1. $result = $xml->xpath('/people');
    как это понимать? Я понял что это закрывающий тег массива XML. Но как он работает? Может парсит все что находится между "родительскими" тегами Peolple?
     
  6. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Любопытно, где надо так гуглить? Научите.

    http://php.net/dom

    http://ru.wikipedia.org/wiki/XPath
     
  7. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    vuzy
    если сервера твои, можно посылать что-нибудь другое кроме xml.
    например serialize array

    если нужно какой-то конкретный результат, лучше подойдут регулярки
     
  8. vuzy

    vuzy Активный пользователь

    С нами с:
    11 мар 2010
    Сообщения:
    199
    Симпатии:
    0
    Адрес:
    киев
    в том то и дело что сервер не мой. Но они предоставляют вывод определенной публичной информации через XML.

    Я все таки добился определенного результата с помощью функций:
    PHP:
    1.  
    2. <?
    3. require_once('bd.php');
    4. $file=file_get_contents("некий xml запрос");
    5. $xml->username=mb_convert_encoding($xml->username, "Windows-1251", "UTF-8");
    6. $xml->slogan=mb_convert_encoding($xml->slogan, "Windows-1251", "UTF-8");
    7. $xml->about=mb_convert_encoding($xml->about, "Windows-1251", "UTF-8");
    8. $xml->roomname=mb_convert_encoding($xml->roomname, "Windows-1251", "UTF-8");
    9. $xml->racename=mb_convert_encoding($xml->racename, "Windows-1251", "UTF-8");
    10. $xml->realname=mb_convert_encoding($xml->realname, "Windows-1251", "UTF-8");
    11. $xml->city=mb_convert_encoding($xml->city, "Windows-1251", "UTF-8");
    12. $xml->country=mb_convert_encoding($xml->country, "Windows-1251", "UTF-8");
    13. $xml->aligTitle=mb_convert_encoding($xml->aligTitle, "Windows-1251", "UTF-8");
    14. $update=time();
    15. $sql="INSERT INTO haddan_user VALUES ()"; //впихнуть все в БД
    16. //mysql_query($sql2) or die (mysql_error()); это тут не нужно закоментил что б не выдавало ошибку =)
    17. ?>
    18.  
    структура файла заведомо известна. И поэтому довольно просто выбрать данные перекодировать их и внести в свою Базу данных. Единственное чего я не понял. Это то что используя функцию mb_convert_encoding сразу ко всему массиву XML он абсолютно ничего не выводит... а пот так поштучно перекодировать так он соображает =)
     
  9. vuzy

    vuzy Активный пользователь

    С нами с:
    11 мар 2010
    Сообщения:
    199
    Симпатии:
    0
    Адрес:
    киев
    АП...

    Возник еще один вопрос.. как получить код ошибки из тэгов

    <site err="104" op="user">
    <error>
    Неправильное имя персонажа или пароль
    </error>
    </site>

    как выудить это 104? для того чтоб прекратить выполнение скрипта если оно верно? а тоон так всю базу испортить может
     
  10. lexa

    lexa Активный пользователь

    С нами с:
    22 июл 2007
    Сообщения:
    1.746
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
  11. vuzy

    vuzy Активный пользователь

    С нами с:
    11 мар 2010
    Сообщения:
    199
    Симпатии:
    0
    Адрес:
    киев
    эта функция выводит массив переменной XML

    мне нужно просто как то обратится к параметру "er" что бы проверить его значение можно даже не присылать готовый код объясните на пальцах..
     
  12. vuzy

    vuzy Активный пользователь

    С нами с:
    11 мар 2010
    Сообщения:
    199
    Симпатии:
    0
    Адрес:
    киев
    PHP:
    1.  
    2. <?
    3. if ($xml->site->@err==104)
    4. {
    5. //code
    6. }
    7. ?>
    8.  
    будет рабоать? или лучше

    PHP:
    1.  
    2. <?
    3. if ($xml->@err==104)
    4. {
    5. //code
    6. }
    7. ?>
    8.  
     
  13. lexa

    lexa Активный пользователь

    С нами с:
    22 июл 2007
    Сообщения:
    1.746
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Именно так. Знаешь, что интересно? Через неё можно увидеть способ добраться до нужного ключа. ;)

    Почему ты в документацию не смотрел? Там примеры есть.

    Как-то так:
    PHP:
    1. <?
    2. $xml->attributes()->err
     
  14. vuzy

    vuzy Активный пользователь

    С нами с:
    11 мар 2010
    Сообщения:
    199
    Симпатии:
    0
    Адрес:
    киев
    да вот посмотрел про симпл хмл с содержимым помог... а больше там ниочем не говорится.. Спасибо помогло.
     
  15. vuzy

    vuzy Активный пользователь

    С нами с:
    11 мар 2010
    Сообщения:
    199
    Симпатии:
    0
    Адрес:
    киев
    такой вопрос.. пробовал старатся обойти массив в цикле с помощью xpath что б достать из people значение "логина" "пола" и "даты регистрации"
    но он мне ровным счетом ничего не выдает...
    PHP:
    1.  
    2. <?
    3. $xmlcount=count($xml->people);
    4. $users=$xml->xpath('/people');
    5. for($i=1; $i < $xmlcount; $i++)
    6. {
    7. echo $i;
    8. echo $users[$i][login];
    9. echo ' - имя пользователя <br>';
    10. }
    11.  
    точнее выдает:
    Код (Text):
    1.  
    2. 1  - имя пользователя
    3. 2  - имя пользователя
    4. 3  - имя пользователя
    5. 4  - имя пользователя
    как с помощью xpath обращатся то к дочерным элементам? по его имени =\\ или как перейти на следующий элемент people что бы продолжить??
     
  16. lexa

    lexa Активный пользователь

    С нами с:
    22 июл 2007
    Сообщения:
    1.746
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Я ж писал:
    А ты for() используешь. Разные вещи. foreach() дёргает итератор, for() генерирует энное кол-во итераций.

    В PHP 5 луше использовать foreach() чаще. Это раньше for() был быстрее местами.

    upd к тому же:
    PHP:
    1. <?
    2. $xmlcount=count($xml->people);
    3. $users=$xml->xpath('/people');
    WTF? Чего ты от этой конструкции ожидаешь?

    upd2 не могу понять, ёскель-моксель, документация тебе совсем не друг?
     
  17. vuzy

    vuzy Активный пользователь

    С нами с:
    11 мар 2010
    Сообщения:
    199
    Симпатии:
    0
    Адрес:
    киев
    нет не друг я ее читал честно но там только какие то совсем ненужные функции ... и даже примеров нет а там где есть то на английском =)...

    коунтом я считаю сколько людей в списке а потом передаю это циклу и пока есть люди цикл пашет после чего перестает и выходит...

    Всеравно:

    PHP:
    1.  
    2. <?
    3. foreach ($xml->people[0]->attributes() as $a=>$b)
    4. {
    5. echo $a.' - ';
    6. echo $b;
    7.  
    выводит только атрибуты первого тэга people хоть с 0 хоть без него... пробовал делать переменную счетчик что б она всевремя добавлялась и выводила следующий элемент тоже не хочет может сделать что то вроде цикла фореач в цикле фор? тогда он точно выведет столько сколько надо =)))

    UPD:
    PHP:
    1.  
    2. <?
    3. $file=file_get_contents('user.xml');
    4. $countxml=count($xml->people);
    5. $i=0;
    6. //$clans=$xml->xpath('/clan');
    7. for ($s=0; $s<$countxml; $s++)
    8. {
    9. foreach ($xml->people[$i]->attributes() as $a=>$b)
    10. //foreach ($clans[0][name] as $a)
    11. {
    12. echo $a.' - ';
    13. echo $b;
    14. echo ' - имя пользователя<br>';
    15. $i++;
    16. }
    17. }
    18. ?>
    19.  
    выдает желаемый результат... а если внутри этого фореач организовать еще один то можно получить внутри 3 циклов еще и значение этих тэгов... а как сделать эо покороче ?? что б за 1 фореач обойти весь тэг people со всеми вложенными в него тэгами?
     
  18. lexa

    lexa Активный пользователь

    С нами с:
    22 июл 2007
    Сообщения:
    1.746
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    vuzy, ох, какой ты геморройный. :) С документаций да, хреного, но её надо учиться читать, какая бы не была. Плюс у доков иногда полезные комментарии.

    Ок. Давай с нуля?

    Ты получаешь содержание файла, суёшь содержание в SimpleXML. Кстати. можно так писать
    PHP:
    1. <?
    2. $xml = simplexml_load_file('user.xml');
    Затем ты берёшь $xml->people и считаешь. НО. Ты неверно толкуешь подсчёт. Он неверный. Переменная $xml->people это то же самое, что $xml->people[0].

    Понял смысл? $xml->people это обращение к первому элементу. Следовательно, считая его ты считаешь не количество тегов <people />. Не-а. Ты считаешь кол-во элементов внутри первого тега <people />! И их всегда будет три. То есть работоспособность твоего скрипта обманчива.

    Теперь про foreach(). Он вызывает объект итератор у класса SimpleXML. И проходит по каждому значению:
    PHP:
    1. <?
    2. foreach ($xml->people as $man){
    3.     echo $man->login.'<br />';
    4. }
    5.  
    6. /*
    7. вася
    8. надя
    9. admin
    10. */
    Ок. Теперь заменим твой XML на такой (добавим атрибут):
    HTML:
    1. <site>
    2.     <people>
    3.         <login>вася</login>
    4.         <sex>1</sex>
    5.         <date_registration>23.02.2010</date_registration>
    6.     </people>
    7.    
    8.     <people clan="Test">
    9.         <login>надя</login>
    10.         <sex>0</sex>
    11.         <date_registration>12.03.2010</date_registration>
    12.     </people>
    13.    
    14.     <people>
    15.         <login>admin</login>
    16.         <sex>1</sex>
    17.         <date_registration>01.01.2000</date_registration>
    18.     </people>
    19. </site>
    И снова сделаем foreach():
    PHP:
    1. <?
    2. foreach ($xml->people as $man){
    3.     echo $man->login.' ['.$man->attributes()->clan.']<br />';
    4. }
    5.  
    6. /*
    7. вася []
    8. надя [Test]
    9. admin []
    10. */
    Теперь понял силу документации? :)
     
  19. vuzy

    vuzy Активный пользователь

    С нами с:
    11 мар 2010
    Сообщения:
    199
    Симпатии:
    0
    Адрес:
    киев
    PHP:
    1. <?
    2.  $xml = simplexml_load_file('user.xml');
    Это понятно. Я уже научился...
    file_get_contents("")
    или
    simplexml_load_file('')
    одно и тоже.
    а ты видать не проверял ?? я посчитал количество тэгов в файле и получил ожидаемый результат в 109 штук после чего выполнил скрипт 109 раз и получил 109 разных записей в таблице =)) так что все верно у меня считает.

    а вот это реально круто =)) тоесть он пройдется по тэгам people назовет их $man и можно будет обратится к его элементам и атрибутам...

    Да сколняю голову перед силой документации но вот если бы она была написана по русски я бы понял это все гаразно раньше а так у меня в книге только пример с выше описанным гемороем =)))))))
     
  20. lexa

    lexa Активный пользователь

    С нами с:
    22 июл 2007
    Сообщения:
    1.746
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Ты прав, не проверил.

    P.S. Документация раньше была почти вся на русском. После обновления php.net, ждём когда напереводят.
     
  21. vuzy

    vuzy Активный пользователь

    С нами с:
    11 мар 2010
    Сообщения:
    199
    Симпатии:
    0
    Адрес:
    киев
    может ты уже знаешь я когда искал библиотеку (вчера) одну наткнулся на сайт http://www.php.su/functions/?count теперь от туда инфу черпаю =)
     
  22. http://docs.php.net/manual/ru/index.php
     
  23. lexa

    lexa Активный пользователь

    С нами с:
    22 июл 2007
    Сообщения:
    1.746
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    vuzy, все доки на русском устарели. Пользуйся, но поглядывай и на документацию на php.net. Например, прочёл про count() на русском, потом посмотри документацию на http://php.net/count

    флоппик, ага-ага? :) Там всё сырое, выкинутого с основного домена.
     
  24. Костян

    Костян Активный пользователь

    С нами с:
    12 ноя 2009
    Сообщения:
    1.724
    Симпатии:
    1
    Адрес:
    адуктО
    там не всё сырое, там просто недопереведено
     
  25. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Костян
    Оно не просто "недопереведено", оно действительно во многих местах устарело. И выяснять эти места на собственном коде малоприятное занятие