При разработке механизмов выгрузки данных из 1С в формат XML (особенно для Яндекс.Маркета — формат YML) разработчики часто сталкиваются с ошибкой «Недопустимое имя XML». Эта проблема возникает на этапе вызова методов объекта ЗаписьXML. В этой статье мы подробно разберем, почему возникает эта ошибка, как правильно формировать структуру файла и какие методы платформы 1С для этого предназначены.
Давайте проанализируем ситуацию. Ошибка «Недопустимое имя XML» чаще всего возникает из-за нарушения стандартов именования элементов XML. Метод ЗаписатьНачалоЭлемента в 1С ожидает в качестве параметра только имя тега. Многие начинающие разработчики пытаются передать туда всю строку целиком, включая атрибуты или спецсимволы.
Рассмотрим типичный ошибочный код:
// ОШИБКА: Попытка записать DOCTYPE как элемент
ЗаписьXML.ЗаписатьНачалоЭлемента("!DOCTYPE yml_catalog SYSTEM ""shops.dtd""");
// ОШИБКА: Попытка записать имя элемента вместе с атрибутом
ЗаписьXML.ЗаписатьНачалоЭлемента("yml_catalog date=""2023-10-10""");
В первом случае восклицательный знак и пробелы недопустимы в имени тега. Во втором случае пробел между названием тега и атрибутом date также приводит к ошибке, так как платформа ищет тег с именно таким длинным именем, что запрещено спецификацией XML. Помните: имя элемента не может содержать пробелов, знаков препинания (кроме дефиса и подчеркивания в определенных позициях) и не может начинаться с цифр.
Инструкция DOCTYPE не является обычным элементом (тегом) XML, поэтому метод ЗаписатьНачалоЭлемента для нее не подходит. Для этих целей в объекте ЗаписьXML существует специализированный метод. Разберем по шагам, как правильно добавить системную информацию в файл.
Для формирования строки вида <!DOCTYPE yml_catalog SYSTEM "shops.dtd"> используем метод ЗаписатьТипДокумента:
// Синтаксис: ЗаписатьТипДокумента(Имя, ПубличныйИдентификатор, СистемныйИдентификатор, ВнутреннееПодмножество)
ЗаписьXML.ЗаписатьТипДокумента("yml_catalog", "", "shops.dtd");
Здесь "yml_catalog" — это имя корневого элемента, а "shops.dtd" — ссылка на файл описания структуры (системный идентификатор). Это позволит сформировать корректный заголовок файла без генерации исключений.
Вторая частая ошибка — попытка «склеить» имя тега и его параметры вручную. В 1С объектная модель ЗаписьXML работает по поточному принципу. Если нам нужно создать тег <yml_catalog date="2023-10-10">, мы должны действовать последовательно: сначала открыть элемент, а затем добавить к нему атрибут.
Рассмотрим правильный порядок действий:
ЗаписатьНачалоЭлемента("yml_catalog").ЗаписатьАтрибут("date", ЗначениеДаты).Проанализируем пример кода для корневого элемента YML:
// Формируем дату в формате ISO 8601, как того требует Яндекс
ТекДата = Формат(ТекущаяДата(), "ДФ='yyyy-MM-dd HH:mm'");
ЗаписьXML.ЗаписатьНачалоЭлемента("yml_catalog");
ЗаписьXML.ЗаписатьАтрибут("date", ТекДата);
// Теперь внутри yml_catalog можно открывать следующие теги, например shop
При создании YML-файла крайне важно соблюдать формат даты. Ошибка автора в примере заключалась в попытке передать дату как часть имени или текста без предварительной подготовки. Выясним причину, почему это критично: валидаторы XML (и роботы Маркета) ожидают строго определенный стандарт YYYY-MM-DD HH:mm.
Также важно помнить о спецсимволах в данных (названиях товаров, описаниях). Если вы используете метод ЗаписатьТекст, 1С автоматически экранирует символы типа &, <, >, превращая их в &, < и т.д. Никогда не пытайтесь собрать XML-строку простой конкатенацией (склеиванием строк через "+"), так как любой случайный символ в наименовании товара «сломает» ваш файл.
Пример правильной записи текстовых данных:
ЗаписьXML.ЗаписатьНачалоЭлемента("name");
ЗаписьXML.ЗаписатьТекст(Выборка.НаименованиеТовара); // 1С сама позаботится о безопасности текста
ЗаписьXML.ЗаписатьКонецЭлемента();
Соберем все наши знания в единый алгоритм работы. Посмотрим, как должен выглядеть инициализирующий блок кода для создания корректного YML-файла:
ПутьКФайлу = "C:\temp\market.xml";
ЗаписьXML = Новый ЗаписьXML;
// 1. Указываем кодировку UTF-8 (стандарт для веба)
ЗаписьXML.ОткрытьФайл(ПутьКФайлу, "UTF-8");
// 2. Пишем заголовок <?xml version="1.0" encoding="UTF-8"?>
ЗаписьXML.ЗаписатьОбъявлениеXML();
// 3. Пишем DOCTYPE
ЗаписьXML.ЗаписатьТипДокумента("yml_catalog", "", "shops.dtd");
// 4. Открываем корневой элемент
ТекДата = Формат(ТекущаяДата(), "ДФ='yyyy-MM-dd HH:mm'");
ЗаписьXML.ЗаписатьНачалоЭлемента("yml_catalog");
ЗаписьXML.ЗаписатьАтрибут("date", ТекДата);
// 5. Открываем секцию shop
ЗаписьXML.ЗаписатьНачалоЭлемента("shop");
// 6. Добавляем вложенные элементы
ЗаписьXML.ЗаписатьНачалоЭлемента("name");
ЗаписьXML.ЗаписатьТекст("Название моего магазина");
ЗаписьXML.ЗаписатьКонецЭлемента(); // Закрываем name
// 7. Закрываем все открытые теги в обратном порядке
ЗаписьXML.ЗаписатьКонецЭлемента(); // Закрываем shop
ЗаписьXML.ЗаписатьКонецЭлемента(); // Закрываем yml_catalog
// 8. Завершаем работу
ЗаписьXML.Закрыть();
Проанализируем еще несколько важных моментов, которые помогут избежать ошибок в будущем:
ЗаписатьНачалоЭлемента соответствовало количеству ЗаписатьКонецЭлемента. Если вы закроете тег yml_catalog раньше, чем shop, система выдаст ошибку структуры.ЗаписатьКонецЭлемента не требует передачи имени тега — он автоматически закрывает последний открытый элемент. Это удобно, но требует внимательности при написании циклов.ДокументDOM. С ним сложнее ошибиться в иерархии, так как вы строите дерево объектов в памяти, а затем одним методом сохраняете его в файл.ОбменСЯндексМаркетом в вашей базе.Используя эти инструкции, вы сможете создать валидный XML-файл любой сложности, избежав досадных ошибок именования и нарушения структуры документа.