Часто перед разработчиком стоит задача прочитать XML-файл, структура которого заранее неизвестна или может меняться. Стандартный подход с жестким перебором имен узлов через условия Если ЧтениеXML.Имя = "Товар" Тогда крайне неудобен, так как требует переписывания кода под каждый новый формат. В этой статье мы разберем, как создать универсальный механизм, который сможет «переварить» любой XML и представить его в удобном для 1С виде, например, в дереве значений или применив XSLT-визуализацию для создания красивого отчета.
Типичная ошибка новичка — пытаться угадать структуру файла. Рассмотрим пример кода, который часто встречается на форумах и который не является универсальным:
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ПутьКФайлу);
Пока ЧтениеXML.Прочитать() Цикл
Если ЧтениеXML.Имя = "Nomenclatura" И ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
// Здесь начинается жесткая привязка к полям
ИмяТекущегоУзла = "Nomenclatura";
КонецЕсли;
КонецЦикла;
Проанализируем эту ситуацию: как только в файле изменится имя тега Nomenclatura на Items, код перестанет работать. Чтобы избежать этого, особенно когда требуется проводить точное сравнение XML-документов в процессе разработки, нам нужно использовать методы, которые извлекают имена узлов и их значения динамически.
Это самый эффективный метод для работы с файлами любого объема. Мы будем использовать объект ЧтениеXML и рекурсивную функцию. Суть заключается в том, что программа «идет» по дереву XML и для каждого найденного элемента создает строку в ДеревоЗначений.
Рассмотрим пример реализации такой функции. Мы не будем проверять конкретные имена, а будем брать свойство Имя самого узла:
Процедура ПрочитатьУзелРекурсивно(ЧтениеXML, ТекущаяСтрокаДерева)
Пока ЧтениеXML.Прочитать() Цикл
ТипУзла = ЧтениеXML.ТипУзла;
Если ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
НоваяСтрока = ТекущаяСтрокаДерева.Строки.Добавить();
НоваяСтрока.ИмяУзла = ЧтениеXML.Имя;
// Читаем атрибуты, если они есть
Пока ЧтениеXML.ПрочитатьАтрибут() Цикл
НоваяСтрока.Атрибуты = НоваяСтрока.Атрибуты + ЧтениеXML.Имя + " = " + ЧтениеXML.Значение + "; ";
КонецЦикла;
// Рекурсивный вызов для вложенных узлов
ПрочитатьУзелРекурсивно(ЧтениеXML, НоваяСтрока);
ИначеЕсли ТипУзла = ТипУзлаXML.Текст Тогда
ТекущаяСтрокаДерева.ЗначениеУзла = ЧтениеXML.Значение;
ИначеЕсли ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
Возврат;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
В данном примере мы используем объект ДеревоЗначений с колонками ИмяУзла, ЗначениеУзла и Атрибуты. Такой подход позволяет визуализировать структуру любого XML в виде иерархии прямо на форме 1С.
Если файл имеет разумный объем (до 50-100 Мб), мы можем воспользоваться моделью DOM (Document Object Model). Этот метод позволяет загрузить весь XML в память и обращаться к его узлам как к объектам. Выясним преимущества этого способа: нам не нужно следить за курсором чтения, мы можем перемещаться по дереву вверх и вниз.
Разберем по шагам работу с ПостроительDOM:
ЧтениеXML и открываем файл.ПостроительDOM и получаем ДокументDOM.ДочерниеУзлы.
Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл(ПутьКФайлу);
Построитель = Новый ПостроительDOM;
ДокументDOM = Построитель.Прочитать(Чтение);
// Теперь можно получить коренной элемент и начать обход
КорневойУзел = ДокументDOM.ЭлементДокумента;
Для Каждого Узел Из КорневойУзел.ДочерниеУзлы Цикл
// Обработка узла
КонецЦикла;
Важный момент: использование DOM требует значительных ресурсов оперативной памяти. Для «любых» (в том числе гигантских) файлов этот метод может не подойти, вызвав ошибку нехватки памяти.
Метод ПрочитатьXML глобальной фабрики XDTO — это, пожалуй, самый «красивый» способ в 1С. Если у вас нет схемы XSD, 1С попытается прочитать XML в объект типа ОбъектXDTO с динамическим типом данных. Проанализируем, как это работает:
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ПутьКФайлу);
Данные = ФабрикаXDTO.ПрочитатьXML(ЧтениеXML);
// Теперь 'Данные' — это объект XDTO, свойства которого соответствуют тегам XML
Преимущество этого метода в том, что вы получаете готовую объектную структуру. Если в XML есть повторяющиеся теги, фабрика автоматически создаст список, который можно обойти циклом. Однако, если структура файла слишком специфична, фабрика может выдать ошибку без наличия схемы.
Если ваша конфигурация основана на «Библиотеке стандартных подсистем» (БСП), вам не нужно изобретать велосипед. Проанализируем возможности общего модуля ОбщегоНазначения. В нем часто присутствует функция ПрочитатьXMLВСтруктуру или аналогичные инструменты для работы с XDTO. Чтобы быстро находить нужные команды в библиотеке, разработчикам полезно иметь под рукой справочник по методам БСП с примерами использования.
Использование БСП гарантирует, что код будет соответствовать стандартам 1С и корректно обрабатывать различные кодировки и спецсимволы.
Чтобы выполнить пожелание пользователя и вывести результат в ТабличныйДокумент, мы рекомендуем использовать алгоритм рекурсивного обхода дерева значений. .
Алгоритм вывода в таблицу:
ДеревоЗначений (Метод 1).Область.Текст для вывода имени узла в первую колонку, а значения — во вторую.Посмотрим на пример вывода:
Процедура ВывестиДеревоВТабДок(СтрокиДерева, ТабДок, Уровень = 0)
Для Каждого Строка Из СтрокиДерева Цикл
Область = ТабДок.ПолучитьОбласть("R" + Формат(ТабДок.ВысотаТаблицы + 1, "ЧГ=0") + "C1:C2");
Область.Область(1, 1).Текст = Строка.ИмяУзла;
Область.Область(1, 1).Отступ = Уровень;
Область.Область(1, 2).Текст = Строка.ЗначениеУзла;
ТабДок.Вывести(Область);
// Рекурсия для дочерних элементов
ВывестиДеревоВТабДок(Строка.Строки, ТабДок, Уровень + 1);
КонецЦикла;
КонецПроцедуры
При работе с действительно универсальным чтением не забудьте про пространства имен (Namespaces). Если файл содержит префиксы вроде <v8:item>, стандартное свойство Имя вернет строку "v8:item". Чтобы получить чистые данные, используйте свойство ЛокальноеИмя.
Также помним про атрибуты. В XML данные могут храниться как внутри тегов, так и в их атрибутах (например, <Item ID="001">). Универсальный парсер обязан проверять ЧтениеXML.КоличествоАтрибутов() и считывать их через ЧтениеXML.ЗначениеАтрибута(), иначе часть информации будет потеряна.
Рассмотренные нами подходы позволяют создать мощный инструмент для анализа любых входящих данных, обеспечивая гибкость интеграций и удобство отладки при работе со сторонними системами.