Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Как распарсить сложный XML?

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (2): [1] 2 »   

> Без описания
President
Отправлено: 26 Января, 2009 - 23:49:45
Post Id


Новичок


Покинул форум
Сообщений всего: 18
Дата рег-ции: Янв. 2009  


Помог: 0 раз(а)




Есть XML нижеуказанного вида.
Я не большой специалист в парсинге. Кинулся юзать Dom.
Пример запроса ниже.
Но столкнулся со следующим:
Парсер показывает 3 узла:
Uzel 0 : Source=
NewsBox
Uzel 1 : Time=
23.01.2009 16:57:18
Uzel 2 : InfoItem=
"ЦБ повысил с 24/01 учетную цену золота до 923,22 руб дубльБиржи Банки ФондыСитуация и прогноз....... текст весь что есть в этом блоке без всяких <> заканчивая[B] ....... Департаментом внешних и общественных связей ЦБ РФ".
[b]Т.е. узел InfoItem не распарсилсяна вложенные в него подузлы! Зато исчезли теги таблиц

Как правильно сделать или хотя бы в каком направлении думать. Пож-ста. Сложность еще в том, что кодировка файла не UTF-8
Нужно чтобы работало на PHP5.
Наверняка есть команды или варианты обхода и вложенных узлов... Но что то пример нагуглить не могу. Да и 90 % почему то варианты нерабочие на PHP5 скачиваю...
Пропали в выводе теги вложенной таблицы. Их бы тоже сохранить как

PHP:
скопировать код в буфер обмена
  1. <?PHP
  2. $dom = new DOMDocument();
  3. $dom->load("primer.xml");
  4. echo "<br>new<br>";
  5. $root = $dom->documentElement;
  6. $nodeList = $root->childNodes;
  7. echo "Total: $nodesList->lenght";
  8. echo $nodeList->lenght;
  9. echo $x->childNodes;
  10. echo $root->childNodes->lenght;
  11. echo "<br>";
  12. $i=0;
  13. for ($child=$root->firstChild; $child; $child=$child->nextSibling)
  14. {
  15. $child = $nodeList->item($i);
  16. echo "Узел $i : ";
  17. echo iconv("UTF-8","windows-1251",$child->nodeName);
  18. echo "=";
  19. echo '<h3>' , iconv("UTF-8","windows-1251", $child->nodeValue) , '</h3>';
  20. $i++;
  21. }
  22. ?>


<?xml version="1.0" encoding="windows-1251"?>
<!DOCTYPE InfoPacket SYSTEM "http://xml.x.ru/dtd/UIF.dtd">
<InfoPacket>
<Source type="string">NewsBox</Source>
<Time type="datetime">23.01.2009 16:57:18</Time>
<InfoItem>
<Source type="string">ИСТОЧНИК</Source>
<Time type="datetime">23.01.2009 15:54:00</Time>
<Title type="string">ЦБ повысил с 24/01 учетную цену золота до 923,22 руб дубль</Title>
<Topic type="string">Биржи Банки Фонды</Topic>
<Topic type="string">Ситуация и прогнозы</Topic>
<Direction type="string">free</Direction>
<Author type="string">с</Author>
<Keyword type="string">ЗОЛОТО-БАНК</Keyword>
<Option name="DirectionId" type="int">18</Option>
<Option name="DirectionId" type="int">32</Option>
<Option name="Abstract" type="string">ЦБ РФ установил с 24 января следующие учетные цены на драгоценные металлы:</Option>
<Text>ЦБ РФ установил с 24 января следующие учетные цены на драгоценные металлы:</Text>
<Text>ЦЕНЫ НА ДРАГОЦЕННЫЕ МЕТАЛЛЫ ЦБ РФ * с 24.01.2009
<Data>
<Table abstract="">
<Column name="col0" type="string">металл</Column>
<Column name="col1" type="string">учетная цена</Column>
<Column name="col2" type="string">тренд</Column>
<Row>
<Cell name="col0" type="string">золото</Cell>
<Cell name="col1" type="decimal">923.22</Cell>
<Cell name="col2" type="decimal">+29.26</Cell>
</Row>
<Row>
<Cell name="col0" type="string">серебро</Cell>
<Cell name="col1" type="decimal">11.97</Cell>
<Cell name="col2" type="decimal">+0.01</Cell>
</Row>
<Row>
<Cell name="col0" type="string">платина</Cell>
<Cell name="col1" type="decimal">982.44</Cell>
<Cell name="col2" type="decimal">+1.74</Cell>
</Row>
<Row>
<Cell name="col0" type="string">палладий</Cell>
<Cell name="col1" type="decimal">193.53</Cell>
<Cell name="col2" type="decimal">-1.56</Cell>
</Row>
</Table>
</Data>
</Text>
<Text>* - цены и тренд указаны в рублях за 1 грамм</Text>
<Text>Данные предоставлены Департаментом внешних и общественных связей ЦБ РФ</Text>
</InfoItem>
</InfoPacket>
(Добавление)
подписка на ответы

(Отредактировано автором: 26 Января, 2009 - 23:50:36)

 
 Top
Джур
Отправлено: 27 Января, 2009 - 08:36:26
Post Id



Посетитель


Покинул форум
Сообщений всего: 423
Дата рег-ции: Март 2007  


Помог: 0 раз(а)




Не заморачивайтесь, заюзайте лучше simplexml_load_string(). я им такие вещи разбираю... Значит и вам поможет.
PHP:
скопировать код в буфер обмена
  1. <pre><?PHP
  2. $xml=simplexml_load_file('1.xml');
  3. print_r($xml->infoitem->text[1]);
  4. ?></pre>

(Отредактировано автором: 27 Января, 2009 - 09:13:09)



-----
Тамбовский каджит тебе товарищ
 
 Top
President
Отправлено: 27 Января, 2009 - 17:19:23
Post Id


Новичок


Покинул форум
Сообщений всего: 18
Дата рег-ции: Янв. 2009  


Помог: 0 раз(а)




Сделал вот такой код:
PHP:
скопировать код в буфер обмена
  1. <?PHP
  2. $xml = new SimpleXMLElement(iconv("UTF-8","windows-1251", file_get_contents('person.xml')));
  3. print_r($xml->infoitem->text[1]);
  4. ?>


И плачу, получил вот такой ответ:

Warning: SimpleXMLElement::__construct() [simplexmlelement.--construct]: Entity: line 3: parser error : Premature end of data in tag Source line 3 in e.php on line 2

Warning: SimpleXMLElement::__construct() [simplexmlelement.--construct]: <Time type="datetime">23.01.2009 16:57:18</Time><InfoItem><Source type="string"> in e.php on line 2

Warning: SimpleXMLElement::__construct() [simplexmlelement.--construct]: ^ in e.php on line 2

Warning: SimpleXMLElement::__construct() [simplexmlelement.--construct]: Entity: line 3: parser error : Premature end of data in tag InfoItem line 3 in e.php on line 2

Warning: SimpleXMLElement::__construct() [simplexmlelement.--construct]: <Time type="datetime">23.01.2009 16:57:18</Time><InfoItem><Source type="string"> in e.php on line 2

Warning: SimpleXMLElement::__construct() [simplexmlelement.--construct]: ^ in e.php on line 2

Warning: SimpleXMLElement::__construct() [simplexmlelement.--construct]: Entity: line 3: parser error : Premature end of data in tag InfoPacket line 3 in e.php on line 2

Warning: SimpleXMLElement::__construct() [simplexmlelement.--construct]: <Time type="datetime">23.01.2009 16:57:18</Time><InfoItem><Source type="string"> in e.php on line 2

Warning: SimpleXMLElement::__construct() [simplexmlelement.--construct]: ^ in e.php on line 2

Fatal error: Uncaught exception 'Exception' with message 'String could not be parsed as XML' in e.php:2 Stack trace: #0 e.php(2): SimpleXMLElement->__construct('<?xml version="...') #1 {main} thrown in e.php on line 2
 
 Top
Stierus Супермодератор
Отправлено: 27 Января, 2009 - 17:24:23
Post Id



Рекордсмен по количеству сообщений за 7 дней


Покинул форум
Сообщений всего: 2132
Дата рег-ции: Дек. 2008  
Откуда: Москваль


Помог: 52 раз(а)




Вы про InfoPacket забыли : $xml->InfoPacket->InfoItem->Text[1]
PHP:
скопировать код в буфер обмена
  1. $res = simplexml_load_file('person.xml');
  2. $return = iconv('utf-8','windows-1251', $xml->InfoPacket->InfoItem->Text[1]);
  3. echo $return;

(Отредактировано автором: 27 Января, 2009 - 17:31:37)

 
My status
 Top
President
Отправлено: 27 Января, 2009 - 18:11:29
Post Id


Новичок


Покинул форум
Сообщений всего: 18
Дата рег-ции: Янв. 2009  


Помог: 0 раз(а)




Stierus пишет:
Вы про InfoPacket забыли : $xml->InfoPacket->InfoItem->Text[1]
PHP:
скопировать код в буфер обмена
  1. $res = simplexml_load_file('person.xml');
  2. $return = iconv('utf-8','windows-1251', $xml->InfoPacket->InfoItem->Text[1]);
  3. echo $return;

Поменял $res на $xml, но все равно на выходе пустота Недовольство, огорчение
(Добавление)
Если:
PHP:
скопировать код в буфер обмена
  1. <?PHP
  2.   $xml = new SimpleXMLElement(iconv("UTF-8","windows-1251", file_get_contents('person.xml')));
  3. echo $xml->InfoPacket->InfoItem->Text[1];
  4.  ?>
то

Warning: SimpleXMLElement::__construct() [simplexmlelement.--construct]: Entity: line 3: parser error : Premature end of data in tag Source line 3 in e.php on line 2

Warning: SimpleXMLElement::__construct() [simplexmlelement.--construct]: <Time type="datetime">23.01.2009 16:57:18</Time><InfoItem><Source type="string"> in e.php on line 2

Warning: SimpleXMLElement::__construct() [simplexmlelement.--construct]: ^ in e.php on line 2

Warning: SimpleXMLElement::__construct() [simplexmlelement.--construct]: Entity: line 3: parser error : Premature end of data in tag InfoItem line 3 in e.php on line 2

Warning: SimpleXMLElement::__construct() [simplexmlelement.--construct]: <Time type="datetime">23.01.2009 16:57:18</Time><InfoItem><Source type="string"> in e.php on line 2

Warning: SimpleXMLElement::__construct() [simplexmlelement.--construct]: ^ in e.php on line 2

Warning: SimpleXMLElement::__construct() [simplexmlelement.--construct]: Entity: line 3: parser error : Premature end of data in tag InfoPacket line 3 in e.php on line 2

Warning: SimpleXMLElement::__construct() [simplexmlelement.--construct]: <Time type="datetime">23.01.2009 16:57:18</Time><InfoItem><Source type="string"> in e.php on line 2

Warning: SimpleXMLElement::__construct() [simplexmlelement.--construct]: ^ in e.php on line 2

Fatal error: Uncaught exception 'Exception' with message 'String could not be parsed as XML' in e.php:2 Stack trace: #0 e.php(2): SimpleXMLElement->__construct('<?xml version="...') #1 {main} thrown in e.php on line 2
(Добавление)
Распарсил вот так:

$dom = new DOMDocument();
$dom->load("person.xml");

$xpath = new DOMXPath($dom);
$arts = $xpath->query("/InfoPacket/Source/Text");

foreach($arts as $art) {
echo $art->nodeName . " - " . $art->nodeValue . "<br />";
}

Но при этом у меня "пропадает" форматирование таблицы (оно становится тоже названиями узлов).
Как сделать так, чтобы некоторые вещи, похожие на узлы, таковыми не считались?
 
 Top
valenok Модератор
Отправлено: 27 Января, 2009 - 20:18:06
Post Id



Здесь могла бы быть ваша реклама


Покинул форум
Сообщений всего: 4574
Дата рег-ции: Июль 2006  
Откуда: Israel


Помог: 3 раз(а)




Среди всего этого я не заметил одного - что получить то надо..
http://ru.php.net/manual/ru/func...-parse.php#87920


-----
Truly yours, Sasha.
 
My status
 Top
Джур
Отправлено: 27 Января, 2009 - 20:18:57
Post Id



Посетитель


Покинул форум
Сообщений всего: 423
Дата рег-ции: Март 2007  


Помог: 0 раз(а)




President пишет:
Сделал вот такой код:

Кролики плакали, но продолжали жрать кактус. Ха-ха
За каким, вы жрете этот кактус? Оставте класс в покое. Что за самолечение блин.

Stierus пишет:
Вы про InfoPacket забыли : $xml->InfoPacket->InfoItem->Text[1]

А вот и нифига... по стандарту <InfoPacket> или любой тег на его месте в обработке не участвует. Подмигивание
Поэтому правильно $xml->InfoItem->Text

PHP:
скопировать код в буфер обмена
  1.  
  2. <pre><?PHP
  3. $xml=simplexml_load_file('1.xml');
  4. echo iconv('utf-8','cp1251',print_r($xml,true));
  5. ?></pre>
  6.  


simplexml_load_file() - создает из документа xml класс со свойствами... Вы можете пробежатся по нему как по массиву,
учитывая "<![!DATA", вложенось и прочие XML заморочки.


-----
Тамбовский каджит тебе товарищ
 
 Top
President
Отправлено: 27 Января, 2009 - 20:54:27
Post Id


Новичок


Покинул форум
Сообщений всего: 18
Дата рег-ции: Янв. 2009  


Помог: 0 раз(а)




valenok пишет:
Среди всего этого я не заметил одного - что получить то надо..
http://ru.php.net/manual/ru/function.xml-parse.php#87920

Не работает. Там только UTF-8
(Добавление)
Заработало! Спасибо! Только я не понял как теперь там табличку то вставить в правильное место .... Точнее тег Data и Table исчезли нафиг Улыбка
SimpleXMLElement Object ( [Source] => NewsBox [Time] => 23.01.2009 16:57:18 [InfoItem] => SimpleXMLElement Object ( [Source] => ПРАЙМ ТАСС [Time] => 23.01.2009 15:54:00 [Title] => ЦБ повысил с 24/01 учетную цену золота до 923,22 руб дубль [Topic] => Array ( [0] => Биржи Банки Фонды [1] => Ситуация и прогнозы ) [Direction] => Array ( [0] => free [1] => Бульон ) [Author] => с [Keyword] => Array ( [0] => ЗОЛОТО-БАНК [1] => ДРАГМЕТАЛЛЫ-ЦЕНЫ ) [Language] => RUS [Option] => Array ( [0] => insert [1] => 13188 [2] => 6 [3] => 7 [4] => 18 [5] => 32 [6] => МОСКВА, 23 января. /ПРАЙМ-ТАСС/. ЦБ РФ установил с 24 января следующие учетные цены на драгоценные металлы: ) [Text] => Array ( [0] => МОСКВА, 23 января. /ПРАЙМ-ТАСС/. ЦБ РФ установил с 24 января следующие учетные цены на драгоценные металлы: [1] => ЦЕНЫ НА ДРАГОЦЕННЫЕ МЕТАЛЛЫ ЦБ РФ * с 24.01.2009 [2] => * - цены и тренд указаны в рублях за 1 грамм [3] => Данные предоставлены Департаментом внешних и общественных связей ЦБ РФ ) ) )

(Отредактировано автором: 27 Января, 2009 - 21:00:56)

 
 Top
Джур
Отправлено: 28 Января, 2009 - 08:43:52
Post Id



Посетитель


Покинул форум
Сообщений всего: 423
Дата рег-ции: Март 2007  


Помог: 0 раз(а)




President пишет:
Заработало! Спасибо! Только я не понял как теперь там табличку то вставить в правильное место

Я когда в первый раз XML парсил сложный, тоже "шокировался" по типу "ээ а где остальное".
На самом деле отображается глубина не более 3-х вроде... Это специфика перевода в array. Показывает 3, а содержит все.

Чтобы получить полную копию xml->array можно обработать как-то так
PHP:
скопировать код в буфер обмена
  1. <pre><?PHP
  2. $xml=simplexml_load_file('1.xml');
  3.  
  4. function pars($xml)
  5. {
  6.   foreach($xml as $k=>$v){
  7.     if(count($v)){
  8.       $a[$k][]=pars($v);
  9.     }else{
  10.       $a[$k][]=$v;
  11.     }
  12.   }
  13.   return $a;
  14. }
  15. print_r(pars($xml));
  16. ?></pre>


Как видите, мы получили подробненько всего монстра.
Учтите, что я не приводил к cp1251, так как пример учебный.

Резюмирую:
То что simplexml выводит xml в таком необычном на первый взгляд виде - это нормально и правильно. А то что таблички "пропали", так просто они слишком глубоко лежали и были скрыты.

Если нужны более подробные/точные пояснения, прошу стучать в аську, не стесняйтесь.

(Отредактировано автором: 28 Января, 2009 - 08:50:46)



-----
Тамбовский каджит тебе товарищ
 
 Top
President
Отправлено: 28 Января, 2009 - 09:02:30
Post Id


Новичок


Покинул форум
Сообщений всего: 18
Дата рег-ции: Янв. 2009  


Помог: 0 раз(а)




Попробую так... Хотя странно, что теги табличек пропали, а информация то из них тянется.
Я думаю, а может сначала поменять эти теги через eger_replace да и жделу конец Улыбка
 
 Top
Джур
Отправлено: 28 Января, 2009 - 14:13:41
Post Id



Посетитель


Покинул форум
Сообщений всего: 423
Дата рег-ции: Март 2007  


Помог: 0 раз(а)




President оставте кактус в покое, он у меня один остался Ха-ха
Возможно вам таки стоит описать задачу, что вы хотите получить. А то я так подозреваю что мы вас не понимаем... или вы нас.


-----
Тамбовский каджит тебе товарищ
 
 Top
President
Отправлено: 29 Января, 2009 - 20:48:24
Post Id


Новичок


Покинул форум
Сообщений всего: 18
Дата рег-ции: Янв. 2009  


Помог: 0 раз(а)




Так у меня что то и не получается, простите глупого Улыбка
В последнем варианте выводятся крякозябры, а мозга исправить мало. Спинной тока видно остался Недовольство, огорчение
Сделал тему:
http://forum.php.su/topic.php?fo...60&topic=499
(Добавление)
[quote=valenok]Среди всего этого я не заметил одного - что получить то надо..
http://ru.php.net/manual/ru/function.xml-parse.php#87920[/quote]

Не работает. Видно проблема с кодировкой Недовольство, огорчение
(Добавление)
[quote=Джур][/quote]Сумел сделать так:

PHP:
скопировать код в буфер обмена
  1. function pars($xml)
  2. {
  3.   foreach($xml as $k=>$v){
  4.     if(count($v)){
  5.       $a[$k][]= pars($v);
  6.     }else{
  7.       $a[$k][]=iconv("UTF-8","windows-1251",$v);
  8.     }
  9.   }
  10.   return $a;
  11. }
  12. print_r(pars($xml));


На выходе получил массив Улыбка
Теперь тот же профиль: а как распарсить массив?
Как запустить перебор его с тем, чтобы когда элемент массива описывается как:
Array ( [0] => Array ( [Column] => Array ( [0] => металл [1] => учетная цена [2] => тренд )
У меня бы было:
<table><td><tr>металл</td><td>учетная цена</td><td>тренд</td></tr>

Вот полученный результат массива (он меня в ужас приводит):
Array ( [Source] => Array ( [0] => NewsBox ) [Time] => Array ( [0] => 23.01.2009 16:57:18 ) [InfoItem] => Array ( [0] => Array ( [Source] => Array ( [0] => ПРАЙМ ТАСС ) [Time] => Array ( [0] => 23.01.2009 15:54:00 ) [Title] => Array ( [0] => ЦБ повысил с 24/01 учетную цену золота до 923,22 руб дубль ) [Topic] => Array ( [0] => Биржи Банки Фонды [1] => Ситуация и прогнозы ) [Direction] => Array ( [0] => free [1] => Бульон ) [Author] => Array ( [0] => с ) [Keyword] => Array ( [0] => ЗОЛОТО-БАНК [1] => ДРАГМЕТАЛЛЫ-ЦЕНЫ ) [Language] => Array ( [0] => RUS ) [Option] => Array ( [0] => insert [1] => 13188 [2] => 6 [3] => 7 [4] => 18 [5] => 32 [6] => МОСКВА, 23 января. /ПРАЙМ-ТАСС/. ЦБ РФ установил с 24 января следующие учетные цены на драгоценные металлы: ) [Text] => Array ( [0] => МОСКВА, 23 января. /ПРАЙМ-ТАСС/. ЦБ РФ установил с 24 января следующие учетные цены на драгоценные металлы: [1] => Array ( [Data] => Array ( [0] => Array ( [Table] => Array ( [0] => Array ( [Column] => Array ( [0] => металл [1] => учетная цена [2] => тренд ) [Row] => Array ( [0] => Array ( [Cell] => Array ( [0] => золото [1] => 923.22 [2] => +29.26 ) ) [1] => Array ( [Cell] => Array ( [0] => серебро [1] => 11.97 [2] => +0.01 ) ) [2] => Array ( [Cell] => Array ( [0] => платина [1] => 982.44 [2] => +1.74 ) ) [3] => Array ( [Cell] => Array ( [0] => палладий [1] => 193.53 [2] => -1.56 ) ) ) ) ) ) ) ) [2] => * - цены и тренд указаны в рублях за 1 грамм [3] => Данные предоставлены Департаментом внешних и общественных связей ЦБ РФ ) ) ) )

(Отредактировано автором: 29 Января, 2009 - 21:52:00)

 
 Top
Джур
Отправлено: 30 Января, 2009 - 08:51:00
Post Id



Посетитель


Покинул форум
Сообщений всего: 423
Дата рег-ции: Март 2007  


Помог: 0 раз(а)




Ну а вот так...
PHP:
скопировать код в буфер обмена
  1. <?PHP
  2. $xml=simplexml_load_file('1.xml');
  3.  
  4. $echo .= '<h1>'.$xml->infoitem->title.'</h1>';
  5. $echo .= '<h2>'.$xml->time.'</h2>';
  6.  
  7. $echo .= '<p>'.$xml->infoitem->text[0].'</p>';
  8.  
  9. $echo .=  '<table border="1"><tr>';
  10. foreach($xml->infoitem->text[1]->data->table->column as $v) $echo .=  '<th>'.$v.'</th>';
  11. $echo .=  '</tr>';
  12. foreach($xml->infoitem->text[1]->data->table->row as $v){
  13.   $echo .=  '<tr><td>'.$v->cell[0].'</td>';
  14.   $echo .=  '<td>'.$v->cell[1].'</td>';
  15.   $echo .=  '<td>'.$v->cell[2].'</td></tr>';
  16. }
  17. $echo .=  '</table>';
  18.  
  19. $echo .= '<p>'.$xml->infoitem->text[2].'</p>';
  20.  
  21. echo iconv('utf-8','cp1251',$echo);

Подмигивание


-----
Тамбовский каджит тебе товарищ
 
 Top
President
Отправлено: 30 Января, 2009 - 11:59:55
Post Id


Новичок


Покинул форум
Сообщений всего: 18
Дата рег-ции: Янв. 2009  


Помог: 0 раз(а)




уд.

(Отредактировано автором: 31 Января, 2009 - 12:12:30)

 
 Top
President
Отправлено: 30 Января, 2009 - 18:32:02
Post Id


Новичок


Покинул форум
Сообщений всего: 18
Дата рег-ции: Янв. 2009  


Помог: 0 раз(а)




Не. Не работает.
Warning: Invalid argument supplied for foreach() in b.php on line XXX

XXX>> $echo .= '<table border="1"><tr>';
 
 Top
Страниц (2): [1] 2 »
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Программирование на PHP »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB