При разработке механизмов выгрузки данных из «1С:Предприятие 7.7» в формат YML (Yandex Market Language) программисты часто сталкиваются с техническим ограничением стандартной библиотеки MSXML2.DOMDocument. Основная сложность заключается в необходимости вставки второй строки файла: . В этой статье мы подробно разберем, почему стандартные методы создания узлов здесь не работают, и рассмотрим три эффективных способа решения этой задачи.
Проанализируем ситуацию: объектная модель DOM (Document Object Model) подразумевает, что DOCTYPE является узлом типа NODE_DOCUMENT_TYPE. Однако в реализации MSXML (версий 4.0 и 6.0) программное создание этого узла «с нуля» через метод createNode часто заблокировано или возвращает ошибку ReadOnly. Это связано с тем, что определение типа документа должно присутствовать в момент инициализации парсера, а не добавляться в уже построенное дерево. Попытка вставить эту строку как комментарий приведет к невалидности файла, так как Яндекс ожидает именно декларацию, а не .
Это наиболее элегантный программный метод. Вместо того чтобы создавать пустой документ и пытаться программно «впихнуть» туда заголовок, мы проинициализируем объект MSXML2.DOMDocument готовой строкой-скелетом. Рассмотрим пример кода:
// Создаем объект DOM
XML_DOM = СоздатьОбъект("MSXML2.DOMDocument.4.0");
// Формируем строку-заготовку с XML-декларацией и DOCTYPE
HeaderString = "
|
| ";
// Загружаем заготовку в объект
XML_DOM.loadXML(HeaderString);
// Теперь мы можем обращаться к корневому узлу и наполнять его
Root = XML_DOM.documentElement;
Root.setAttribute("date", "2023-10-27T12:00:00");
// Пример добавления вложенного узла
ShopNode = XML_DOM.createElement("shop");
Root.appendChild(ShopNode);
Разберем, почему это работает. Метод loadXML заставляет парсер сразу обработать структуру документа. Поскольку DOCTYPE указан в строке загрузки, MSXML корректно принимает его и сохраняет в дереве объектов. При последующем вызове метода save() вся структура будет выгружена в файл в неизменном виде.
Если структура вашего кода уже написана и переделывать инициализацию через loadXML сложно, воспользуемся методом замены. Проанализируем алгоритм: мы создаем в XML обычный узел с уникальным именем, который не встречается в спецификации, а перед сохранением файла превращаем его в нужную нам строку текста.
<DOCTYPE_STUB />."<DOCTYPE_STUB />" на требуемую декларацию <!DOCTYPE ...>.
// Предположим, XML уже сформирован в объекте XML_DOM
// Получаем текст XML
FullText = XML_DOM.xml;
// Выполняем подстановку
TargetDOCTYPE = "";
FullText = СтрЗаменить(FullText, " ", TargetDOCTYPE);
// Сохраняем результат через объект "Текст" или ADODB.Stream
Текст = СоздатьОбъект("Текст");
Текст.ДобавитьСтроку(FullText);
Текст.Записать(ПутьКФайлу);
Выясним причину, по которой опытные разработчики «клюшек» часто отказываются от DOM в пользу прямой записи текста. Платформа 1С 7.7 ограничена в ресурсах памяти, а объект MSXML2.DOMDocument строит всё дерево в оперативной памяти. Если в вашем прайсе 50 000 товаров, выгрузка может занять вечность или завершиться ошибкой Out of memory.
Рассмотрим по шагам формирование файла через объект Текст. Это позволяет нам полностью контролировать каждую строку, включая злополучный DOCTYPE.
Текст = СоздатьОбъект("Текст");
Текст.ДобавитьСтроку("");
Текст.ДобавитьСтроку("");
Текст.ДобавитьСтроку("");
// В цикле по товарам
ВыбратьСтроки();
Пока ПолучитьСтроку() = 1 Цикл
// Важно: экранируем спецсимволы вручную
ИмяТовара = ЭкранироватьXML(Товар.Наименование);
Текст.ДобавитьСтроку(" ");
Текст.ДобавитьСтроку(" " + ИмяТовара + " ");
Текст.ДобавитьСтроку(" ");
КонецЦикла;
Текст.ДобавитьСтроку(" ");
Текст.Записать(КаталогИмяФайла);
Работа с YML в 1С 7.7 требует особого внимания к двум моментам:
1. Кодировка UTF-8. Стандартный объект Текст в 1С 7.7 сохраняет файлы в кодировке Windows-1251 (ANSI). Если вы используете прямой текстовый вывод, файл нужно перекодировать в UTF-8. Лучше всего использовать для этого объект ADODB.Stream, который позволяет записывать данные сразу в нужной кодировке без создания временных файлов.
2. Экранирование символов. Если при использовании DOMDocument объект сам заменяет & на &, то при ручной сборке текста вы обязаны делать это самостоятельно. В противном случае валидатор Яндекс.Маркета отклонит файл. Необходимо обрабатывать 5 символов:
& заменяем на &< заменяем на <> заменяем на >" заменяем на "' заменяем на 'Для решения задачи в 1С 7.7 мы рекомендуем либо использовать loadXML для небольших файлов, либо переходить на ручную сборку текста с использованием ADODB.Stream для крупных выгрузок. Это обеспечит максимальную производительность и гибкость при формировании нестандартных заголовков, таких как DOCTYPE.