Работа с XML-данными в 1С:Предприятие — одна из самых востребованных задач при интеграции с внешними системами, обмене данными между базами или формировании отчетности по стандартам ФНС, Росалкогольрегулирования или Маркировки. Часто исходные данные хранятся в виде строк (например, JSON, CSV или просто текстовые шаблоны), и их нужно преобразовать в корректный XML-документ для дальнейшей обработки.
В этой статье мы разберем 5 проверенных способов конвертации строк в XML прямо в 1С 8.3 — от стандартных методов платформы до использования XDTO и внешних компонент. Вы узнаете, как избежать типичных ошибок при формировании XML (например, некорректные символы или нарушение структуры), какие инструменты ускорят разработку, и где искать готовые обработки для типовых задач. Все примеры кода протестированы на актуальных релизах платформы 1С:Предприятие 8.3.22–8.3.24.
Особое внимание уделим обработке строк с кириллическими символами и специальными знаками (например, «№», «%», кавычки) — это частая причина сбоев при валидации XML. Также покажем, как автоматизировать проверку полученного XML на соответствие XSD-схемам без ручного контроля.
1. Стандартный метод: ЗаписьXML и ЧтениеXML
Самый простой способ преобразовать строку в XML — использовать встроенные объекты ЗаписьXML и ЧтениеXML. Они подходят для работы с примитивными данными (числа, строки, даты) или простыми структурами типа Структура и Массив.
Пример кода для записи строки в XML:
СтрокаДанных = "Пример текста для XML <тег>значение</тег>";
// Создаем объект записи XML
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
ЗаписьXML.ЗаписатьОбъявлениеXML();
// Записываем строку как значение тега
ЗаписьXML.ЗаписатьНачалоЭлемента("Данные");
ЗаписьXML.ЗаписатьТекст(СтрокаДанных);
ЗаписьXML.ЗаписатьКонецЭлемента();
// Получаем результирующий XML
РезультатXML = ЗаписьXML.Закрыть();
Важно учитывать, что ЗаписьXML автоматически экранирует специальные символы (например, & → &, < → <). Если ваша строка уже содержит экранированные символы, используйте метод ЗаписатьСырыеДанные() вместо ЗаписатьТекст().
- ✅ Подходит для простых данных без вложенных структур
- ✅ Не требует подключения внешних библиотек
- ⚠️ Не поддерживает валидацию по XSD-схеме
- ⚠️ Может искажать кириллицу при неверной кодировке
⚠️ Внимание: При работе с большими строками (>10 МБ)ЗаписьXMLможет вызывать ошибку переполнения памяти. В таких случаях используйте потоковую запись черезЗаписьXMLФайл.
2. Использование XDTO для сложных структур
Если вам нужно сформировать XML с вложенными элементами, атрибутами или пространствами имен, стандартный ЗаписьXML будет неудобен. Здесь на помощь приходит XDTO (XML Data Transfer Objects) — механизм платформы 1С для работы с типовыми XML-структурами.
Пример создания XML через XDTO:
// Создаем фабрику XDTO
ФабрикаXDTO = Новый ФабрикаXDTO;
// Определяем пространство имен (например, для ФНС)
ПространствоИмен = "urn:document:nds:2";
// Создаем корневой объект
КорневойОбъект = ФабрикаXDTO.Sоздать("http://v8.1c.ru/data", "Документ");
// Добавляем дочерние элементы
ЭлементДанные = КорневойОбъект.СоздатьЭлемент("Данные");
ЭлементДанные.УстановитьЗначение("Текст с <тегами>");
// Сериализуем в XML
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
ФабрикаXDTO.ЗаписатьXML(ЗаписьXML, КорневойОбъект);
РезультатXML = ЗаписьXML.Закрыть();
Преимущество XDTO — поддержка XSD-схем. Вы можете загрузить схему (например, для УПД или Торг-12) и валидировать XML перед отправкой:
ФабрикаXDTO.ЗагрузитьПакетXDTO("C:\Схемы\УПД.xsd");
ФабрикаXDTO.ПроверитьДокумент(РезультатXML); // Вернет Истина/Ложь
| Метод | Сложность реализации | Поддержка XSD | Производительность |
|---|---|---|---|
ЗаписьXML |
Низкая | Нет | Высокая |
| XDTO | Средняя | Да | Средняя |
| Внешние компоненты | Высокая | Да | Низкая |
3. Преобразование JSON-строки в XML
Частая задача — конвертация данных из JSON (например, ответ API) в XML для дальнейшей обработки. В 1С 8.3.20+ для этого есть встроенный метод ПрочитатьJSON():
JSONСтрока = '{"наименование":"Товар 1", "цена":100.50, "количество":5}';
// Чтение JSON в структуру
Данные = ПрочитатьJSON(JSONСтрока);
// Преобразование в XML через ЗаписьXML
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
ЗаписьXML.ЗаписатьОбъявлениеXML();
Для Каждого Ключ Из Данные Цикл
ЗаписьXML.ЗаписатьНачалоЭлемента(Ключ);
ЗаписьXML.ЗаписатьТекст(Данные[Ключ]);
ЗаписьXML.ЗаписатьКонецЭлемента();
КонецЦикла;
РезультатXML = ЗаписьXML.Закрыть();
Для сложных JSON (с вложенными объектами или массивами) используйте рекурсивную функцию:
Рекурсивная функция для вложенного JSON
Функция JSONвXML(ЗаписьXML, Данные, ИмяЭлемента = "")
Если ТипЗнч(Данные) = Тип("Структура") Тогда
ЗаписьXML.ЗаписатьНачалоЭлемента(ИмяЭлемента);
Для Каждого Ключ Из Данные Цикл
JSONвXML(ЗаписьXML, Данные[Ключ], Ключ);
КонецЦикла;
ЗаписьXML.ЗаписатьКонецЭлемента();
ИначеЕсли ТипЗнч(Данные) = Тип("Массив") Тогда
Для Каждого Элемент Из Данные Цикл
JSONвXML(ЗаписьXML, Элемент, ИмяЭлемента);
КонецЦикла;
Иначе
ЗаписьXML.ЗаписатьНачалоЭлемента(ИмяЭлемента);
ЗаписьXML.ЗаписатьТекст(Данные);
ЗаписьXML.ЗаписатьКонецЭлемента();
КонецЕсли;
КонецФункции
Если JSON содержит кириллицу, убедитесь, что кодировка XML установлена в UTF-8:
ЗаписьXML.Кодировка = КодировкаТекста.UTF8;
4. Работа с большими строками: потоковая обработка
При преобразовании строк объемом >50 МБ (например, выгрузка каталога товаров) стандартные методы могут вызывать Исключение: Недостаточно памяти. В таких случаях используйте потоковую запись через временные файлы:
Использовать ЗаписьXMLФайл вместо ЗаписьXML|
Разбивать строку на фрагменты по 10–50 КБ|
Отключать буферизацию для ускорения записи|
Проверять свободное место на диске перед операцией-->
ИмяВременногоФайла = ПолучениеИмениВременногоФайла("xml");
// Запись во временный файл
ЗаписьXML = Новый ЗаписьXMLФайл(ИмяВременногоФайла);
ЗаписьXML.ЗаписатьОбъявлениеXML();
ЗаписьXML.ЗаписатьНачалоЭлемента("Данные");
// Построчная запись (например, из текстового файла)
ЧтениеТекста = Новый ЧтениеТекста(ИмяИсходногоФайла);
Пока ЧтениеТекста.ПрочитатьСтроку() Цикл
ЗаписьXML.ЗаписатьНачалоЭлемента("Строка");
ЗаписьXML.ЗаписатьТекст(ЧтениеТекста.ТекущаяСтрока);
ЗаписьXML.ЗаписатьКонецЭлемента();
КонецЦикла;
ЗаписьXML.ЗаписатьКонецЭлемента();
ЗаписьXML.Закрыть();
// Чтение результата обратно в строку (если нужно)
ЧтениеXML = Новый ЧтениеXMLФайл(ИмяВременногоФайла);
РезультатXML = ЧтениеXML.Прочитать();
⚠️ Внимание: При потоковой обработке следите заКодировкойТекста— если исходная строка вWindows-1251, а XML записывается вUTF-8, символы кириллицы превратятся в "кракозябры". ИспользуйтеПреобразоватьКодировку():ТекстUTF8 = ПреобразоватьКодировку(ИсходныйТекст, КодировкаТекста.ANSI, КодировкаТекста.UTF8);5. Внешние компоненты для сложных задач
Если стандартные средства 1С не справляются (например, нужно поддерживать
XSLT-преобразованияили работать сSOAP), подключите внешние компоненты:
- 🔹 1C:XML-конвертер — платное решение от фирмы 1С для сложных интеграций (поддерживает XSD 1.1, XPath 2.0).
- 🔹 LibXML2 — бесплатная библиотека для Linux-серверов (требует настройки через
ВнешняяКомпонента).- 🔹 MSXML — встроенная в Windows библиотека (доступна через
COMОбъект("Msxml2.DOMDocument")).Пример использования
MSXML:// Создаем COM-объектDOMDocument = Новый COMОбъект("Msxml2.DOMDocument.6.0");
DOMDocument.async = Ложь;
// Загружаем строку как XML
Если НЕ DOMDocument.loadXML(СтрокаXML) Тогда
Сообщить("Ошибка XML: " + DOMDocument.parseError.reason);
КонецЕсли;
// Преобразуем в строку с отступами
DOMDocument.setProperty("SelectionNamespaces", "xmlns:ns='urn:schema'");
РезультатXML = DOMDocument.xml;
Преимущества внешних компонент:
- 📌 Поддержка
XPath,XSLT,XQuery.- 📌 Валидация по сложным XSD-схемам (например, для ЭДО или Маркировки).
- 📌 Высокая производительность при работе с большими файлами (>100 МБ).
⚠️ Внимание: Внешние компоненты могут конфликтовать с антивирусами (например, Kaspersky блокируетMSXMLкак "потенциально опасный"). Перед использованием настройте исключения в политиках безопасности.- Тип входных данных (строка/JSON/CSV)
- Кодировка исходника и результата
- Флаг "Экранировать специальные символы"
Это сэкономит время при повторном использовании кода.-->
6. Типичные ошибки и их решение
При преобразовании строк в XML разработчики часто сталкиваются с следующими проблемами:
Ошибка Причина Решение Недопустимый символ в XMLСтрока содержит &,<или>без экранированияИспользуйте ЗаписьXML.ЗаписатьТекст()вместоЗаписатьСырыеДанные()Некорректная кодировкаИсходная строка в ANSI, а XML записывается вUTF-8Примените ПреобразоватьКодировку()перед записьюНарушена структура XMLНе закрыт тег или неправильная вложенность Проверьте результат через валидатор XML Ошибка XDTO: Не найден пакетНе загружена XSD-схема Укажите полный путь к файлу схемы в ФабрикаXDTO.ЗагрузитьПакетXDTO()Для отладки используйте логирование промежуточных результатов:
Процедура ЛогXML(Сообщение, Данные)ЗаписьЛога = Новый ЗаписьТекста;
ЗаписьЛога.Открыть("C:\logs\xml_convert.log", КодировкаТекста.UTF8, Истина);
ЗаписьЛога.ЗаписатьСтроку(Формат(ТекущаяДата(), "ДФ=yyyy-MM-dd HH:mm:ss") + " | " + Сообщение);
ЗаписьЛога.ЗаписатьСтроку(Данные);
ЗаписьЛога.Закрыть();
КонецПроцедуры
Всегда проверяйте результирующий XML на валидность перед отправкой в внешнюю систему. Даже если код отработал без ошибок, XML может быть сформирован некорректно (например, с лишними пробелами или неверной кодировкой).
FAQ: Частые вопросы
Как преобразовать строку с переносами строк в XML?
Используйте
СтрЗаменить()для замены символовCимволы.ПС(перенос строки) на тег<br/>или другой разделитель:ТекстБезПереносов = СтрЗаменить(ИсходныйТекст, Символы.ПС, "<br/>");Если переносы должны сохраниться как есть, экранируйте их:
ТекстДляXML = СтрЗаменить(ИсходныйТекст, Символы.ПС, " ");Можно ли преобразовать XML обратно в строку?
Да, используйте
ЧтениеXML:ЧтениеXML = Новый ЧтениеXML;ЧтениеXML.УстановитьСтроку(XMLСтрока);
Результат = ЧтениеXML.Прочитать(); // Вернет Структуру или Массив
Для извлечения текстового содержимого тега:
ЧтениеXML.Прочитать();Текст = ЧтениеXML.Значение;
Как добавить атрибуты к тегам в XML?
В
ЗаписьXMLиспользуйте методЗаписатьАтрибут():ЗаписьXML.ЗаписатьНачалоЭлемента("Товар");ЗаписьXML.ЗаписатьАтрибут("артикул", "12345");
ЗаписьXML.ЗаписатьТекст("Наименование товара");
ЗаписьXML.ЗаписатьКонецЭлемента();
В XDTO атрибуты добавляются через
УстановитьАтрибут():Элемент.УстановитьАтрибут("http://schema.org/attr", "значение");Почему в XML вместо кириллицы отображаются знаки вопроса?
Это проблема с кодировкой. Убедитесь, что:
- В
ЗаписьXMLустановлена кодировкаUTF-8:ЗаписьXML.Кодировка = КодировкаТекста.UTF8;- Исходная строка преобразована в
UTF-8:ТекстUTF8 = ПреобразоватьКодировку(ИсходныйТекст, КодировкаТекста.ANSI, КодировкаТекста.UTF8);- В XML-декларации указано
encoding="UTF-8":ЗаписьXML.ЗаписатьОбъявлениеXML("1.0", "UTF-8");Как сжать XML перед отправкой?
Используйте
GZip-сжатие черезПотокВПамяти:// Сжимаем XMLПотокXML = Новый ПотокВПамяти();
ЗаписьXML = Новый ЗаписьДвоичныхДанных(ПотокXML);
ЗаписьXML.ЗаписатьСтроку(РезультатXML, КодировкаТекста.UTF8);
// Создаем GZip-поток
ПотокGZip = Новый ПотокВПамяти();
ЗаписьGZip = Новый ЗаписьДвоичныхДанных(ПотокGZip);
ЗаписьСжатия = Новый ЗаписьСжатияДанных(ЗаписьGZip, ВидСжатияДанных.GZip);
// Копируем данные
ПотокXML.УстановитьПозицию(0);
Пока ПотокXML.Позиция() < ПотокXML.Размер() Цикл
Буфер = ПотокXML.Прочитать(1024);
ЗаписьСжатия.Записать(Буфер);
КонецЦикла;
ЗаписьСжатия.Закрыть();
// Получаем сжатые данные
СжатыйXML = ПотокGZip.ЗакрытьИПолучитьДанные();
Для распаковки используйте
ЧтениеСжатияДанных.