Как правильно обработать дочерние элементы с одинаковыми названиями?

ABabiy

Новичок
Исправляюсь

PHP:
/** Работаем с OFFER-ами **/

foreach ($xml_slave->xpath('//offer') as $key => $item) {

    $param      = $item->param; // param OFFERa slave
    $categoryId = $item->categoryId; // categoryId OFFERa slave


    //TODO-sasha Если НЕ найден артикул из проверяемого файла в мастере то переносим в файл-результат объект offer, его атрибуты, а также дочерние элементы. Важно!!! При копировании заменяем id категории на значение из мастера

    if (sizeof(search_offer($xml_master, $param)) == 0) {

        $offer = $xml3->shop[0]->offers->addChild('offer');

        $offer_attributes = element_attributes($item->attributes());

        /** Добавляем аттрибуты к offer **/

        foreach ($offer_attributes as $key_a => $item_a) {
            $offer->addAttribute($key_a, $item_a);
        }

        /** Работа с элементами OFFER-a **/

        foreach ($item as $key_off => $off) { //перебираем элементы OFFER-a


            $offer->addChild($key_off, $off);


            /** Работа с элементом category **/
       

            /** Добавляем аттрибуты к дочерним элементам offer **/

            $offer->addChild($key_off, $off);

            $offer->$key_off->addAttribute('ddd', 'eee');
           
        }
    }
}
 

WMix

герр M:)ller
Партнер клуба
PHP:
        foreach ($item as $key_off => $off) {
            $offer->addChild($key_off, $off);

            $offer->addChild($key_off, $off); // повтор?? теперь есть минимум 2 элемента $key_off
            $offer->$key_off->addAttribute('ddd', 'eee'); // и в какой из них мы добавляем?
        }
PHP:
$child = $offer->addChild($key_off, $off);
$child->addAttribute('тест', 'тест1');
 

ABabiy

Новичок
PHP:
        foreach ($item as $key_off => $off) {
            $offer->addChild($key_off, $off);

            $offer->addChild($key_off, $off); // повтор?? теперь есть минимум 2 элемента $key_off
            $offer->$key_off->addAttribute('ddd', 'eee'); // и в какой из них мы добавляем?
        }
Там проверка была - я при подготовке кода убрал, а строка осталась.
Потому 2 раза. Очепятка :)
Я немного запутался - и опечатку сделал.
Работает - спасибо большое!
 

ABabiy

Новичок
Доброй ночи.
При тестировании вылезла та же проблема:

Это в исходнике:
Код:
<param code="article" name="Артикул">a_chl_sam_ga3_2016_svw_cvr_wht</param>
<param code="867549" name="Цвет">White - Белый</param>
Цикл копирования в новый файл:
Код:
foreach ($attributes_by_element as $key_atr => $attr) {
                    $child->addAttribute($key_atr, $attr);
                }
И тут получается затык:
при чтении следующего элемента param и его атрибутов всё ок, вот только таких элементов несколько и как их идентифицировать?
Создали 1param и к нему атрибуты циклом
Создали 2 парам и к нему атрибуты второго(!!!) элемента param.
По факту атрибуты первого снова записываются
Код:
<param code="article" name="Артикул">a_chl_sam_ga3_2016_svw_cvr_wht</param>
<param code="article" name="Артикул">White - Белый</param>
 

ABabiy

Новичок
Вот вся функция

PHP:
/** Создаёт результирующий XML файл из мастера и подчинённого файлов.**/

function create_res_xml($xml_master, $xml_slave, $xml_res) {

    global $path_cat1;
    global $path_cat2;
    global $path_cat3;
    global $xml2;
    global $xml3;
    global $offer;

    /** Работаем с OFFER-ами **/

    foreach ($xml_slave->xpath('//offer') as $key => $item) {

        $param      = $item->param; // param OFFERa slave
        $categoryId = $item->categoryId; // categoryId OFFERa slave


        //TODO-sasha Если НЕ найден артикул из проверяемого файла в мастере то переносим в файл-результат объект offer, его атрибуты, а также дочерние элементы. Важно!!! При копировании заменяем id категории на значение из мастера

        if (sizeof(search_offer($xml_master, $param)) == 0) {

            $offer = $xml3->shop[0]->offers->addChild('offer');

            $offer_attributes = element_attributes($item->attributes());


            /** Добавляем атрибуты к offer **/

            foreach ($offer_attributes as $key_a => $item_a) {
                $offer->addAttribute($key_a, $item_a);
            }

            /** Работа с элементами OFFER-a **/

            foreach ($item as $key_off => $off) { //перебираем элементы OFFER-a

                /** Работа с элементом category **/

                if ($key_off == strval('categoryId')) {

                    $name_cat_slave = category_name_by_id($path_cat2, strval($off));

                    $id_cat_master = category_id_by_name($path_cat1, strval($name_cat_slave));

                    if (isset($id_cat_master)) {
                        //TODO-sasha Получили id в мастере, соответствующее текущему значению id slave
                        $child = $offer->addChild($key_off, strval($id_cat_master));
                    } else {
                        //TODO-sasha Получили id slave, поскольку в мастере нет похожей категории
                        $child = $offer->addChild($key_off, strval($off));
                    }                  

                } else {
                    $child = $offer->addChild($key_off, strval($off));
                }

                /** Добавляем атрибуты к дочерним элементам OFFER-а **/

                $attributes_by_element = $xml2->shop[0]->offers[0]->offer[$key]->$key_off->attributes();

                foreach ($attributes_by_element as $key_atr => $attr) {
                    $child->addAttribute($key_atr, $attr);
                }
            }
        }
    }

} // function create_res_xml
 

WMix

герр M:)ller
Партнер клуба
если чесно, мне сложно понять, если у тебя в голове не складывается что есть
PHP:
$xml2->shop[0]->offers[0]->offer[$key]->$key_off->attributes();
то у меня тем более. есть такие функции print_r, var dump
дампи, разбирайся.
 

ABabiy

Новичок
если чесно, мне сложно понять, если у тебя в голове не складывается что есть
PHP:
$xml2->shop[0]->offers[0]->offer[$key]->$key_off->attributes();
то у меня тем более. есть такие функции print_r, var dump
дампи, разбирайся.
Постоянно пользуюсь данными функциями.
В скайпе объяснил бы быстрее. Я к менторам обратился - пасуют...
 

WMix

герр M:)ller
Партнер клуба
Постоянно пользуюсь данными функциями
ну тожда должен четко понимать, что
Код:
$xml2->shop[0]->offers[0]->offer[$key]->$key_off
является массивом элементов (на момент ошибки), что это необходимо было учесть
 

ABabiy

Новичок
ну тожда должен четко понимать, что
Код:
$xml2->shop[0]->offers[0]->offer[$key]->$key_off
является массивом элементов (на момент ошибки), что это необходимо было учесть
$key_off и перебирается - это массив элементов (названия элементов дочерних) И у них атрибуты считываются
 

ABabiy

Новичок
Код:
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
  <stores>
    <store uid="111" name="444"/>
    <store uid="222" name="555"/>
    <store uid="333" name="666"/>
  </stores>
</catalog>
Не получается.
Не могли бы Вы рабочий код скинуть (пример)
Вот такой файл file1.xml скопировать поэлементно в файл file2.xml со всеми атрибутами.
Дальше я смог бы транслировать на свою работу ваше решение.
Спасибо!
 

WMix

герр M:)ller
Партнер клуба
PHP:
function copyChildren($src, $dstn){
  foreach($src->children() as $child){
    $tmp = $dstn->addChild($child->getName());
    foreach($child->attributes() as $name => $value){
      $tmp->addAttribute($name, $value);
    }
    copyChildren($child, $tmp);
  }
}
PHP:
$xml = simplexml_load_string(file_get_contents('file1.xml'));
$xmlCopy = new SimpleXMLElement('<catalog />');
copyChildren($xml, $xmlCopy);
file_put_contents('file2.xml', $xmlCopy->asXML() );
 

ABabiy

Новичок
PHP:
function copyChildren($src, $dstn){
  foreach($src->children() as $child){
    $tmp = $dstn->addChild($child->getName());
    foreach($child->attributes() as $name => $value){
      $tmp->addAttribute($name, $value);
    }
    copyChildren($child, $tmp);
  }
}
PHP:
$xml = simplexml_load_string(file_get_contents('file1.xml'));
$xmlCopy = new SimpleXMLElement('<catalog />');
copyChildren($xml, $xmlCopy);
file_put_contents('file2.xml', $xmlCopy->asXML() );
Да, Ваш пример работает. Спасибо огромное. Пробую у себя реализовать!
 

WMix

герр M:)ller
Партнер клуба
согласен, и функцию задом наперед переписать (про корневые аттрибуты забыл)

PHP:
function xmlCopy($src, $dstn){
  foreach($src->attributes() as $name => $value){
    $dstn->addAttribute($name, $value);
  }
  foreach($src->children() as $child){
    xmlCopy($child, $dstn->addChild($child->getName()));
  }
  return $dstn;
}

file_put_contents(
    'file2.xml',
    xmlCopy(
        simplexml_load_file('file1.xml'),
        new SimpleXMLElement('<catalog-copy />')
    )->asXML()
);
 
Сверху