|
v7: Чем заменить AddIn.XMLParser от v7plus.dll | ☑ | ||
---|---|---|---|---|
0
basily
25.04.22
✎
10:24
|
Необходимо переписать обработку использующую СоздатьОбъект("AddIn.XMLParser") от v7plus.dll на что-то другое ей подобное с аналогичными методами перебора дабы не сильно менять код. Подойдёт ли СоздатьОбъект("Microsoft.XMLDOM")? И какие это будут методы? Пример из кода:
гXMLАнализатор = СоздатьОбъект("AddIn.XMLParser"); гФайл = гXMLАнализатор.СоздатьПоследовательноСчитываемыйДокумент(); гФайл.СвязатьСФайлом(ФормИмяФайлаДанных); ТипТега = гФайл.Спуститься(); Объект = гФайл.ТекущийЭлементВВидеОбъекта(); УзелBody = Объект.ВыбратьУзел("Body"); УзлыДанных = УзелBody.ВыбратьУзлы(ИмяУзла); Количество = УзлыДанных.КоличествоУзлов(); Для СчДанных = 0 По Количество - 1 Цикл УзелДанных = УзлыДанных.ПолучитьУзел(СчДанных); Реквизиты = УзелДанных.ВыбратьУзел("КлючевыеСвойства"); Для Сч = 1 По Реквизиты.КоличествоПодчиненных() Цикл Реквизит = Реквизиты.ПолучитьПодчиненныйПоНомеру(Сч); ... |
|||
1
youalex
25.04.22
✎
10:30
|
||||
2
MWWRuza
гуру
25.04.22
✎
10:45
|
Вот такой использую: XML_DOM=CreateObject("MSXML2.DOMDocument.6.0");
Если интересно, могу куски кода выложить. С парсером из v7plus, отличия в коде будут, и большие. Но, все решаемо. А с парсером из v7plus, у меня с самого начала что-то не заладилось, не нравится он мне. |
|||
3
basily
25.04.22
✎
10:52
|
(1) Спасибо за наводку.
(2) Покажите пример кода, пожалуйста. |
|||
4
MWWRuza
гуру
25.04.22
✎
11:05
|
(3) Ну,мне сейчас некогда специальные демо-примеры писать, попробуйте с готовыми, рабочими функциями из программы разобраться. Это "общение" 1с77 с ФСРАР УТМ. Будет не понятно, пишите, прокоментирую:
Загрузка DOOM из запроса к УТМ(есть аналогичная функция загрузки из файла, если надо): Функция ЗагрузитьDOM(URL,Вер = 1) Экспорт Скрипт = СоздатьОбъект("MSScriptControl.ScriptControl"); Скрипт.language="vbscript"; Это = Скрипт.Eval("this"); Если Константа.ВсегдаИспользоватьCurl = 0 Тогда WinHttp = СоздатьОбъект("WinHttp.WinHttpRequest.5.1"); Скрипт.AddObject("WinHttp",WinHttp); WinHttp.Open("GET", URL, 0); Попытка WinHttp.Send(); Исключение Сообщить("Служба УТМ не запущена, невозможно получить список входящих документов!"); Возврат ""; КонецПопытки; Если WinHTTP.Status<>200 Тогда Предупреждение("Не удалось загрузить документ. Возможно он удалён или служба УТМ не запущена."); Возврат ""; КонецЕсли; Стрим = СоздатьОбъект("ADODB.Stream"); Стрим.Mode = 3; Стрим.Type = 1; Стрим.Open(); Скрипт.AddObject("Stream",Стрим); Размер = Скрипт.Eval("LenB(WinHttp.responseBody)"); Иначе Стрим = СоздатьОбъект("ADODB.Stream"); Стрим.Mode = 3; Стрим.Type = 1; Стрим.Open(); Размер = 0; КонецЕсли; XML_DOM=CreateObject("MSXML2.DOMDocument.6.0"); WShell = СоздатьОбъект("WScript.Shell"); ВременнаяПапка = WShell.ExpandEnvironmentStrings("%TEMP%") + "\"; ПутьВременногоФайла = ПолучитьИмяВременногоФайла(ВременнаяПапка); Если (Размер > 570*1024) ИЛИ (Константа.ВсегдаИспользоватьCurl = 1) Тогда // 1С падает, если размер файла больше 570 Кб Команда = "curl " + URL + " > " + ПутьВременногоФайла; КодВозврата = WShell.Run("%COMSPEC% /C "+Команда, 0, 1); Если КодВозврата <> 0 Тогда Предупреждение("Невозможно получить XML-файл. Возможно не установлен cUrl."); Сообщить("Пожалуйста, проверьте что УТМ запущен, а файл curl.exe (http://curl.haxx.se/download.html) | скопирован в папку Windows."); Возврат ""; КонецЕсли; XML_DOM.Load(ПутьВременногоФайла); ФС.УдалитьФайл(ПутьВременногоФайла); Иначе Скрипт.Eval("Stream.Write(WinHttp.responseBody)"); Стрим.Position = 0; Стрим.Type = 2; Стрим.Charset = "utf-8"; Ответ = Стрим.ReadText(); Стрим.Close(); XML_DOM.LoadXML(Ответ); КонецЕсли; XML_DOM.setProperty("SelectionLanguage", "XPath"); nodDoc = XML_DOM.DocumentElement.selectSingleNode("/*"); ТабПреф.УдалитьСтроки(); // Очистим таблицу содержащуюся в глобальной переменной от предыдущих соответствий ЗаполнитьТабПростИмен(nodDoc); ТабПреф.Свернуть("СтПреф,НовПреф,URL","Сверт"); Если ТабПреф.КоличествоСтрок() > 0 Тогда ТзСтПреф = ПолучитьТзСтандартныхПрефиксов(); StrNameSpase = ""; ТабПреф.ВыбратьСтроки(); Пока ТабПреф.ПолучитьСтроку() = 1 Цикл СтрТЗСтПреф = ""; Если ТзСтПреф.НайтиЗначение(ТабПреф.URL, СтрТЗСтПреф,"URL") = 1 Тогда ТабПреф.СтПреф = ТзСтПреф.ПолучитьЗначение(СтрТЗСтПреф,"СтПреф"); КонецЕсли; ПрефNS = ТабПреф.НовПреф; URLns = ТабПреф.URL; ПрострИмен = " " + "xmlns:" + ПрефNS + "=" + "'" + URLns + "'"; StrNameSpase = StrNameSpase + ПрострИмен; КонецЦикла; StrNameSpase = СокрП(StrNameSpase); Если СокрЛП(StrNameSpase) <> "" Тогда XML_DOM.setProperty("SelectionNamespaces", StrNameSpase); КонецЕсли; КонецЕсли; Возврат XML_DOM; КонецФункции А эта функция парсит полученный DOOM(в данном случае, это получение информации по АлкоКоду): Функция ПолучитьОтветАК(ИдЗапроса, УТМ_URL) СзОтвета = СоздатьОбъект("СписокЗначений"); ДокументыУдалены = 1; НомерПопытки = 0; ReplyId = ""; ПолученОтвет = 0; Пока (ДокументыУдалены > 0) И (НомерПопытки < 5) Цикл Если ДокументыУдалены > 0 Тогда ДокументыУдалены = 0; КонецЕсли; НомерПопытки = НомерПопытки + 1; XML_DOM = ЗагрузитьDOM(УТМ_URL+"opt/out"); Если ПустоеЗначение(XML_DOM) = 1 Тогда Возврат ""; КонецЕсли; Если XML_DOM.parseError.errorCode <> 0 Тогда Сообщить("Невозможно прочитать список входящих документов: " + XML_DOM.parseError.reason); Возврат ""; КонецЕсли; NodesList = XML_DOM.getElementsByTagName("url"); Для инд = 0 по NodesList.Length - 1 Цикл Node = NodesList.Item(инд); URL = СокрЛП(Node.Text); RegExp.Pattern = "http://.*/opt/_?out/(.*)/(\d+)"; Matches=RegExp.Execute(URL); Если Matches.Count() > 0 Тогда DocType = Matches.Item(0).SubMatches.Item(0); DocNumber = Matches.Item(0).SubMatches.Item(1); DocName = ПолучитьНазваниеДокумента(DocType) + " №" + DocNumber; Иначе DocName = Node.Text; СтрЗаменить(DocName, УТМ_URL, ""); КонецЕсли; Попытка ReplyId = СокрЛП(Node.attributes.getNamedItem("replyId").value); Исключение КонецПопытки; Если ReplyId = ИдЗапроса Тогда ReplyAP = ЗагрузитьDOM(URL,2); Product = ReplyAP.selectSingleNode("/ns:Documents/ns:Document/ns:ReplyAP_v2/rap:Products/rap:Product"); СзОтвета.ДобавитьЗначение(Product.selectSingleNode("./pref:FullName").text); // 1 СзОтвета.ДобавитьЗначение(Product.selectSingleNode("./pref:AlcCode").text); // 2 ТипУпаковки = Product.selectSingleNode("./pref:UnitType").text; СзОтвета.ДобавитьЗначение(ТипУпаковки); // 3 Если ТипУпаковки = "Packed" Тогда Объем = Product.selectSingleNode("./pref:Capacity").text; Иначе Объем = 0; КонецЕсли; СзОтвета.ДобавитьЗначение(Объем); // 4 СзОтвета.ДобавитьЗначение(Product.selectSingleNode("./pref:AlcVolume").text); // 5 СзОтвета.ДобавитьЗначение(Product.selectSingleNode("./pref:ProductVCode").text); // 6 Producer = Product.selectSingleNode("./pref:Producer"); ТипКонтрагента = Прав(Producer.firstChild.nodeName,2); Если ТипКонтрагента = "UL" Тогда СзОтвета.ДобавитьЗначение(Перечисление.ВидКонтрЕГАИС.UL); // 7 ИначеЕсли ТипКонтрагента = "FL" Тогда СзОтвета.ДобавитьЗначение(Перечисление.ВидКонтрЕГАИС.FL); // 7 ИначеЕсли ТипКонтрагента = "FO" Тогда СзОтвета.ДобавитьЗначение(Перечисление.ВидКонтрЕГАИС.FO); // 7 Иначе СзОтвета.ДобавитьЗначение(Перечисление.ВидКонтрЕГАИС.TS); // 7 КонецЕсли; TipKontr = Producer.firstChild; СзОтвета.ДобавитьЗначение(TipKontr.selectSingleNode("./oref:ClientRegId").text); // 8 СзОтвета.ДобавитьЗначение(TipKontr.selectSingleNode("./oref:ShortName").text); // 9 СзОтвета.ДобавитьЗначение(TipKontr.selectSingleNode("./oref:FullName").text); // 10 СзОтвета.ДобавитьЗначение(TipKontr.selectSingleNode("./oref:address/oref:Country").text); // 11 Попытка ПроизводительИНН = TipKontr.selectSingleNode("./oref:INN").text; Исключение ПроизводительИНН = ""; КонецПопытки; СзОтвета.ДобавитьЗначение(ПроизводительИНН); // 12 Попытка ПроизводительКПП = TipKontr.selectSingleNode("./oref:KPP").text; Исключение ПроизводительКПП = ""; КонецПопытки; СзОтвета.ДобавитьЗначение(ПроизводительКПП); // 13 Попытка ПроизвКодРегиона = TipKontr.selectSingleNode("./oref:address/oref:RegionCode").text; Исключение ПроизвКодРегиона = ""; КонецПопытки; СзОтвета.ДобавитьЗначение(ПроизвКодРегиона); // 14 Попытка ПроизвАдрес = TipKontr.selectSingleNode("./oref:address/oref:description").text; Исключение ПроизвАдрес = ""; КонецПопытки; СзОтвета.ДобавитьЗначение(ПроизвАдрес); // 15 УдалитьИсходящийЗапрос(ReplyId,УТМ_URL); УдалитьДокумент(URL); Возврат СзОтвета; КонецЕсли; КонецЦикла; КонецЦикла; КонецФункции |
|||
5
MWWRuza
гуру
25.04.22
✎
11:08
|
Там общий принцип: выбираете узлы, потом к ним можно в цикле обращаться по индексам. Если это "конечный" узел, без вложенности, то можно получить его содержимое через ".text".
|
|||
6
Злопчинский
25.04.22
✎
11:11
|
работа с XML есть в 1С++
есть вк OpenXML от Ромикса |
|||
7
MWWRuza
гуру
25.04.22
✎
11:22
|
(6) Ну, да... Короче, вариантов куча, кому чем удобнее, или кто к чему привык. Но, родная v7plus в этом отношении, далеко не самая лучшая.
|
|||
8
Злопчинский
25.04.22
✎
11:35
|
//**************************************************************************************
// Процедура ОбработатьУзел(Узел, Уровень=0) Состояние(Уровень); Если СЗузлы.НайтиЗначение(Врег(Узел.tagName)) = 0 Тогда Стр = Формат("","С"+Уровень*8); Сообщить(Стр + "<--- узел не обрабатывается согласно установленным ограничениям -->"); Возврат; КонецЕсли; КолвоУзлов = Узел.childNodes.length; Для СчУзлов = 0 По КолвоУзлов-1 Цикл ТекУзел = Узел.childNodes.item(СчУзлов); Если ТекУзел.nodeType <> 1 Тогда Продолжить; КонецЕсли; Стр = Формат("","С"+Уровень*8); СтрАтрибуты = ""; Для счАтрибутов = 0 По ТекУзел.attributes.length-1 Цикл Атрибут = ТекУзел.attributes.item(счАтрибутов); СтрАтрибуты = СтрАтрибуты + ?(СтрАтрибуты="","",";") + Атрибут.nodename+"="+Атрибут.value; КонецЦикла; ТекстУзла = ""; Если ТекУзел.childNodes.length = 1 Тогда Если ТекУзел.childNodes.item(0).nodetype = 3 Тогда ТекстУзла = ТекУзел.childNodes.item(0).text; КонецЕсли; КонецЕсли; Стр = Стр + ТекУзел.tagName + ?(СтрАтрибуты="","","("+СтрАтрибуты+")" ) + ": " +ТекстУзла; Сообщить(Стр); ОбработатьУзел(ТекУзел, Уровень+1); КонецЦикла; Состояние(""); КонецПроцедуры // ОбработатьУзел() |
|||
9
Злопчинский
25.04.22
✎
11:36
|
Иксемель = СоздатьОбъект("Microsoft.XMLDOM");
Иксемель.Load(ФайлДанных); Корень = Иксемель.DocumentElement; Результат = ВыполнитьУзел(Корень,0); //ОбработатьУзел(Корень, 0); //тест чтения Иксемель = ""; |
|||
10
victuan1
25.04.22
✎
14:05
|
(2) > С парсером из v7plus, отличия в коде будут, и большие.
В принципе, те же яйца, но в профиль. Ведь v7plus использует ту же библиотеку msxml Я даже написал универсальные ф-и, инкапсулируя методы v7plus и msxml. Получилось что-то вроде такого: //_____________________________________________________________________________ Функция КомпонентаV7plusЗагрузить() Экспорт //0 - не было еще попытки загрузить, -1 - не получилось загрузить, 1 - получилось загрузить со старой версией анализатора, 2 - получилось загрузить с новой версией анализатора Если число(КомпонентаV7plusЗагружена) >= 1 Тогда // уже загружена успешно //ИначеЕсли КомпонентаV7plusЗагружена = -1 Тогда // была ошибка при попытке загрузить, но будет пытаться еще раз загрузить (вдруг пользователь подсунул файл ВК в нужную папку) Иначе Если ПустоеЗначение(КомпонентаV7plusЗагружена) = 1 Тогда Попытка // возможно была загружена ПарсерХМЛ = СоздатьОбъект("AddIn.XMLParser"); ПарсерХМЛ = 0; КомпонентаV7plusЗагружена = 1 Исключение КонецПопытки; КонецЕсли; //Загрузим внешнюю компоненту V7Plus.dll Если КомпонентаV7plusЗагружена = 1 Тогда ИначеЕсли ЗагрузитьВК("v7plus.dll") <> 1 Тогда КомпонентаV7plusЗагружена = -1; Возврат КомпонентаV7plusЗагружена КонецЕсли; Попытка ПарсерХМЛ = СоздатьОбъект("AddIn.XMLParser"); ВерсияАнализатора = ПарсерХМЛ.ВерсияАнализатора; ВерсияБазовогоАнализатора = ПарсерХМЛ.ВерсияБазовогоАнализатора; ПарсерХМЛ = 0; КомпонентаV7plusЗагружена = 1; //по умолчанию, ВК V7plus не загружена (возможные состояния: 0/1/2/-1 не загружена/загружена/загружена с огран./невозможно загрузить) Исключение КомпонентаV7plusЗагружена = -1; // что-то все-таки не получилось Возврат КомпонентаV7plusЗагружена; КонецПопытки; Если ((ВерсияАнализатора <> "2.0")и(ВерсияАнализатора <> "1.0")) или (ВерсияБазовогоАнализатора <> "3.0") Тогда Если (ВерсияАнализатора <> "2.0") или (число(ВерсияБазовогоАнализатора) < 4) Тогда сообщить("Обнаружена версия анализатора / базового анализатора XML-парсера (msxml.dll): "+ВерсияАнализатора+" / "+ВерсияБазовогоАнализатора); сообщить("Должны быть версия анализатора / базового анализатора XML-парсера (msxml.dll): 2.0 / 3.0"); сообщить("Отключите в 'Индивид.настройках' использование v7plus.dll или перерегистрируйте библиотеки, выполнив инструкцию ПеререгистрацияБиблиотек.txt в архиве regdllview-x32.zip из комплекта поставки, иначе возможны ошибки при обработке файлов XML"); КонецЕсли; КомпонентаV7plusЗагружена = 2; //будем использовать методы как для XML DOM КонецЕсли КонецЕсли; Возврат КомпонентаV7plusЗагружена; КонецФункции //_____________________________________________________________________________ Функция ПолучитьДокументИзФайла(ПолноеИмяФайла) Экспорт Если ИспользоватьV7plus = 0 Тогда Попытка ХМЛ = СоздатьОбъект("Msxml2.DOMDocument.6.0"); Исключение Попытка ХМЛ = СоздатьОбъект("Msxml2.DOMDocument.4.0"); Исключение Попытка ХМЛ = СоздатьОбъект("Msxml2.DOMDocument"); Исключение ХМЛ = ""; сообщить(ОписаниеОшибки(),"!!"); Сообщить("В системе не установлена ни одна из библиотек MSXML!","!"); Возврат 0 КонецПопытки; КонецПопытки; КонецПопытки; ХМЛ.async=0; ХМЛ.validateOnParse=-1; ХМЛ.resolveExternals=-1; Иначе Попытка ПарсерХМЛ = СоздатьОбъект("AddIn.XMLParser"); ХМЛ = ПарсерХМЛ.СоздатьДокумент(); ПарсерХМЛ = 0; Исключение ПарсерХМЛ = 0; сообщить(ОписаниеОшибки(),"!!"); Возврат "" КонецПопытки; КонецЕсли; Попытка ХМЛ.load(ПолноеИмяФайла) Исключение сообщить(ОписаниеОшибки()+". Не удалось прочитать файл: "+ПолноеИмяФайла,"!!"); ХМЛ = "" КонецПопытки; //Если (ХМЛ.parseError.errorCode<>0) Тогда ??? - вывести список ошибок как в Алкодекларации? // // ошибки при проверке валидности // Сообщить("При проверке валидности файла "+ПолноеИмяФайла+" выявлены ошибки!","!"); // ХМЛ = 0 //КонецЕсли; Возврат ХМЛ КонецФункции //_____________________________________________________________________________ Функция ИмяУзла(Узел) Экспорт Если ПустоеЗначение(Узел) = 1 Тогда Возврат "" ИначеЕсли (ИспользоватьV7plus = 0) или (КомпонентаV7plusЗагружена = 2) Тогда Возврат Узел.NodeName Иначе Возврат Узел.Наименование КонецЕсли КонецФункции //_____________________________________________________________________________ Функция ЗнУзла(Узел) Экспорт//ф-я возвращает значение необязательного Узла (если этот узел существует) Если ПустоеЗначение(Узел)=1 Тогда Возврат "" ИначеЕсли (ИспользоватьV7plus = 0) или (КомпонентаV7plusЗагружена = 2) Тогда Возврат Узел.Text //??? сокрлп(Узел.Text) Иначе Возврат Узел.Значение //??? сокрлп(Узел.Значение) КонецЕсли КонецФункции //_____________________________________________________________________________ Функция ПолучитьАтрибутУзла(РодительскийЭлемент, Атрибут) Экспорт Если ПустоеЗначение(РодительскийЭлемент) = 1 Тогда Возврат "" ИначеЕсли (ИспользоватьV7plus = 0) или (КомпонентаV7plusЗагружена = 2) Тогда Возврат РодительскийЭлемент.getAttribute(Атрибут) Иначе Возврат РодительскийЭлемент.ПолучитьАтрибут(Атрибут) КонецЕсли КонецФункции //_____________________________________________________________________________ Функция ВыбратьУзелПоИмени(РодительскийЭлемент, ИмяЭлементаДляПоиска) Экспорт Если ПустоеЗначение(РодительскийЭлемент) = 1 Тогда Возврат ПолучитьПустоеЗначение() ИначеЕсли (ИспользоватьV7plus = 0) или (КомпонентаV7plusЗагружена = 2) Тогда Возврат РодительскийЭлемент.getElementsByTagName(ИмяЭлементаДляПоиска).item(0) Иначе Возврат РодительскийЭлемент.ВыбратьУзел(ИмяЭлементаДляПоиска) КонецЕсли КонецФункции //_____________________________________________________________________________ Функция ВыбратьУзел(РодительскийЭлемент, ИмяЭлементаДляПоиска, ПропускатьОшибки = 0) Экспорт Если ПустоеЗначение(РодительскийЭлемент) = 1 Тогда Возврат ПолучитьПустоеЗначение() ИначеЕсли (ИспользоватьV7plus = 0) или (КомпонентаV7plusЗагружена = 2) Тогда ИмяЭлементаДляПоиска = сред(ИмяЭлементаДляПоиска,Найти(ИмяЭлементаДляПоиска,":")+1); Для й = 0 По РодительскийЭлемент.ChildNodes.length-1 Цикл Узел = РодительскийЭлемент.ChildNodes.item(й); Если Узел.baseName = ИмяЭлементаДляПоиска Тогда Возврат Узел; КонецЕсли; КонецЦикла; Иначе Узел = РодительскийЭлемент.ВыбратьУзел(ИмяЭлементаДляПоиска); Если ПустоеЗначение(Узел)=0 Тогда Возврат Узел КонецЕсли; ИмяЭлементаДляПоиска = сред(ИмяЭлементаДляПоиска,Найти(ИмяЭлементаДляПоиска,":")+1); Для Индекс = 1 По РодительскийЭлемент.КоличествоПодчиненных() Цикл //заимствовано у Mrgnstrn (http://forum.fsrar.ru/viewtopic.php?p=244770#p244770) Если Нрег(РодительскийЭлемент.ПолучитьПодчиненныйПоНомеру(Индекс).Наименование) = Нрег(ИмяЭлементаДляПоиска) Тогда Возврат РодительскийЭлемент.ПолучитьПодчиненныйПоНомеру(Индекс); КонецЕсли; КонецЦикла; КонецЕсли; Если ПропускатьОшибки = 0 Тогда Сообщить("В файле XML не удалось найти элемент: " + ИмяЭлементаДляПоиска, "!"); КонецЕсли; Возврат ПолучитьПустоеЗначение() КонецФункции //_____________________________________________________________________________ Функция КоличествоПодчиненных(РодительскийЭлемент) Экспорт Если ПустоеЗначение(РодительскийЭлемент) = 1 Тогда Возврат ПолучитьПустоеЗначение() ИначеЕсли (ИспользоватьV7plus = 0) или (КомпонентаV7plusЗагружена = 2) Тогда Возврат РодительскийЭлемент.childNodes.length Иначе Возврат РодительскийЭлемент.КоличествоПодчиненных() КонецЕсли КонецФункции //_____________________________________________________________________________ Функция ПолучитьПодчиненныйПоНомеру(РодительскийЭлемент, Индекс) Экспорт Если ПустоеЗначение(РодительскийЭлемент) = 1 Тогда Возврат ПолучитьПустоеЗначение() ИначеЕсли (ИспользоватьV7plus = 0) или (КомпонентаV7plusЗагружена = 2) Тогда Возврат РодительскийЭлемент.childNodes(Индекс) Иначе Возврат РодительскийЭлемент.ПолучитьПодчиненныйПоНомеру(Индекс+1) КонецЕсли КонецФункции и т.д. |
|||
11
victuan1
25.04.22
✎
14:06
|
(10) Эти ф-и позволяют переключать что использовать: v7plus или msxml
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |