При интеграции с внешними системами и обмене данными часто возникает задача фильтрации и разделения одного XML-файла со сложной вложенной структурой (например, список пациентов с поддеревом их счетов) на два разных файла в зависимости от определенного признака (например, наличный или безналичный расчет).
Рассмотрим основные способы решения этой задачи в платформе 1С:Предприятие, проанализируем их плюсы, минусы и особенности реализации.
Если в системе есть XSD-схема или объект описан в пакете XDTO, самым удобным и лаконичным способом является работа с объектом ОбъектXDTO. Суть метода заключается в загрузке исходного файла и последующем удалении лишних узлов из коллекций для каждого итогового файла.
Разберем по шагам алгоритм работы с XDTO:
ЧтениеXML и метода ФабрикаXDTO.ПрочитатьXML().СписокXDTO.ЗаписьXML и ФабрикаXDTO.ЗаписатьXML().Важная особенность: Списочные свойства элементов XDTO представляют собой коллекцию СписокXDTO. При удалении элементов из СписокXDTO метод Удалить(Индекс) смещает индексы оставшихся элементов. Поэтому обход списка необходимо выполнять строго в обратном порядке — с конца в начало.
Рассмотрим пример кода для очистки списка счетов в объекте XDTO:
// Пример обхода коллекции XDTO в обратном порядке
Для Каждого Пациент Из ОбъектXDTO.Пациенты Цикл
СписокСчетов = Пациент.Счета;
ВсегоСчетов = СписокСчетов.Количество();
Для Индекс = 1 По ВсегоСчетов Цикл
ОбратныйИндекс = ВсегоСчетов - Индекс;
ТекущийСчет = СписокСчетов.Получить(ОбратныйИндекс);
// Для первого файла удаляем безналичные счета
Если ТекущийСчет.ВидОплаты = "Безнал" Тогда
СписокСчетов.Удалить(ОбратныйИндекс);
КонецЕсли;
КонецЦикла;
КонецЦикла;
Если XSD-схема отсутствует или работа с XDTO по какому-то параметру не подходит, можно построить промежуточную структуру данных с помощью объекта ДеревоЗначений.
Рассмотрим порядок действий для этого способа:
ЧтениеXML рекурсивно или поуровнево читаем исходный файл и заполняем ДеревоЗначений, воспроизводя иерархию узлов (вложенность порядка 8 уровней).ЗаписьXML последовательно выгружаем оба дерева значений обратно в XML-формат.Если исходный XML-файл имеет очень большой объем (сотни мегабайт или гигабайты), загрузка полного дерева в память через ОбъектXDTO или ДеревоЗначений может привести к вызову ошибки нехватки памяти (Out of Memory). В таком случае оптимальным решением является последовательное чтение и параллельная запись.
Проанализируем алгоритм потоковой обработки:
ЧтениеXML.ЗаписьXML для файла 1 (Наличные) и файла 2 (Безналичные).Этот подход требует больше кода для управления состоянием записи XML, но обеспечивает максимальную скорость работы и минимальный расход оперативной памяти.
Для небольших и средних файлов также доступен механизм DOM платформы 1С. С помощью объекта ПостроительDOM загружаем XML в объект ДокументDOM.
Далее выполняем обход узлов и удаляем не подходящие элементы вызовом метода УдалитьДочерний(). После модификации сохраняем документ в файл с помощью объекта ЗаписьDOM.
СписокXDTO в обратном порядке (от конца к началу).ЧтениеXML и два объекта ЗаписьXML.ДеревоЗначений.