При обмене данными между информационными базами 1С часто возникает задача выгрузить или прочитать не просто значения реквизитов, а сырой исходный текст поддерева XML. Например, требуется сохранить содержимое узла CatalogObject.Справочник1 вместе со всеми его дочерними тегами (Ref, IsFolder, DeletionMark и др.) в виде одной строки.
Объект ЧтениеXML работает как последовательный потоковый парсер. У него отсутствует встроенный метод вроде InnerXML, позволяющий за один вызов получить весь исходный код текущего элемента. Проанализируем несколько способов решения этой задачи в зависимости от объема файла и требуемого быстродействия.
Если размер XML-файла относительно небольшой, проще всего выгрузить документ в объектную модель документа (DOM) с помощью объекта ПостроительDOM. После того как документ прочитан, мы находим нужный узел (например, через поиск по дочерним узлам или с использованием XPath) и записываем его в строку.
Рассмотрим пошагово алгоритм получения строки с помощью объектов ЗаписьDOM и ЗаписьXML:
ДокументDOM с помощью ПостроительDOM.ДочерниеУзлы или вычисление XPath-выражения).ЗаписьXML и подготавливаем его к записи в строку методом УстановитьСтроку().ЗаписьDOM записываем найденный узел DOM в объект ЗаписьXML.ЗаписьXML и получаем итоговую строку.Разберем пример кода на языке 1С:
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл("C:\Exchange\data.xml");
ПостроительDOM = Новый ПостроительDOM;
ДокументDOM = ПостроительDOM.Прочитать(ЧтениеXML);
// Поиск узла с помощью XPath
ВыражениеXPath = "//CatalogObject.Справочник1[Ref='a4b8db1c-3cbb-11e4-9445-b4b52f7093b4']";
РезультатXPath = ДокументDOM.ВычислитьВыражениеXPath(ВыражениеXPath);
УзелСправочника = РезультатXPath.ПолучитьСледующий();
Если УзелСправочника <> Неопределено Тогда
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
ЗаписьDOM = Новый ЗаписьDOM;
ЗаписьDOM.Записать(УзелСправочника, ЗаписьXML);
ТекстУзлаXML = ЗаписьXML.Закрыть();
// Переменная ТекстУзлаXML содержит полное XML-описание элемента
КонецЕсли;
ЧтениеXML.Закрыть();
Загрузка огромного файла в DOM целиком может вызвать высокое потребление оперативной памяти. Чтобы обойти это ограничение, объединим потоковое чтение и DOM. Выполним последовательное чтение с помощью ЧтениеXML до тех пор, пока курсор не встанет на начало нужного элемента, после чего считаем только данный узел через ПостроительDOM.
Проанализируем реализацию этого подхода:
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл("C:\Exchange\data.xml");
ПостроительDOM = Новый ПостроительDOM;
Пока ЧтениеXML.Прочитать() Цикл
Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "CatalogObject.Справочник1" Тогда
// Считываем только текущий элемент со всеми его дочерними узлами
УзелDOM = ПостроительDOM.Прочитать(ЧтениеXML);
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
ЗаписьDOM = Новый ЗаписьDOM;
ЗаписьDOM.Записать(УзелDOM, ЗаписьXML);
ТекстУзлаXML = ЗаписьXML.Закрыть();
Прервать; // Узел получен
КонецЕсли;
КонецЦикла;
ЧтениеXML.Закрыть();
Если XML-структура описывает объекты 1С или соответствует стандартной сериализации, для преобразования элемента в строку можно применить ФабрикаXDTO. Когда ЧтениеXML находится на начальном теге объекта, мы считываем его в объект XDTO, а затем записываем обратно в XML-строку.
Рассмотрим пример реализации:
Пока ЧтениеXML.Прочитать() Цикл
Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "CatalogObject.Справочник1" Тогда
ОбъектXDTO = ФабрикаXDTO.ПрочитатьXML(ЧтениеXML);
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
ФабрикаXDTO.ЗаписатьXML(ЗаписьXML, ОбъектXDTO);
ТекстУзлаXML = ЗаписьXML.Закрыть();
Прервать;
КонецЕсли;
КонецЦикла;
Для небольших XML-файлов проще всего использовать Загрузку в DOM целиком с поиском нужного тега через XPath. Если файл имеет большой объем и нужно сохранить производительность системы, рекомендуется использовать частичное считывание в DOM или Фабрику XDTO прямо в процессе потокового чтения объекта ЧтениеXML.