![]() |
![]() |
![]() |
|
v7: Загрузка XML-файла с неоднородной структурой | ☑ | ||
---|---|---|---|---|
0
gorlanovmax
02.02.16
✎
08:41
|
Доброго дня,
столкнулся с проблемой проблемой при загрузке XML-файла с неоднородной структурой. Пользуюсь компонентой OpenXML от Romix Имею файл вот с такой структурой: <?xml version="1.0" standalone="yes"?> <Personel xmlns="http://tempuri.org/Personel.xsd"> <PERSON> <LAST_NAME>Нуруллаев</LAST_NAME> <FIRST_NAME>Маъруфжон</FIRST_NAME> <MIDDLE_NAME>Фарход угли</MIDDLE_NAME> <TAB_NUM /> <PERS_ID>014dc87b-685c-4936-9681-a00ab50f1b87</PERS_ID> <ORG_ID>bd6a705e-664e-47ca-aad6-3520173c6874</ORG_ID> <TYPE_ID>5b9f23a0-346d-48c4-81e5-6afbc2a83320</TYPE_ID> </PERSON> <PERSON> <LAST_NAME>Нуруллаев</LAST_NAME> <FIRST_NAME>Маъруфжон</FIRST_NAME> <MIDDLE_NAME>Фарход угли</MIDDLE_NAME> <TAB_NUM /> <PHOTO>235678764</PHOTO> <PERS_ID>014dc87b-685c-4936-9681-a00ab50f1b87</PERS_ID> <ORG_ID>bd6a705e-664e-47ca-aad6-3520173c6874</ORG_ID> <TYPE_ID>5b9f23a0-346d-48c4-81e5-6afbc2a83320</TYPE_ID> </PERSON> Все методы, которые я находил, работают при знании четкой и неизменной структуры. Кто-то сможет подсказать методы работы с такими файлами? |
|||
1
RomaH
naïve
02.02.16
✎
08:51
|
объект xdto из него сделай
|
|||
2
RomaH
naïve
02.02.16
✎
08:53
|
Функция ПолучитьОбъектXDTOИзТекста(Знач ТекстОтвета) Экспорт
Попытка ЧтениеXML = Новый ЧтениеXML(); ЧтениеXML.УстановитьСтроку(ТекстОтвета); Возврат ФабрикаXDTO.ПрочитатьXML(ЧтениеXML); Исключение Возврат Неопределено; КонецПопытки; КонецФункции |
|||
3
Serginio1
02.02.16
✎
09:49
|
Фабрика=СоздатьФабрикуXDTO(ПутьКPersonel.xsd);
ЧтениеXML=Новый ЧтениеXML; ЧтениеXML=Новый ЧтениеXML; ЧтениеXML.ОткрытьФайл(ИмяФайла); ЧтениеXML.ПерейтиКСодержимому(); Имя=ЧтениеXML.Имя; ОбъектВыгрузки=Фабрика.ПрочитатьXML(ЧтениеXML,ФабрикаВыгрузки.Тип(ЧтениеXML.URIПространстваИмен,Имя)); ЧтениеXML.Закрыть(); |
|||
4
gorlanovmax
02.02.16
✎
09:49
|
У меня 7.7, а не 8
|
|||
5
Ёпрст
гуру
02.02.16
✎
09:53
|
Да любым дом-документом, влёт разгребается
|
|||
6
gorlanovmax
02.02.16
✎
10:01
|
(5) Если не сложно, можно пример
|
|||
7
Serginio1
02.02.16
✎
10:25
|
(4) Через COM используй
|
|||
8
Ёпрст
гуру
02.02.16
✎
10:28
|
(6)
xmlDoc = СоздатьОбъект("Microsoft.XMLDOM"); xmlDoc.Load(СокрЛП(ВыбФайл)); Узел=xmlDoc.selectNodes("//PERSON"); // без точки - все узлы, с точкой - подчиненные Для к=0 по Узел.length-1 Цикл Узел1 = Узел.item(к); ТекЭлем = Узел1.selectNodes(".//LAST_NAME").item(0); Адрес=""; Для ном=0 По ТекЭлем.childNodes.length-1 Цикл ДочЭлем=ТекЭлем.childNodes(ном); Сообщить(ДочЭлем.text); КонецЦикла; КонецЦикла; |
|||
9
Ёпрст
гуру
02.02.16
✎
10:29
|
+8
".//LAST_NAME" |
|||
10
Ёпрст
гуру
02.02.16
✎
10:31
|
там точка, если че.. форматирование кода тут, съедает.
Можно и рекурсией бегать, можно и через объект ДОМ=СоздатьОбъект("MSXML2.DOMDocument.6.0"); ДОМ.load(СокрЛП(ВыбФайл)); читать - как угодно, в общем |
|||
11
Serginio1
02.02.16
✎
10:32
|
Вообще для семерки лучше использовать классы Net
Есть более продвинутые инструменты http://metanit.com/sharp/tutorial/16.1.php Использование классов .Net в 1С для новичков Для семерки нужно установить УстЭтоСемерка() |
|||
12
gorlanovmax
02.02.16
✎
23:09
|
(8) На первом же отсутствии тега PHOTO в узле, выдает ошибку
ТекЭлем = Узел1.selectNodes(".//PHOTO").item(0); {C:\USERS\EXTFORMS\???????? ???.ERT(21)}: Плохой тип переменной |
|||
13
gorlanovmax
02.02.16
✎
23:10
|
Проблема именно в том, что в некоторых узлах есть тег PHOTO, а в некоторых - нет
|
|||
14
Злопчинский
02.02.16
✎
23:36
|
делаю по стариковски.
типа Определяю в СЗ перечень тегов, которые меня интересуют разбираю последовательно, рекурсией, при входе в очередную рекурсию - смотрю очередной тег/узел - есть в списке нужных мне: - если нет, то пропуск... |
|||
15
Злопчинский
02.02.16
✎
23:41
|
Процедура ПриОткрытии()
//список обрабатываемых узлов // http://cwms3000.ru/wiki/index.php?title=Интеграция:Приход // СЗузлы = СоздатьОбъект("СписокЗначений"); СЗузлы.ДобавитьЗначение("DOC"); СЗузлы.ДобавитьЗначение("DOC_IN"); //ОТКРЫВАЮЩИЙ ТЕГ: входящий документ СЗузлы.ДобавитьЗначение("NUMBER"); //ОТКРЫВАЮЩИЙ ТЕГ: номер документа СЗузлы.ДобавитьЗначение("ID_DOC"); //GUID СЗузлы.ДобавитьЗначение("INV_DATE"); //дата подачи заявки СЗузлы.ДобавитьЗначение("IN_DATE"); //плановая дата приемки СЗузлы.ДобавитьЗначение("CONTENT"); //СТРОКИ: ОТКРЫВАЮЩИЙ ТЕГ СЗузлы.ДобавитьЗначение("CODE"); //товар СЗузлы.ДобавитьЗначение("UNIT_NAME"); //единица СЗузлы.ДобавитьЗначение("CNT"); //количество //----------- ИНИЦИАЛИЗАЦИЯ ПЕРЕМЕННЫХ -------------------------------------------------------------------------------------- // Иксемель = СоздатьОбъект("Microsoft.XMLDOM"); Иксемель.Load(ФайлДанных); Корень = Иксемель.DocumentElement; //ОбработатьУзел(Корень, 0); //тест чтения ТрассировкаЗагрузки = "==========================================================================================================================="; ТрассировкаЗагрузки = ТрассировкаЗагрузки+РазделительСтрок+ТекущаяДата()+" "+ТекущееВремя()+": НАЧАЛО ЗАГРУЗКИ ДАННЫХ ИЗ ФАЙЛА ОБМЕНА= "+ИмяФайла; Результат = ВыполнитьУзел(Корень,0); ТрассировкаЗагрузки = ТрассировкаЗагрузки+РазделительСтрок+ТекущееВремя()+": КОД ВОЗВРАТА= "+Число(Результат); ТрассировкаЗагрузки = ТрассировкаЗагрузки+РазделительСтрок+ТекущаяДата()+" "+ТекущееВремя()+": КОНЕЦ ЗАГРУЗКИ ДАННЫХ ИЗ ФАЙЛА ОБМЕНА= "+ИмяФайла; ТрассировкаЗагрузки = ТрассировкаЗагрузки+РазделительСтрок+"==========================================================================================================================="; Форма.Параметр.Установить("ПРОТОКОЛ",ТрассировкаЗагрузки); Иксемель = ""; Результат = Число(Результат); Если Результат = 1 Тогда Форма.Параметр.Установить("КОДВОЗВРАТА",1); Форма.Параметр.Установить("ОПИСАНИЕ",ИмяФайла+": ЗАГРУЗКА ВЫПОЛНЕНА УСПЕШНО"); Иначе // -1 = ошибка, негрузим // -77 = внутренняя ошибка, пытаемся еще раз Форма.Параметр.Установить("КОДВОЗВРАТА",Число(Результат)); Форма.Параметр.Установить("ОПИСАНИЕ",ИмяФайла+": ОШИБКА, ЗАГРУЗКА ДАННЫХ НЕ ВЫПОЛНЕНА"); КонецЕсли; КонецПроцедуры // |
|||
16
Djelf
гуру
02.02.16
✎
23:44
|
Для 7.7, делает то как называется
Ибо они меня утомили, возможно когда то сломается но это маловероятно. Функция хмлУдалитьПространствоИмен(хмлСообщение) //:MSXML2.DOMDocument xslDoc=СоздатьОбъект("MSXML2.DOMDocument"); xslDoc.async = 0; xslDoc.loadXML(" |<xsl:stylesheet version=""1.0"" xmlns:xsl=""http://www.w3.org/1999/XSL/Transform""> | <xsl:output method=""xml"" version=""1.0"" encoding=""UTF-8"" omit-xml-declaration=""yes"" indent=""yes""/> | <xsl:strip-space elements=""*""/> | | <!-- keep comments --> | <xsl:template match=""comment()""> | <xsl:copy> | <xsl:apply-templates/> | </xsl:copy> | </xsl:template> | <xsl:template match=""*""> | <!-- remove element prefix --> | <xsl:element name=""{local-name(.)}""> | <!-- process attributes --> | <xsl:for-each select=""@*""> | <!-- remove attribute prefix --> | <xsl:attribute name=""{local-name(.)}""> | <xsl:value-of select=""normalize-space(.)""/> | </xsl:attribute> | </xsl:for-each> | <xsl:apply-templates/> | </xsl:element> | </xsl:template> |</xsl:stylesheet> |"); xmlDoc=СоздатьОбъект("MSXML2.DOMDocument"); хмлСообщение.transformNodeToObject(xslDoc, xmlDoc); Возврат xmlDoc; КонецФункции |
|||
17
Злопчинский
02.02.16
✎
23:46
|
//**************************************************************************************
// Функция ВыполнитьУзел(Узел, Уровень=0) Если СЗузлы.НайтиЗначение(Врег(Узел.tagName)) = 0 Тогда //<--- узел не обрабатывается согласно установленным ограничениям -->" Возврат 1; КонецЕсли; КолвоУзлов = Узел.childNodes.length-1; Для СчУзлов = 0 По КолвоУзлов Цикл ТекУзел = Узел.childNodes.item(СчУзлов); Если ТекУзел.nodeType <> 1 Тогда Продолжить; КонецЕсли; УзелИмя = ВРЕГ(ТекУзел.tagName); УзелТекст = СокрЛП(ТекУзел.text); //----- обработка начала тега -------------------------------------------------------------------------------------------- Если УзелИмя = "DOC_IN" Тогда //заказ на приемку ТрассировкаЗагрузки = ТрассировкаЗагрузки +РазделительСтрок+ТекущееВремя()+": начало загрузки документа"; КонецЕсли; Если УзелИмя = "NUMBER" Тогда //номер заявки ТрассировкаЗагрузки = ТрассировкаЗагрузки +РазделительСтрок+ТекущееВремя()+": номер заявки= "+УзелТекст; Если УзелИмя = "ID_DOC" Тогда //GUID ТрассировкаЗагрузки = ТрассировкаЗагрузки +РазделительСтрок+ТекущееВремя()+": идентификатор заявки= "+УзелТекст; КонецЕсли; Результат = ВыполнитьУзел(ТекУзел, Уровень+1); //-----------ОБРАБОТКА ВЛОЖЕННЫХ УЗЛОВ --------------------------- //обработка конца тега (сюда попадаем после обработки внутренних тегов) Если УзелИмя = "DOC_IN" Тогда.... Если УзелИмя = "CODE" Тогда //закончена обработка строки заявки, зафиксируем ее КонецЦикла; Возврат 1; КонецФункции // ОбработатьУзел() |
|||
18
Злопчинский
02.02.16
✎
23:46
|
тривиальный шаблон рекурсивной процедуры
//************************************************************************************** // Процедура ОбработатьУзел(Узел, Уровень=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); КонецЦикла; Состояние(""); КонецПроцедуры // ОбработатьУзел() |
|||
19
Djelf
гуру
02.02.16
✎
23:58
|
(18) не люблю рекурсию... и это медленно...
хлопнуть пространство имен и все становится просто и быстро либо переходить на xml.setProperty "SelectionLanguage", "XPath" и запросы будут проще но у меня 77 на wine, а с ним печалька... вот и вырезаю ПространставоИмен... |
|||
20
Злопчинский
03.02.16
✎
00:03
|
(19) Согласен, но для меня
1. слишком много умных букв в примере с пространстовм имен 2. для загрузки 100 мегабайтных иксемелей рекурсия может и много, но обычные иксемели для обмена заявками всякими и даже что побольше грузит вообщем без напряга |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |