Как оптимальнее всего прочитать и обновить только конкретное поле в XML-файле?
Всем привет! Есть задача, прочитать xml-файл, загрузить из него объекты данных, записать в этот файл идентификаторы (ГУИД) загруженных объектов в нужное поле и вернуть файл назад уже с записанными идентификаторами, ничего в нем больше не изменяя.
Вопрос: как наиболее быстро это сделать? Иными словами, можно ли обновить в xml-файле только нужное поле, не считывая/перезаписывая файл повторно целиком?
Вопрос: как наиболее быстро это сделать? Иными словами, можно ли обновить в xml-файле только нужное поле, не считывая/перезаписывая файл повторно целиком?
Найденные решения
(2),
(5),
(12), Сделал следующим образом: у объекта ЗаписьXML есть метод "ЗаписатьТекущий", который записывает текущий элемент xml. На вход подается объект ЧтениеXML. Таким образом, можно записать XML и подменить только нужные поля.
(5),
(12), Сделал следующим образом: у объекта ЗаписьXML есть метод "ЗаписатьТекущий", который записывает текущий элемент xml. На вход подается объект ЧтениеXML. Таким образом, можно записать XML и подменить только нужные поля.
// добавить нужные имена для замены
РезультатОбработкиСообщения = Новый Структура();
РезультатОбработкиСообщения.Вставить("СтатусОбработки", "");
РезультатОбработкиСообщения.Добавить("ОписаниеОшибки", "");
Пока ЧтениеXML.Прочитать() Цикл
Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
УзелПишемЗначение = РезультатОбработкиСообщения.Свойство(ЧтениеXML.ЛокальноеИмя);
ЗначениеЗаписано = Ложь;
Если УзелПишемЗначение И ЗначениеЗаполнено(РезультатОбработкиСообщения[ЧтениеXML.ЛокальноеИмя]) Тогда
ЗаписьXML.ЗаписатьНачалоЭлемента(ЧтениеXML.ЛокальноеИмя);
//Убираем, если необходимо, атрибут "nil"
Пока ЧтениеXML.ПрочитатьАтрибут() Цикл
Если ЧтениеXML.ЛокальноеИмя <> "nil" Тогда
ЗаписьXML.ЗаписатьАтрибут(ЧтениеXML.Префикс + ":" + ЧтениеXML.ЛокальноеИмя, ЧтениеXML.Значение);
КонецЕсли;
КонецЦикла;
Продолжить;
Иначе
ЗаписьXML.ЗаписатьТекущий(ЧтениеXML);
КонецЕсли;
ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.Текст И УзелПишемЗначение Тогда
//Присваиваем новое значение тега XML
ЗаписьXML.ЗаписатьТекст(РезультатОбработкиСообщения[ЧтениеXML.ЛокальноеИмя]);
ЗначениеЗаписано = Истина;
ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента И УзелПишемЗначение Тогда
//Если элемент был с пустым значением, оно будет записываться перед концом элемента
Если НЕ ЗначениеЗаписано Тогда
ЗаписьXML.ЗаписатьТекст(РезультатОбработкиСообщения[ЧтениеXML.ЛокальноеИмя]);
ЗначениеЗаписано = Истина;
КонецЕсли;
УзелПишемЗначение = Ложь;
ЗаписьXML.ЗаписатьТекущий(ЧтениеXML);
Иначе
ЗаписьXML.ЗаписатьТекущий(ЧтениеXML);
КонецЕсли;
КонецЦикла;
ПоказатьОстальные ответы
Подписаться на ответы
Инфостарт бот
Сортировка:
Древо развёрнутое
Свернуть все
Читать через ФабрикаXDTO, записывать ГУИД сразу же в момент создания объекта, в этот момент вы в цикле как раз будете иметь доступ к текущему объекту XDTO.
UPD: вот на коленке пример набросал.
UPD: вот на коленке пример набросал.
Прикрепленные файлы:
ЧтениеИИзменениеXDTO.epf
(2)
и сразу после получения ГУИДа, пока объект XDTO еще существует, записывать его назад в файл?
Не знаю, подойдет ли этот вариант, т.к. в файле могут быть несколько разных пространств имен. Например, элемент <Head> относится к пространству имен "http://www.1c.ru/SSL/Exchange/Message", а <body> - свой кастомный пакет
ФабрикаXDTO, записывать ГУИД сразу же в момент создания объекта, в этот момент вы в цикле как раз будете иметь доступ к текущему объекту XDTO.
и сразу после получения ГУИДа, пока объект XDTO еще существует, записывать его назад в файл?
Не знаю, подойдет ли этот вариант, т.к. в файле могут быть несколько разных пространств имен. Например, элемент <Head> относится к пространству имен "http://www.1c.ru/SSL/Exchange/Message", а <body> - свой кастомный пакет
(5)Кстати, как вариант) Иметь в файле заглушку в виде "#МЕСТОДЛЯИД#, в массиве хранить гуиды и просто по порядку вхождения заменять. Кстати, средства работы со строками даже на очень длинных строках(проверял на файлах с текстом по 50 Мб) работают мгновенно, чего не скажешь про средства работы с XML.
1. Прочитать файл, накопить объектные соответствия в соответствии (ИД из файла, ИД из программы).
2. Прочитать файл целиком в строку текста.
3. Для Каждого С ИЗ Соответствие Цикл Строка = СтрЗаменить(Строка, С.Ключ, С.Значение) КонецЦикла.
4. Записать файл. Старый для истории переименовать в .xmlold.
2. Прочитать файл целиком в строку текста.
3. Для Каждого С ИЗ Соответствие Цикл Строка = СтрЗаменить(Строка, С.Ключ, С.Значение) КонецЦикла.
4. Записать файл. Старый для истории переименовать в .xmlold.
(2),
(5),
(12), Сделал следующим образом: у объекта ЗаписьXML есть метод "ЗаписатьТекущий", который записывает текущий элемент xml. На вход подается объект ЧтениеXML. Таким образом, можно записать XML и подменить только нужные поля.
(5),
(12), Сделал следующим образом: у объекта ЗаписьXML есть метод "ЗаписатьТекущий", который записывает текущий элемент xml. На вход подается объект ЧтениеXML. Таким образом, можно записать XML и подменить только нужные поля.
// добавить нужные имена для замены
РезультатОбработкиСообщения = Новый Структура();
РезультатОбработкиСообщения.Вставить("СтатусОбработки", "");
РезультатОбработкиСообщения.Добавить("ОписаниеОшибки", "");
Пока ЧтениеXML.Прочитать() Цикл
Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
УзелПишемЗначение = РезультатОбработкиСообщения.Свойство(ЧтениеXML.ЛокальноеИмя);
ЗначениеЗаписано = Ложь;
Если УзелПишемЗначение И ЗначениеЗаполнено(РезультатОбработкиСообщения[ЧтениеXML.ЛокальноеИмя]) Тогда
ЗаписьXML.ЗаписатьНачалоЭлемента(ЧтениеXML.ЛокальноеИмя);
//Убираем, если необходимо, атрибут "nil"
Пока ЧтениеXML.ПрочитатьАтрибут() Цикл
Если ЧтениеXML.ЛокальноеИмя <> "nil" Тогда
ЗаписьXML.ЗаписатьАтрибут(ЧтениеXML.Префикс + ":" + ЧтениеXML.ЛокальноеИмя, ЧтениеXML.Значение);
КонецЕсли;
КонецЦикла;
Продолжить;
Иначе
ЗаписьXML.ЗаписатьТекущий(ЧтениеXML);
КонецЕсли;
ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.Текст И УзелПишемЗначение Тогда
//Присваиваем новое значение тега XML
ЗаписьXML.ЗаписатьТекст(РезультатОбработкиСообщения[ЧтениеXML.ЛокальноеИмя]);
ЗначениеЗаписано = Истина;
ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента И УзелПишемЗначение Тогда
//Если элемент был с пустым значением, оно будет записываться перед концом элемента
Если НЕ ЗначениеЗаписано Тогда
ЗаписьXML.ЗаписатьТекст(РезультатОбработкиСообщения[ЧтениеXML.ЛокальноеИмя]);
ЗначениеЗаписано = Истина;
КонецЕсли;
УзелПишемЗначение = Ложь;
ЗаписьXML.ЗаписатьТекущий(ЧтениеXML);
Иначе
ЗаписьXML.ЗаписатьТекущий(ЧтениеXML);
КонецЕсли;
КонецЦикла;
Показать
Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот