Разработка и Конфигурация · 12 мин
Как прочитать строку как XML в 1С
Как прочитать строку как XML в 1С: объект ЧтениеXML, УстановитьСтроку, построчный разбор узлов, работа с атрибутами, обработка ошибок и типовые примеры кода.
Задача прочитать строку как XML в 1С возникает при обмене данными с веб-сервисами, при получении ответов от API, при загрузке файлов из внешних систем и при разборе настроек, хранящихся в виде XML-текста. Встроенный язык платформы предоставляет для этого объект ЧтениеXML, который работает как последовательный парсер: он читает документ узел за узлом и позволяет извлекать имена элементов, атрибуты и текстовое содержимое.
Ключевой момент: чтобы разобрать XML из строковой переменной, а не из файла, используется метод УстановитьСтроку(). Если же данные лежат в файле на диске, применяется ОткрытьФайл(). Дальнейшая логика разбора в обоих случаях одинакова — цикл Прочитать() с проверкой типа текущего узла.
Ниже разобраны базовый пример кода, работа с атрибутами и вложенными элементами, обработка ошибок формата, а также альтернативные способы — через ДокументDOM и ФабрикаXDTO, которые удобнее в отдельных сценариях.
Базовый пример: ЧтениеXML и УстановитьСтроку
Объект ЧтениеXML создаётся конструктором Новый ЧтениеXML. После этого строку с XML-содержимым передают методу УстановитьСтроку(). Парсер встаёт на начало документа, и дальше каждый вызов Прочитать() сдвигает позицию к следующему узлу, пока метод не вернёт Ложь — признак конца документа.
СтрокаXML = "<Товары><Товар Код=""001""><Наименование>Кабель</Наименование></Товар></Товары>";
Чтение = Новый ЧтениеXML;
Чтение.УстановитьСтроку(СтрокаXML);
Пока Чтение.Прочитать() Цикл
Если Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
Сообщить("Начало элемента: " + Чтение.Имя);
ИначеЕсли Чтение.ТипУзла = ТипУзлаXML.Текст Тогда
Сообщить("Текст: " + Чтение.Значение);
ИначеЕсли Чтение.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
Сообщить("Конец элемента: " + Чтение.Имя);
КонецЕсли;
КонецЦикла;
Чтение.Закрыть();
После завершения разбора вызовите Закрыть() — это освобождает ресурсы парсера. Если строка содержит некорректный XML, исключение возникнет либо при УстановитьСтроку(), либо при первом вызове Прочитать(), поэтому боевой код всегда оборачивают в Попытка...Исключение.
Чтение = Новый ЧтениеXML;
Чтение.УстановитьСтроку(СтрокаXML);
Пока Чтение.Прочитать() Цикл
Если Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
// обработка узла
КонецЕсли;
КонецЦикла;
Чтение.Закрыть();Какие типы узлов встречаются при разборе
Парсер проходит документ последовательно и для каждого шага заполняет свойство ТипУзла. Понимание типов узлов — основа корректного разбора, потому что обращение к Имя или Значение имеет смысл только для соответствующих типов.
НачалоЭлемента— открывающий тег; доступныИмя, атрибуты,URIПространстваИмен;КонецЭлемента— закрывающий тег; доступноИмя;Текст— текстовое содержимое между тегами; доступноЗначение;НачалоДокументаиКонецДокумента— служебные позиции;Комментарий,ИнструкцияОбработки,ОбъявлениеXML— обычно пропускаются.
Частая ошибка новичков — ожидать, что текст элемента доступен сразу на узле НачалоЭлемента. На самом деле текст приходит отдельным узлом типа Текст следующим шагом цикла. Для упрощения есть метод ПрочитатьЗначение()-подобная логика не предусмотрена, но можно использовать Пропустить(), чтобы перепрыгнуть через поддерево, которое не нужно.
Чтение атрибутов и текстового содержимого
Когда парсер стоит на узле НачалоЭлемента, атрибуты доступны тремя способами: по имени через ПолучитьАтрибут("ИмяАтрибута"), по индексу через ЗначениеАтрибута(Индекс) с учётом КоличествоАтрибутов(), либо перебором через ПрочитатьАтрибут(). Если атрибут отсутствует, ПолучитьАтрибут вернёт Неопределено — обязательно проверяйте результат перед использованием.
Если Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента
И Чтение.Имя = "Товар" Тогда
КодТовара = Чтение.ПолучитьАтрибут("Код");
Если КодТовара = Неопределено Тогда
КодТовара = "";
КонецЕсли;
// Перебор всех атрибутов
Пока Чтение.ПрочитатьАтрибут() Цикл
Сообщить(Чтение.Имя + " = " + Чтение.Значение);
КонецЦикла;
КонецЕсли;
Для чтения текстового содержимого простого элемента удобен приём: на узле НачалоЭлемента вызвать Прочитать() ещё раз и проверить, что следующий узел — Текст. Тогда Чтение.Значение даст содержимое. Все значения приходят как строки: числа и даты нужно преобразовывать вручную через Число(), Дата() или XMLЗначение для типов, сериализованных по правилам XDTO.
Разбор вложенной структуры: практический сценарий
Реальные XML-документы имеют иерархию: документ — табличная часть — строки. Правильный подход — отслеживать контекст через локальные переменные и сбрасывать их на закрывающих тегах. Разберём пример загрузки списка товаров в массив структур.
Функция РазобратьТовары(СтрокаXML) Экспорт
Результат = Новый Массив;
ТекущийТовар = Неопределено;
Чтение = Новый ЧтениеXML;
Чтение.УстановитьСтроку(СтрокаXML);
Пока Чтение.Прочитать() Цикл
Если Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
Если Чтение.Имя = "Товар" Тогда
ТекущийТовар = Новый Структура("Код,Наименование");
ТекущийТовар.Код = Чтение.ПолучитьАтрибут("Код");
ИначеЕсли Чтение.Имя = "Наименование" И ТекущийТовар <> Неопределено Тогда
Чтение.Прочитать();
Если Чтение.ТипУзла = ТипУзлаXML.Текст Тогда
ТекущийТовар.Наименование = Чтение.Значение;
КонецЕсли;
КонецЕсли;
ИначеЕсли Чтение.ТипУзла = ТипУзлаXML.КонецЭлемента
И Чтение.Имя = "Товар" Тогда
Результат.Добавить(ТекущийТовар);
ТекущийТовар = Неопределено;
КонецЕсли;
КонецЦикла;
Чтение.Закрыть();
Возврат Результат;
КонецФункции
Обратите внимание на три приёма: текущий объект создаётся на открывающем теге, наполняется на дочерних узлах и фиксируется в результате на закрывающем. Такая схема масштабируется на любую глубину вложенности — для более сложных документов добавляют переменную текущего раздела или стек контекстов.
- 1Сформируйте или получите строку с XML-содержимым
- 2Создайте объект: Новый ЧтениеXML
- 3Вызовите УстановитьСтроку(СтрокаXML) внутри Попытка...Исключение
- 4В цикле Прочитать() проверяйте ТипУзла и Имя элемента
- 5Извлекайте атрибуты через ПолучитьАтрибут, текст — на узле ТипУзлаXML.Текст
- 6Закройте чтение методом Закрыть() и проверьте собранные данные
Обработка ошибок и проверка результата
Строка, пришедшая извне, не гарантированно является валидным XML. Типичные проблемы: обрезанный документ, незакрытые теги, недопустимые символы, неверная кодировка, HTML вместо XML. Любая из них вызовет исключение, поэтому разбор всегда помещают в защищённый блок.
Чтение = Новый ЧтениеXML;
Попытка
Чтение.УстановитьСтроку(СтрокаXML);
Пока Чтение.Прочитать() Цикл
// разбор
КонецЦикла;
Чтение.Закрыть();
Исключение
ТекстОшибки = ОписаниеОшибки();
ЗаписьЖурналаРегистрации("ЗагрузкаXML",
УровеньЖурналаРегистрации.Ошибка,,, ТекстОшибки);
КонецПопытки;
Помимо технической валидности проверяйте смысловую: наличие обязательных элементов, заполненность ключевых атрибутов, соответствие количества загруженных строк ожидаемому. Полезно логировать не только факт ошибки, но и фрагмент строки, на котором разбор прервался, — это сильно ускоряет поиск причины при обмене с внешними системами.
Альтернативы: ДокументDOM и ФабрикаXDTO
Последовательный парсер ЧтениеXML — не единственный способ. Встроенный язык предлагает ещё два механизма, которые в ряде задач удобнее.
ДокументDOM загружает весь документ в память как дерево и позволяет обращаться к элементам по XPath-подобным путям. Подходит, когда нужен произвольный доступ к узлам и документ умеренного размера:
Чтение = Новый ЧтениеXML;
Чтение.УстановитьСтроку(СтрокаXML);
Построитель = Новый ПостроительDOM;
Документ = Построитель.Прочитать(Чтение);
Узлы = Документ.ПолучитьЭлементыПоИмени("Товар");
Для Каждого Узел Из Узлы Цикл
Код = Узел.ПолучитьАтрибут("Код");
КонецЦикла;
ФабрикаXDTO и функции ПрочитатьXML применяются, когда XML соответствует известной схеме: платформа сама преобразует документ в объект с типизированными свойствами. Это стандартный путь для обменов EnterpriseData, веб-сервисов и сериализованных объектов конфигурации.
Сравнение вариантов
Последовательный разбор, минимальный расход памяти. Подходит для больших документов и потоковой загрузки, но код разбора вложенных структур громоздкий
Дерево в памяти со случайным доступом к узлам. Удобен для небольших документов и выборок по имени элемента, но требует больше памяти
Автоматическое преобразование в типизированные объекты по схеме. Лучший выбор для стандартных форматов обмена, но требует описанной схемы
Когда какой способ выбрать
Выбор механизма зависит от размера документа, наличия схемы и характера доступа к данным. Для однопроходной загрузки больших файлов — только ЧтениеXML. Для разбора короткого ответа API с необходимостью доставать значения из разных веток — удобнее ДокументDOM. Для стандартных обменов и веб-сервисов — ФабрикаXDTO.
Если строка пришла из файла, сначала прочитайте файл в строку через ЧтениеТекста с указанием кодировки, либо сразу используйте Чтение.ОткрытьФайл() — это надёжнее, так как парсер сам определит кодировку по объявлению XML.
Как выбрать действие
Что важно запомнить
Строку разбирают через ЧтениеXML с методом УстановитьСтроку и циклом Прочитать(), проверяя ТипУзла. Атрибуты читают на узле НачалоЭлемента, текст — на узле Текст. Разбор всегда защищают обработкой исключений, а для дерева в памяти и типизированных схем есть ДокументDOM и ФабрикаXDTO.
Частые вопросы
Чем УстановитьСтроку отличается от ОткрытьФайл?
УстановитьСтроку принимает XML-содержимое из строковой переменной, уже находящейся в памяти. ОткрытьФайл читает данные напрямую из файла на диске. Логика дальнейшего разбора идентична, но при работе с файлом парсер сам учитывает кодировку из объявления XML.
Почему ПолучитьАтрибут возвращает Неопределено?
Так происходит, если атрибут с указанным именем отсутствует в текущем элементе либо имя указано с ошибкой в регистре символов — имена атрибутов чувствительны к регистру. Перед использованием значения всегда проверяйте его на Неопределено.
Как пропустить ненужный фрагмент документа?
На узле НачалоЭлемента вызовите метод Пропустить() — парсер перейдёт сразу к концу текущего элемента, минуя всё его содержимое. Это быстрее, чем вручную отслеживать вложенность ненужной ветки.
Как преобразовать строковое значение из XML в дату или число?
Все значения из ЧтениеXML приходят строками. Для чисел используйте Число(), для дат — конструктор Дата() или функцию XMLЗначение с указанием типа, если значение записано в каноническом формате XDTO (например, 2026-01-15T10:30:00).
Что делать, если XML содержит пространства имён?
Свойство Имя возвращает локальное имя без префикса, а пространство доступно через URIПространстваИмен. Если в документе есть элементы с одинаковыми локальными именами из разных пространств, сравнивайте оба свойства, иначе разбор перепутает узлы.
Можно ли прочитать XML в управляемой форме на клиенте?
Да, ЧтениеXML доступен на тонком и веб-клиенте. Однако тяжёлый разбор больших документов лучше выполнять на сервере, чтобы не блокировать интерфейс пользователя и не передавать большие строки между клиентом и сервером.