При интеграции различных информационных систем и обработке файлов обмена разработчики 1С часто сталкиваются с ошибкой парсера «Document is empty XML» при попытке десериализации данных с помощью объекта ФабрикаXDTO. Разберем по шагам, почему возникает эта ошибка, где кроются неочевидные нюансы и как правильно организовать чтение XML-документов в платформе 1С:Предприятие.
Проанализируем типичную ошибку в исходном коде, которая чаще всего приводит к сообщению о пустом документе:
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(ИмяФайлаДляЗагрузки);
ОбъектXML = ФабрикаXDTO.ПрочитатьXML(ЧтениеXML);
Метод УстановитьСтроку() предназначен исключительно для передачи готового текста XML-разметки напрямую из строковой переменной. Если передать в этот метод путь к файлу на диске (например, "C:\Exchange\data.xml"), встроенный парсер 1С попытается разобрать саму строку с путем к файлу как XML-документ. Поскольку в ней нет XML-тегов, синтаксический анализатор сообщает, что документ пуст.
Для загрузки содержимого файла с диска необходимо использовать метод ОткрытьФайл(), а также обязательно закрывать поток после завершения работы:
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ИмяФайлаДляЗагрузки);
ОбъектXML = ФабрикаXDTO.ПрочитатьXML(ЧтениеXML);
ЧтениеXML.Закрыть();
Если файл создается или модифицируется вручную, в XML-структуру могут закрасться синтаксические ошибки. Например, некорректная расстановка точек с запятой внутри тегов:
<ИнтеграцияADЗагрузка xmlns="http://www.sample-package.org"; xmlns:xs="http://www.w3.org/2001/XMLSchema";>
По спецификации стандарта XML атрибуты и пространства имен разделяются исключительно пробелами. Наличие точки с запятой делает разметку невалидной, и парсер прерывает разбор до обработки тела документа.
Рассмотрим пример корректно оформленного XML-документа с объявлением пространств имен:
<?xml version="1.0" encoding="Windows-1251"?>
<ИнтеграцияADЗагрузка xmlns="http://www.sample-package.org" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ЭлементСпискаADЗагрузка>
<Login>GagarinYuA</Login>
<СтатусЗагрузки>1</СтатусЗагрузки>
<ВнутреннийНомерТелефона>737</ВнутреннийНомерТелефона>
<ТабельныйНомер>0000-00006</ТабельныйНомер>
<SSID>1qaz2wsx</SSID>
</ЭлементСпискаADЗагрузка>
</ИнтеграцияADЗагрузка>
Выясним еще одну скрытую причину сбоев при ручном редактировании файлов. При сохранении в текстовых редакторах (например, в Блокноте) в начало файла может добавляться невидимый маркер последовательности байтов — UTF-8 BOM (байт-маркер EF BB BF).
Если файл содержит заголовок encoding="Windows-1251", но физически сохранен с меткой BOM в UTF-8, либо если кодировка в декларации не совпадает с реальной кодировкой потока, метод ПрочитатьXML() завершится ошибкой. Убедитесь, что кодировка в заголовке и кодировка сохранения файла строго согласованы.
Когда корневой элемент XML-документа не содержит явного атрибута xsi:type, фабрика XDTO может не определить, к какому типу из пакета относится корневой узел. В этом случае тип можно передать явно вторым параметром метода ПрочитатьXML():
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ИмяФайлаДляЗагрузки);
// Получаем тип из фабрики метаданных конфигурации
ТипXDTO = ФабрикаXDTO.Тип("http://www.sample-package.org", "ИнтеграцияADЗагрузка");
ОбъектXDTO = ФабрикаXDTO.ПрочитатьXML(ЧтениеXML, ТипXDTO);
ЧтениеXML.Закрыть();
Посмотрим на альтернативные варианты чтения структуры документа, если использование предопределенного пакета XDTO не требуется:
Используется для последовательного разбора больших файлов без загрузки всей иерархии в оперативную память:
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ИмяФайлаДляЗагрузки);
Пока ЧтениеXML.Прочитать() Цикл
Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "Login" Тогда
ЧтениеXML.Прочитать();
Логин = ЧтениеXML.Значение;
КонецЕсли;
КонецЦикла;
ЧтениеXML.Закрыть();
Подходит для работы с произвольными XML-файлами без необходимости предварительного создания XSD-схем:
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ИмяФайлаДляЗагрузки);
Построитель = Новый ПостроительDOM;
ДокументDOM = Построитель.Прочитать(ЧтениеXML);
ЧтениеXML.Закрыть();
Если схема обмена хранится во внешнем файле и отсутствует в дереве метаданных:
Фабрика = СоздатьФабрикуXDTO(ПутьКФайлуСхемыXSD);
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ИмяФайлаДляЗагрузки);
ОбъектXDTO = Фабрика.ПрочитатьXML(ЧтениеXML);
ЧтениеXML.Закрыть();