За последние 24 часа нас посетили 74263 программиста и 10147 роботов. Сейчас ищут 2250 программистов ...

SimpleXML у текущего эл. много Разных и Повторяющихся других

Тема в разделе "PHP для новичков", создана пользователем alex255, 3 фев 2016.

  1. alex255

    alex255 Новичок

    С нами с:
    3 фев 2016
    Сообщения:
    7
    Симпатии:
    0
    Добрый день,

    Необходимо обработать XML-файл. С simplexml_load_file разобрался, с выборкой foreach тоже. Однако с одной тонкостью никак не могу справиться, поэтому обращаюсь к профессиональному сообществу.

    Везде приводятся примеры PHP по обработке, когда в XML текущий элемент имеет определенное количество ПОВТОРЯЮЩИХСЯ дочерних элементов (с повторяющимся тегом!), типа:
    Код (PHP):
    1. <?xml version='1.0' standalone='no' ?>
    2. <newxml>
    3.    <site>
    4.       <razdely>
    5.          <news>
    6.             <name>1</name>
    7.             <text>1</text>
    8.          </news>
    9.          <news>
    10.             <name>2</name>
    11.             <text>2</text>
    12.          </news>
    13.          <news>
    14.             <name>3</name>
    15.             <text>3</text>
    16.          </news>         
    17.       </razdely>
    18.    </site>
    19. </newxml>
    Ну и различные вариации, с атрибутами, множеством вложенных тегов и т.д. Чем сложнее XML, тем больше обращений к определенным тегам... А как быть с задачей при обработке XML, если текущий элемент имеет РАЗНЫЕ и ПОВТОРЯЮЩИЕСЯ дочерние элементы, совершенно не понимаю как сделать. Пример XML:
    Код (PHP):
    1. <?xml version='1.0' standalone='no' ?>
    2. <newxml>
    3.    <site>
    4.       <razdely>
    5.          <razdel>Раздел 1</razdel>
    6.          <news>
    7.             <name>1</name>
    8.             <text>1</text>
    9.          </news>
    10.          <razdel>Раздел 2</razdel>
    11.          <news>
    12.             <name>2</name>
    13.             <text>2</text>
    14.          </news>
    15.          <news>
    16.             <name>3</name>
    17.             <text>3</text>
    18.          </news>         
    19.          <razdel>Раздел 3</razdel>
    20.          <news>
    21.             <name>4</name>
    22.             <text>4</text>
    23.          </news>
    24.          <news>
    25.             <name>5</name>
    26.             <text>5</text>
    27.          </news>         
    28.       </razdely>
    29.    </site>
    30. </newxml>
    Естественно когда обрабатываем <news> хотим определить <razdel> и для значений news: 4,5 раздел - будет 3.
    Вроде бы получилось определить количество элементов массива <razdely>, но потом обращения всё время идут к массивам ->news и ->razdel.

    Принцип понятен, но решения нет:
    Код (PHP):
    1. <?php
    2. $filename='1.xml';
    3. $xml = simplexml_load_file($filename);
    4.  
    5. foreach ($xml->razdely as $razdely) 
    6. {
    7. echo count($razdely);
    8. }
    9.  
    10. ?>
    Вроде бы просто, но истина где-то там...

    Спасибо!

    Подсказка от модератора:
    Любой код или текст конфигурации пишите между тегом [code=php] и [/code].
    Используйте отступы в коде для форматирования текста.
    Это помогает быстрее понять вас, увеличивает шанс на получение ответа.
    Что выделять? Например: PHP, HTML, CSS, JavaScript, SQL, XML, .htaccess, ini, регулярные выражения, код шаблонизаторов, любая другая разметка, результаты array/object dump и т. д.
     
  2. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.497
    Симпатии:
    1.726
    Некорректно составлен XML, где вы такой взяли? При такой структуре - только руками. Чтоб можно было автоматом, должно быть
    Код (PHP):
    1. <xml>
    2.     <razdely>
    3.         <razdel id='1'>
    4.             <news>1</news> 
    5.             <news>2</news>
    6.        </razdel>
    7.         
    8.     </razdely>
    9. </xml>
    10.  
     
  3. alex255

    alex255 Новичок

    С нами с:
    3 фев 2016
    Сообщения:
    7
    Симпатии:
    0
    Re: SimpleXML у текущего эл. много разных и повторяющихся др

    Данный пример выдуман, но такого плана XML один ресурс использует и как-то обрабатывает. Причем в <news></news> там всё нормально. Но связи с <razdel></razdel>, в моем понимании нет.

    У меня вот какая идея есть: нужно обработать элемент <razdely>, количество элементов в нём определено count($razdely). А дальше нужно обработать каждый элемент и сравнить, что-то типа IF($xxx=='<razdel>') и IF($xxx=='<news>'), то какой-то индекс ввести... короче создать новый массив в котором если тег <razdel> - будет 0, а если <news> - условно 1. А потом уже при обработке данных foreach ($xml->razdely->news as $news) обращаться к этому массиву чтобы взять id тега <razdel>. Но не могу реализовать.

    Пытался файл также прочитать построчно и сравнить опять же строчки, ну там тоже что-то запутался. Да и наверное использовать ещё и file() вместе с simplexml_load_file это уже перебор, хотя и такое устроит.
     
  4. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.497
    Симпатии:
    1.726
    Чтоб было так, как вы хотите, структура должна быть такая, как я показал. Покажите конкретный xml, который вам нужно обработать. Хотя, в вашем случае можно ещё использовать https://php.net/manual/ru/book.xml.php - там XML не преобразуется в структуру в памяти, и вы сможете сами следить за ходом разбора. Но сколько я с XML встречался, там новости в разделы или что-то подобное вкладывается как я показал. Ну или ещё вариант, например, в Яндекс.Маректе
    Код (PHP):
    1. ....
    2. <category id=25>Имя категории</category>
    3. ...
    4. <product id=74>
    5.     <category>25</category>
    6. </product>
    7. ...
    8.  
     
  5. alex255

    alex255 Новичок

    С нами с:
    3 фев 2016
    Сообщения:
    7
    Симпатии:
    0
    Re: SimpleXML у текущего эл. много разных и повторяющихся др

    Оригинал не могу выложить, он огромен и в какой-то степени конфиденциален. Поверьте на слово, выглядит принципиально так. Возможно это ошибка программистов этого сайта, а может ещё какие-то причины, но факт остается фактом. Сайт сам создает такой XML и при этом сам же его обрабатывает, если загрузить этот документ.
     
  6. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.497
    Симпатии:
    1.726
    Re: SimpleXML у текущего эл. много Разных и Повторяющихся др

    Покажите выдержку, конфиденциальные данные замените на XXX, в чём проблема? А принципиально - я дал вам ссылку на потоковый парсер XML, он здесь более уместен будет, если всё как вы говорите один в один
     
  7. alex255

    alex255 Новичок

    С нами с:
    3 фев 2016
    Сообщения:
    7
    Симпатии:
    0
    Хорошо спасибо! Я начинал изучение с парсеров XML. Эти "молекулы" меня неделю назад добивали с ними провозился, в итоге simplexml обнаружил тоже провозился, но был очень счастлив, когда со всем разобрался, уже скрипт прописал, в базу данных добавляю, но не могу связь установить между <news> и <razdel>. Я обновил коды в теме, такого плана xml. Попробую если других вариантов нет, но честно говоря не очень хотелось бы.

    Мне кажется решить вопрос обработки массива $razdely, который получается обращением foreach ($xml->razdely as $razdely всё-таки проще:
    Код (PHP):
    1. <razdely>
    2.          <razdel>Раздел 1</razdel>
    3.          <news>
    4.             <name>1</name>
    5.             <text>1</text>
    6.          </news>
    7.          <razdel>Раздел 2</razdel>
    8.          <news>
    9.             <name>2</name>
    10.             <text>2</text>
    11.          </news>
    12.          <news>
    13.             <name>3</name>
    14.             <text>3</text>
    15.          </news>       
    16.          <razdel>Раздел 3</razdel>
    17.          <news>
    18.             <name>4</name>
    19.             <text>4</text>
    20.          </news>
    21.          <news>
    22.             <name>5</name>
    23.             <text>5</text>
    24.          </news>       
    25. </razdely> 
    Возможно его как-то обработать по-штучно типа $razdely и обратиться к данным из тегов <news> и <razdel> (через единый индекс, чтобы связь установить) или он будет всё время возвращать отдельные массивы $news и $razdel со своими индексами?

    Подсказка от модератора:
    Любой код или текст конфигурации пишите между тегом [code=php] и [/code].
    Используйте отступы в коде для форматирования текста.
    Это помогает быстрее понять вас, увеличивает шанс на получение ответа.
    Что выделять? Например: PHP, HTML, CSS, JavaScript, SQL, XML, .htaccess, ini, регулярные выражения, код шаблонизаторов, любая другая разметка, результаты array/object dump и т. д.
     
  8. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.497
    Симпатии:
    1.726
    Re: SimpleXML у текущего эл. много Разных и Повторяющихся др

    При такой структуре foreach ($xml->razdely as $razdely вам не поможет. Вы никак не свяжите раздел с новостями. Если там, конечно, нету каких-нибудь атрибутов, которые вы тут не публикуете. Если всё так печально, то только потоковый парсинг с достаточно сложным алгоритмом. Возможно, ещё DOMDocument вас подойдёт. Там можно перебирать все узлы подряд через foreach. Вот, посмотрите. http://phpfiddle.org/lite/code/futa-73zk
     
  9. MiksIr

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

    С нами с:
    29 ноя 2006
    Сообщения:
    2.333
    Симпатии:
    44
    Re: SimpleXML у текущего эл. много Разных и Повторяющихся др

    Так где ваш код, который не работает?
    Код (Text):
    1. foreach($xml->site->razdely as $name=>$element) {
    2.  }
    И вперед

    Добавлено спустя 1 минуту 25 секунд:
    Re: SimpleXML у текущего эл. много Разных и Повторяющихся других
    Да с чего бы это. Иерархии нет, конечно, но есть порядок детей, заданный в XML. С ним можно работать.
     
  10. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.497
    Симпатии:
    1.726
    Re: SimpleXML у текущего эл. много Разных и Повторяющихся др

    Хотя да, можно и в SimpleXML, но тогде через https://php.net/manual/ro/simplexmlelement.children.php, и проверять, кто очередной детёнышь - раздел или новость
     
  11. alex255

    alex255 Новичок

    С нами с:
    3 фев 2016
    Сообщения:
    7
    Симпатии:
    0
    Re: SimpleXML у текущего эл. много Разных и Повторяющихся др

    А какой код-то? Я уж всё что мог привел, как к каждому из массивов обратиться умею, а как их связать незнаю. Идею тоже высказал, если можно так сделать, подскажите как. По документации искал, думал XPath использовать, children, пока с ними не разобрался, но посмотрев примеры решил вряд ли подойдет. Что мне даст, что они все принадлежат элементу <razdely>? Это итак известно. Определенную надежду возложил на SimpleXMLElement::count - Считает количество дочерних элементов у текущего элемента. Собственно поэтому и тему создал, вдруг кто сориентирует. Он-то посчитал количество элементов в <razdely>, а что дальше можно с ними сделать, кроме как в примере число детей вывести, как обратиться к i-му элементу... не понимаю.

    Индексов нету и атрибутов никаких. Получается, как вариант можно к номеру строки привязаться, т.е. читать построчно и увидев первый раз тег <razdel> присвоить 0 какое-то значение, а у <news> уже своё какое-то и уже сформировать. т.е. index каждой <news> мы знаем когда foreach($xml->site->razdely->news as $news) обрабатываем, но нужен ещё массив в котором будут элементы id новостей и разделы пересекаться. Т.е. мы знаем структуру, незнаем количество каждого элемента, знаем, что последовательно идут. Мне кажется - это несложная задача, хотя честно я уж больше недели с ней вожусь. Пытался построчно прочитать, используя file(), а потом сравнить c тегами If($text=='<razsel'), используя strpos и прочие, но не выводит...

    Похоже, дальше придется штудировать документацию.
     
  12. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.497
    Симпатии:
    1.726
    У.... alex255, ну хоть зачатки алгоритмического мышления же должны быть у программиста.... http://phpfiddle.org/lite/code/rk0w-zh38

    Добавлено спустя 1 минуту 46 секунд:
    Re: SimpleXML у текущего эл. много Разных и Повторяющихся других
    Немного там опечатался, не найдёте ведь...
    Код (PHP):
    1. <?php
    2. $XML = <<<XML
    3. <razdely>
    4.          <razdel>Раздел 1</razdel>
    5.          <news>
    6.             <name>1</name>
    7.             <text>1</text>
    8.          </news>
    9.          <razdel>Раздел 2</razdel>
    10.          <news>
    11.             <name>2</name>
    12.             <text>2</text>
    13.          </news>
    14.          <news>
    15.             <name>3</name>
    16.             <text>3</text>
    17.          </news>       
    18.          <razdel>Раздел 3</razdel>
    19.          <news>
    20.             <name>4</name>
    21.             <text>4</text>
    22.          </news>
    23.          <news>
    24.             <name>5</name>
    25.             <text>5</text>
    26.          </news>       
    27. </razdely>
    28. XML;
    29.  
    30. $xml = simplexml_load_string($XML);
    31. $razdel = "";
    32.  
    33. foreach ($xml->children() as $n) {
    34.     if ($n->getName() === "razdel")
    35.         $razdel = (string) $n;
    36.     elseif ($n->getName() === "news") {
    37.         echo "Новость раздела $razdel " . $n->text . "<br>";
    38.     }
    39. }
    40. ?>
    Дальше догадаетесь?
     
  13. alex255

    alex255 Новичок

    С нами с:
    3 фев 2016
    Сообщения:
    7
    Симпатии:
    0
    Re: SimpleXML у текущего эл. много Разных и Повторяющихся др

    Спасибо! Пойду проверять, но подозреваю, что всё получится, getName() мне и не хватало, не доводилось с ней работать. Ну логика-то вроде у меня была, знаний не хватало)) Это хобби скорее, отнимающее кучу времени, но доставляющее удовольствие, когда всё получается. Спасибо!
     
  14. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.497
    Симпатии:
    1.726
    Даже и ещё проще, MiksIr прав.
    Код (PHP):
    1. <?php
    2. $XML = <<<XML
    3. <razdely>
    4.          <razdel>Раздел 1</razdel>
    5.          <news>
    6.             <name>1</name>
    7.             <text>1</text>
    8.          </news>
    9.          <razdel>Раздел 2</razdel>
    10.          <news>
    11.             <name>2</name>
    12.             <text>2</text>
    13.          </news>
    14.          <news>
    15.             <name>3</name>
    16.             <text>3</text>
    17.          </news>       
    18.          <razdel>Раздел 3</razdel>
    19.          <news>
    20.             <name>4</name>
    21.             <text>4</text>
    22.          </news>
    23.          <news>
    24.             <name>5</name>
    25.             <text>5</text>
    26.          </news>       
    27. </razdely>
    28. XML;
    29.  
    30. $xml = simplexml_load_string($XML);
    31. $razdel = "";
    32.  
    33. foreach ($xml as $t => $n) {
    34.     if ($t === "razdel")
    35.         $razdel = (string) $n;
    36.     elseif ($t === "news") {
    37.         echo "Новость раздела $razdel " . $n . "<br>";
    38.     }
    39. }
    40. ?>
    Век живи, век учись. MiksIr, спасибо!
     
  15. alex255

    alex255 Новичок

    С нами с:
    3 фев 2016
    Сообщения:
    7
    Симпатии:
    0
    Re: SimpleXML у текущего эл. много Разных и Повторяющихся др

    Блин, в тексте ответа MiksIr, строчку с кодом и не заметил, пролистал, решил, что он меня процитировал... Умной мысли, основанной на знаниях мне и не хватало. Спасибо!