К статье
Практический материал

Разработка и Конфигурация · 13 мин

Как в 1С прочитать XML-файл как текст

Как в 1С прочитать XML-файл как обычный текст: ЧтениеТекста, ПолучитьТекст, кодировки, BOM, построчное чтение, типичные ошибки и проверка результата.

Задача прочитать XML как текст возникает в 1С чаще, чем кажется: нужно логировать исходное содержимое файла обмена, найти конкретный фрагмент строковым поиском, исправить битый тег перед разбором, отправить файл в HTTP-запросе как строку или просто посмотреть, что реально пришло от контрагента. Штатные объекты ЧтениеXML и ФабрикаXDTO парсят структуру, а для «сырого» доступа к содержимому используется другой инструмент — ЧтениеТекста.

Ключевой момент: XML — это обычный текстовый файл с разметкой, поэтому технически ничто не мешает прочитать его посимвольно или целиком в строку. Проблемы начинаются не с чтения, а с кодировки, символа BOM, переводов строк и размера файла. Если их не учесть, на выходе получаются «кракозябры», потерянный первый символ или зависший клиент на файле в несколько сотен мегабайт.

Ниже разобраны рабочие способы чтения XML как текста на встроенном языке 1С, выбор кодировки, обработка больших файлов, типичные ошибки и способы проверить, что текст прочитан корректно.

Когда XML нужно читать именно как текст, а не как структуру

Объект ЧтениеXML подходит, когда нужно обойти узлы, атрибуты и значения. Но он требует корректного, валидного документа: сломанный тег, незакрытый элемент или посторонний текст до декларации <?xml ...?> вызовут исключение ещё до начала обработки. Кроме того, парсер «съедает» исходное форматирование — вы не увидите, как файл выглядел на самом деле.

Чтение как текст оправдано в ситуациях:

  • логирование исходного содержимого обмена для разбора ошибок с контрагентом;
  • предобработка файла: замена некорректных символов, удаление лишних деклараций, склейка фрагментов;
  • поиск конкретной подстроки без построения всей модели документа;
  • передача содержимого в тело HTTP-запроса, в печатную форму или в поле хранилища значений;
  • диагностика: посмотреть первые строки файла, чтобы понять кодировку и структуру.

Если цель — извлечь данные из валидного XML, читайте его как текст только для диагностики, а основную обработку ведите через ЧтениеXML. Смешивать подходы в одном проходе не стоит: строковый разбор XML хрупок и плохо переносит изменения формата.

Базовый способ: ЧтениеТекста и чтение файла целиком

Самый простой сценарий — прочитать весь файл в одну строковую переменную. Для этого создаётся объект ЧтениеТекста, ему передаётся путь к файлу и кодировка, после чего вызывается метод Прочитать().

Чтение = Новый ЧтениеТекста("C:\Обмен\zakaz.xml", КодировкаТекста.UTF8);

ТекстXML = Чтение.Прочитать();

Чтение.Закрыть();

Сообщить(СтрДлина(ТекстXML));

Метод Прочитать() без параметров возвращает всё содержимое файла одной строкой, включая переводы строк. После работы объект нужно закрыть методом Закрыть() — иначе файл останется занятым, и последующие попытки записи или удаления завершатся ошибкой доступа.

Если файл лежит на сервере, а код выполняется на клиенте, сначала передайте файл на сервер через ПоместитьФайл() или работайте с временным хранилищем. Путь в конструкторе ЧтениеТекста интерпретируется относительно той стороны, где выполняется код: сервер не видит диск C пользователя, и наоборот.

Порядок действий
  1. 1
    Определите, где выполняется код: на клиенте или на сервере — от этого зависит доступный путь к файлу.
  2. 2
    Создайте объект: Новый ЧтениеТекста(ПутьКФайлу, КодировкаТекста.UTF8).
  3. 3
    Прочитайте содержимое: переменная = Чтение.Прочитать() — весь файл одной строкой.
  4. 4
    Закройте чтение: Чтение.Закрыть().
  5. 5
    Проверьте результат: длина строки больше нуля, первые символы содержат <?xml, нет символов замены (�).

Выбор кодировки и проблема BOM

Кодировка — главный источник ошибок при чтении XML как текста. XML-файлы обменов чаще всего сохранены в UTF-8, но встречаются файлы в UTF-16, ANSI (Windows-1251) и даже в кодировке, отличной от заявленной в декларации encoding="...". Если указать неверную кодировку, кириллица превратится в нечитаемые символы, при этом исключения не возникнет — ошибка проявится только в данных.

Практический подход: начните с КодировкаТекста.UTF8, прочитайте первые строки и посмотрите на русский текст внутри. Если видны «кракозябры», попробуйте КодировкаТекста.ANSI или КодировкаТекста.UTF16. Декларация в первой строке файла (encoding="windows-1251") — подсказка, но не гарантия: некоторые системы пишут в декларации одно, а сохраняют в другом.

Отдельная тема — BOM (byte order mark), служебные байты в начале файла. При чтении UTF-8 с BOM платформа обычно обрабатывает его корректно, но если вы читаете файл побайтово или вручную разбираете начало строки, BOM может «прилипнуть» к первому символу и сломать сравнение строки с <?xml. Признак проблемы: условие Лев(ТекстXML, 5) = "<?xml" возвращает Ложь при визуально правильном начале файла.

Построчное чтение и обработка больших файлов

Когда файл велик или нужно обрабатывать его инкрементно, используйте метод ПрочитатьСтроку() в цикле. Он возвращает очередную строку без символа перевода строки, а по достижении конца файла — Неопределено.

Чтение = Новый ЧтениеТекста(ПутьКФайлу, КодировкаТекста.UTF8);

Строка = Чтение.ПрочитатьСтроку();

Пока Строка <> Неопределено Цикл

Если Найти(Строка, "<Номенклатура") > 0 Тогда

// обработка найденного фрагмента

КонецЕсли;

Строка = Чтение.ПрочитатьСтроку();

КонецЦикла;

Чтение.Закрыть();

У построчного чтения есть ограничение: XML не обязан быть отформатирован построчно. Многие системы выгружают весь документ одной строкой без переводов — тогда ПрочитатьСтроку() вернёт весь файл за один вызов, и выигрыша по памяти не будет. Проверить это заранее можно, открыв файл в текстовом редакторе или прочитав первую порцию методом Прочитать(РазмерЧасти) с явным размером в символах.

Для потоковой обработки «однострочных» больших файлов читайте частями фиксированного размера и ищите границы тегов внутри буфера, перенося «хвост» незавершённого фрагмента на следующую итерацию. Это сложнее, но единственный устойчивый вариант для файлов, которые нельзя загрузить в память целиком.

Сравнение вариантов

Прочитать() целиком

Подходит для файлов до нескольких мегабайт. Простой код, но весь файл загружается в память одной строкой.

ПрочитатьСтроку() в цикле

Экономит память при построчно отформатированном XML. Бесполезно, если файл записан одной строкой без переводов.

Прочитать(Размер) частями

Универсальный вариант для больших файлов. Требует ручной склейки фрагментов на границах тегов.

ЧтениеXML

Для разбора структуры валидного документа. Не подходит, если нужен исходный текст или файл содержит ошибки разметки.

Чтение XML из строки, а не из файла

Иногда XML уже находится в строковой переменной — получен из веб-сервиса, макета или хранилища значений — и требуется дальнейшая работа. Файл на диске при этом создавать не нужно: для разбора структуры ЧтениеXML умеет работать напрямую со строкой через метод УстановитьСтроку().

ЧтениеXML = Новый ЧтениеXML;

ЧтениеXML.УстановитьСтроку(ТекстXML);

Пока ЧтениеXML.Прочитать() Цикл

Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда

Сообщить(ЧтениеXML.Имя);

КонецЕсли;

КонецЦикла;

ЧтениеXML.Закрыть();

Если же нужна именно строковая обработка (поиск, замена, извлечение фрагмента), работайте со строкой напрямую функциями Найти(), Сред(), СтрЗаменить(). Для поиска без учёта регистра используйте НРег() на обеих частях сравнения — имена тегов в XML регистрозависимы по стандарту, но реальные выгрузки этим правилом иногда пренебрегают.

Обратная задача — сохранить строку как XML-файл — решается объектом ЗаписьТекста с явным указанием кодировки. Сохраняйте в той же кодировке, в которой читали, если файл пойдёт обратно в ту же систему.

Типичные ошибки
01
Чтение без указания кодировки — платформа применит кодировку по умолчанию, и кириллица из UTF-8-файла превратится в нечитаемые символы без всякого исключения.
02
Пропуск Чтение.Закрыть() — файл остаётся заблокированным, следующая запись или удаление завершаются ошибкой доступа.
03
Проверка Лев(Текст, 5) = "<?xml" без учёта BOM — условие ложно срабатывает, хотя файл корректен.
04
Чтение целиком файла в сотни мегабайт — сеанс зависает или падает по нехватке памяти вместо потоковой обработки.
05
Разбор XML регулярными заменами вместо ЧтениеXML — код ломается при любом изменении порядка атрибутов или форматирования.

Проверка результата и диагностика проблем

После чтения убедитесь, что текст получен корректно, прежде чем передавать его дальше. Минимальный набор проверок: строка непустая, её длина соотносится с размером файла, в начале присутствует декларация XML или корневой элемент, в тексте нет символа замены (�), который является верным признаком неверной кодировки.

Если текст будет передан в ЧтениеXML или отправлен контрагенту, полезно выполнить пробный разбор: установить строку в ЧтениеXML и прочитать первый узел. Исключение на этом этапе означает, что файл повреждён или обрезан — и лучше узнать об этом сразу, чем в середине загрузки данных.

Для диагностики «кракозябр» выведите в журнал регистрации или сообщением первые 200–300 символов прочитанного текста. По виду искажений легко понять направление ошибки: UTF-8, прочитанный как ANSI, даёт характерные двухбайтовые последовательности вместо каждой русской буквы, а обратная ошибка выглядит иначе.

Контрольные точки

Как проверить результат

Длина строки после Прочитать()
Норма

Больше нуля и соотносится с размером файла

Тревожный признак

Пустая строка при непустом файле — неверный путь или проблема доступа

Начало текста
Норма

Содержит <?xml или имя корневого элемента

Тревожный признак

Посторонние символы или пустое начало — возможен BOM или обрезанный файл

Кириллица в тексте
Норма

Русские буквы читаемы

Тревожный признак

Символы � или «кракозябры» — указана неверная кодировка

Пробный разбор через ЧтениеXML
Норма

Первый узел читается без исключения

Тревожный признак

Исключение — файл повреждён или содержит ошибки разметки

Безопасная организация кода и ограничения

Чтение файла — операция, которая может завершиться ошибкой: файл не существует, занят другим процессом, нет прав доступа. Оборачивайте работу с ЧтениеТекста в конструкцию Попытка ... Исключение ... КонецПопытки и обязательно закрывайте объект в ветке исключения, если он был создан. Перед чтением проверяйте существование файла через объект Файл и его метод Существует().

В клиент-серверном режиме помните о разделении контекстов: файловые операции в коде с директивой &НаСервере выполняются на сервере, и пути должны быть серверными. Для передачи содержимого между клиентом и сервером используйте временное хранилище, а не попытки читать один и тот же путь с обеих сторон.

Не используйте чтение как текст для обхода ограничений прав доступа к данным: содержимое файла обмена может содержать персональные данные и коммерческую информацию, и его запись в журнал регистрации или открытые сообщения должна быть осознанным решением, а не побочным эффектом отладки.

Частые вопросы

Чем ЧтениеТекста отличается от ЧтениеXML?

ЧтениеТекста возвращает содержимое файла как есть — строки и символы без анализа структуры. ЧтениеXML разбирает документ на узлы, атрибуты и значения, но требует валидного XML и не показывает исходное форматирование. Для диагностики и предобработки нужен первый, для извлечения данных — второй.

Почему после чтения русские буквы превратились в непонятные символы?

Указана кодировка, отличная от реальной кодировки файла. Исключения при этом не возникает — ошибка видна только в данных. Попробуйте по очереди КодировкаТекста.UTF8, ANSI и UTF16 и проверьте декларацию encoding в первой строке файла.

Как прочитать XML, если весь файл записан одной строкой?

ПрочитатьСтроку() вернёт весь файл за один вызов, поэтому для больших «однострочных» файлов используйте Прочитать(РазмерЧасти) с фиксированным числом символов и склеивайте фрагменты на границах тегов вручную. Для небольших файлов проще прочитать целиком.

Можно ли прочитать XML как текст на клиенте в тонком клиенте?

Да, если включена возможность использования синхронных вызовов или задействованы асинхронные методы (НачатьПомещениеФайла и аналоги). В веб-клиенте прямой доступ к файловой системе ограничен — файл сначала помещается во временное хранилище, а чтение выполняется на сервере.

Что делать, если файл занят другой программой?

Чтение завершится исключением. Оберните код в Попытка/Исключение, при ошибке подождите и повторите попытку с ограниченным числом итераций. Если файл постоянно занят поставщиком данных, договоритесь о выгрузке через промежуточный файл с последующим переименованием — это стандартный способ избежать гонки.

Нужно ли закрывать ЧтениеТекста, если чтение завершилось ошибкой?

Да. Если объект был успешно создан, вызовите Закрыть() и в ветке исключения — иначе файловый дескриптор останется открытым до завершения сеанса, и файл будет недоступен для других операций.

Итог

Что важно запомнить

XML читается как текст объектом ЧтениеТекста: укажите путь и кодировку (чаще UTF-8), прочитайте целиком через Прочитать() или построчно через ПрочитатьСтроку(), обязательно закройте объект. Контролируйте кодировку по отсутствию символов замены, учитывайте BOM при сравнении начала строки, а большие файлы обрабатывайте частями, чтобы не исчерпать память.