Дополнительные поля при импорте CommerceML из 1С: разбор b_xml_tree
Зачем выносить обработку в отдельный класс
Стандартный импорт «1С ↔ сайт» кладёт XML во временную структуру b_xml_tree. Пока идёт сессия, дерево сохраняет глубину, имена узлов и значения так же, как в исходном файле — это проще искать нужные элементы через SQL joins по LEFT_MARGIN и RIGHT_MARGIN, чем парсить сырой документ второй раз. Отдельный класс можно вызвать с последнего шага обработчика режима каталога, когда загружается файл похожий на offers.xml, и уже там обновить произвольные свойства торговых предложений через API инфоблока.
Клон компонента и точка входа
Копируют штатный catalog.import.1c, подключают кастомную версию вместо типовой, и перед переключением сессионного состояния на следующий индекс вставляют проверку имени входящего файла. Ниже — иллюстрация проверки: после финального сообщения об импорте для потока предложений выполняется собственная процедура (имена символических кодов свойств заменены на свой пример).
$exchangeDoneMessage = \Bitrix\Main\Localization\Loc::getMessage("CC_BSC1_DEA_DONE");
$exchangeSession["STEP"] = 9;
if (
isset($_GET["filename"])
&& $_GET["filename"] === 'offers.xml'
) {
OffersMarginSync::applyFromStagingTree();
}Важная деталь: индекс девятого шага опирается на ту же машину состояний, что описывают материалы по обмену CommerceML для Битрикс; её стоит сверить на актуальной версии платформы, прежде чем выкладывать на боевой контур.
Чтение дерева и запись свойства по внешнему ключу
Метод сначала убеждается, что в корне блока оффера ожидаемый текст справочника («пакет предложений»), затем собирает пары «внешний идентификатор торгового предложения» — «цифровое значение поля учёта» из вложенных узлов через один запрос со соединением по дереву на глубину предложений. Дальше остаётся найти элемент в каталоге по XML_ID и передать строку в свойство с кодом, например WHOLESALE_MARGIN. Ниже — черновая схема на API ядра с соединением b_xml_tree; глубину уровней и имена узлов подставляют под фактический XML из своей конфигурации 1С.
declare(strict_types=1);
final class OffersMarginSync
{
private const CATALOG_IBLOCK_ID = 10;
public static function applyFromStagingTree(): void
{
$connection = \Bitrix\Main\Application::getConnection();
$snapshot = $connection->query(
"SELECT VALUE FROM b_xml_tree "
. "WHERE DEPTH_LEVEL = 2 AND NAME = 'Наименование'"
)->fetch();
if (!$snapshot || $snapshot["VALUE"] !== 'Пакет предложений') {
return;
}
$rows = $connection->query(
"SELECT idNode.VALUE AS CRM_CODE, qtyNode.VALUE AS MARGIN_PCT"
. " FROM b_xml_tree AS skuNode"
. " INNER JOIN b_xml_tree AS qtyNode ON ("
. " qtyNode.LEFT_MARGIN BETWEEN skuNode.LEFT_MARGIN AND skuNode.RIGHT_MARGIN"
. " AND qtyNode.DEPTH_LEVEL = 6 AND qtyNode.NAME = 'Ставка'"
. ")"
. " INNER JOIN b_xml_tree AS idNode ON ("
. " idNode.LEFT_MARGIN BETWEEN skuNode.LEFT_MARGIN AND skuNode.RIGHT_MARGIN"
. " AND idNode.DEPTH_LEVEL = 4 AND idNode.NAME = 'Ид'"
. ")"
. " WHERE skuNode.DEPTH_LEVEL = 3 AND skuNode.NAME = 'Предложение'"
);
if (!\Bitrix\Main\Loader::includeModule("iblock")) {
return;
}
$order = ["SORT" => "ASC"];
$columns = ["ID", "XML_ID", "NAME"];
$predicate = ["IBLOCK_ID" => self::CATALOG_IBLOCK_ID];
while ($exchangeRow = $rows->fetch()) {
$predicate["=XML_ID"] = $exchangeRow["CRM_CODE"];
$catalogCursor = \CIBlockElement::GetList(
$order,
$predicate,
false,
false,
$columns
);
if ((int)$catalogCursor->SelectedRowsCount() === 0) {
continue;
}
$elementPayload = $catalogCursor->Fetch();
\CIBlockElement::SetPropertyValues(
(int)$elementPayload["ID"],
self::CATALOG_IBLOCK_ID,
$exchangeRow["MARGIN_PCT"],
'WHOLESALE_MARGIN'
);
}
}
}На что посмотреть при отладке
- Уточнять фильтры
=XML_IDи код свойства перед выкладкой — несуществующее свойство даст предупреждение, но не остановит сценарий. - Если нужных строк вообще нет, проще временно сохранить копию проблемной выгрузки и дерево последнего успешного прогона, чтобы переснять имена узлов через выборку
b_xml_treeуже на тестовом стенде.
Не хотите копаться сами?
Починю за 1-3 дня. Без предоплаты — оплата по результату.
15+ лет опыта с 1С-Битрикс · Без предоплаты · 7 дней гарантии