Добрый день, Необходимо обработать XML-файл. С simplexml_load_file разобрался, с выборкой foreach тоже. Однако с одной тонкостью никак не могу справиться, поэтому обращаюсь к профессиональному сообществу. Везде приводятся примеры PHP по обработке, когда в XML текущий элемент имеет определенное количество ПОВТОРЯЮЩИХСЯ дочерних элементов (с повторяющимся тегом!), типа: Код (PHP): <?xml version='1.0' standalone='no' ?> <newxml> <site> <razdely> <news> <name>1</name> <text>1</text> </news> <news> <name>2</name> <text>2</text> </news> <news> <name>3</name> <text>3</text> </news> </razdely> </site> </newxml> Ну и различные вариации, с атрибутами, множеством вложенных тегов и т.д. Чем сложнее XML, тем больше обращений к определенным тегам... А как быть с задачей при обработке XML, если текущий элемент имеет РАЗНЫЕ и ПОВТОРЯЮЩИЕСЯ дочерние элементы, совершенно не понимаю как сделать. Пример XML: Код (PHP): <?xml version='1.0' standalone='no' ?> <newxml> <site> <razdely> <razdel>Раздел 1</razdel> <news> <name>1</name> <text>1</text> </news> <razdel>Раздел 2</razdel> <news> <name>2</name> <text>2</text> </news> <news> <name>3</name> <text>3</text> </news> <razdel>Раздел 3</razdel> <news> <name>4</name> <text>4</text> </news> <news> <name>5</name> <text>5</text> </news> </razdely> </site> </newxml> Естественно когда обрабатываем <news> хотим определить <razdel> и для значений news: 4,5 раздел - будет 3. Вроде бы получилось определить количество элементов массива <razdely>, но потом обращения всё время идут к массивам ->news и ->razdel. Принцип понятен, но решения нет: Код (PHP): <?php $filename='1.xml'; $xml = simplexml_load_file($filename); foreach ($xml->razdely as $razdely) { echo count($razdely); } ?> Вроде бы просто, но истина где-то там... Спасибо! Подсказка от модератора: Любой код или текст конфигурации пишите между тегом [code=php] и [/code]. Используйте отступы в коде для форматирования текста. Это помогает быстрее понять вас, увеличивает шанс на получение ответа. Что выделять? Например: PHP, HTML, CSS, JavaScript, SQL, XML, .htaccess, ini, регулярные выражения, код шаблонизаторов, любая другая разметка, результаты array/object dump и т. д.
Некорректно составлен XML, где вы такой взяли? При такой структуре - только руками. Чтоб можно было автоматом, должно быть Код (PHP): <xml> <razdely> <razdel id='1'> <news>1</news> <news>2</news> </razdel> </razdely> </xml>
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 это уже перебор, хотя и такое устроит.
Чтоб было так, как вы хотите, структура должна быть такая, как я показал. Покажите конкретный xml, который вам нужно обработать. Хотя, в вашем случае можно ещё использовать https://php.net/manual/ru/book.xml.php - там XML не преобразуется в структуру в памяти, и вы сможете сами следить за ходом разбора. Но сколько я с XML встречался, там новости в разделы или что-то подобное вкладывается как я показал. Ну или ещё вариант, например, в Яндекс.Маректе Код (PHP): .... <category id=25>Имя категории</category> ... <product id=74> <category>25</category> </product> ...
Re: SimpleXML у текущего эл. много разных и повторяющихся др Оригинал не могу выложить, он огромен и в какой-то степени конфиденциален. Поверьте на слово, выглядит принципиально так. Возможно это ошибка программистов этого сайта, а может ещё какие-то причины, но факт остается фактом. Сайт сам создает такой XML и при этом сам же его обрабатывает, если загрузить этот документ.
Re: SimpleXML у текущего эл. много Разных и Повторяющихся др Покажите выдержку, конфиденциальные данные замените на XXX, в чём проблема? А принципиально - я дал вам ссылку на потоковый парсер XML, он здесь более уместен будет, если всё как вы говорите один в один
Хорошо спасибо! Я начинал изучение с парсеров XML. Эти "молекулы" меня неделю назад добивали с ними провозился, в итоге simplexml обнаружил тоже провозился, но был очень счастлив, когда со всем разобрался, уже скрипт прописал, в базу данных добавляю, но не могу связь установить между <news> и <razdel>. Я обновил коды в теме, такого плана xml. Попробую если других вариантов нет, но честно говоря не очень хотелось бы. Мне кажется решить вопрос обработки массива $razdely, который получается обращением foreach ($xml->razdely as $razdely всё-таки проще: Код (PHP): <razdely> <razdel>Раздел 1</razdel> <news> <name>1</name> <text>1</text> </news> <razdel>Раздел 2</razdel> <news> <name>2</name> <text>2</text> </news> <news> <name>3</name> <text>3</text> </news> <razdel>Раздел 3</razdel> <news> <name>4</name> <text>4</text> </news> <news> <name>5</name> <text>5</text> </news> </razdely> Возможно его как-то обработать по-штучно типа $razdely и обратиться к данным из тегов <news> и <razdel> (через единый индекс, чтобы связь установить) или он будет всё время возвращать отдельные массивы $news и $razdel со своими индексами? Подсказка от модератора: Любой код или текст конфигурации пишите между тегом [code=php] и [/code]. Используйте отступы в коде для форматирования текста. Это помогает быстрее понять вас, увеличивает шанс на получение ответа. Что выделять? Например: PHP, HTML, CSS, JavaScript, SQL, XML, .htaccess, ini, регулярные выражения, код шаблонизаторов, любая другая разметка, результаты array/object dump и т. д.
Re: SimpleXML у текущего эл. много Разных и Повторяющихся др При такой структуре foreach ($xml->razdely as $razdely вам не поможет. Вы никак не свяжите раздел с новостями. Если там, конечно, нету каких-нибудь атрибутов, которые вы тут не публикуете. Если всё так печально, то только потоковый парсинг с достаточно сложным алгоритмом. Возможно, ещё DOMDocument вас подойдёт. Там можно перебирать все узлы подряд через foreach. Вот, посмотрите. http://phpfiddle.org/lite/code/futa-73zk
Re: SimpleXML у текущего эл. много Разных и Повторяющихся др Так где ваш код, который не работает? Код (Text): foreach($xml->site->razdely as $name=>$element) { } И вперед Добавлено спустя 1 минуту 25 секунд: Re: SimpleXML у текущего эл. много Разных и Повторяющихся других Да с чего бы это. Иерархии нет, конечно, но есть порядок детей, заданный в XML. С ним можно работать.
Re: SimpleXML у текущего эл. много Разных и Повторяющихся др Хотя да, можно и в SimpleXML, но тогде через https://php.net/manual/ro/simplexmlelement.children.php, и проверять, кто очередной детёнышь - раздел или новость
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 и прочие, но не выводит... Похоже, дальше придется штудировать документацию.
У.... alex255, ну хоть зачатки алгоритмического мышления же должны быть у программиста.... http://phpfiddle.org/lite/code/rk0w-zh38 Добавлено спустя 1 минуту 46 секунд: Re: SimpleXML у текущего эл. много Разных и Повторяющихся других Немного там опечатался, не найдёте ведь... Код (PHP): <?php $XML = <<<XML <razdely> <razdel>Раздел 1</razdel> <news> <name>1</name> <text>1</text> </news> <razdel>Раздел 2</razdel> <news> <name>2</name> <text>2</text> </news> <news> <name>3</name> <text>3</text> </news> <razdel>Раздел 3</razdel> <news> <name>4</name> <text>4</text> </news> <news> <name>5</name> <text>5</text> </news> </razdely> XML; $xml = simplexml_load_string($XML); $razdel = ""; foreach ($xml->children() as $n) { if ($n->getName() === "razdel") $razdel = (string) $n; elseif ($n->getName() === "news") { echo "Новость раздела $razdel " . $n->text . "<br>"; } } ?> Дальше догадаетесь?
Re: SimpleXML у текущего эл. много Разных и Повторяющихся др Спасибо! Пойду проверять, но подозреваю, что всё получится, getName() мне и не хватало, не доводилось с ней работать. Ну логика-то вроде у меня была, знаний не хватало)) Это хобби скорее, отнимающее кучу времени, но доставляющее удовольствие, когда всё получается. Спасибо!
Даже и ещё проще, MiksIr прав. Код (PHP): <?php $XML = <<<XML <razdely> <razdel>Раздел 1</razdel> <news> <name>1</name> <text>1</text> </news> <razdel>Раздел 2</razdel> <news> <name>2</name> <text>2</text> </news> <news> <name>3</name> <text>3</text> </news> <razdel>Раздел 3</razdel> <news> <name>4</name> <text>4</text> </news> <news> <name>5</name> <text>5</text> </news> </razdely> XML; $xml = simplexml_load_string($XML); $razdel = ""; foreach ($xml as $t => $n) { if ($t === "razdel") $razdel = (string) $n; elseif ($t === "news") { echo "Новость раздела $razdel " . $n . "<br>"; } } ?> Век живи, век учись. MiksIr, спасибо!
Re: SimpleXML у текущего эл. много Разных и Повторяющихся др Блин, в тексте ответа MiksIr, строчку с кодом и не заметил, пролистал, решил, что он меня процитировал... Умной мысли, основанной на знаниях мне и не хватало. Спасибо!