Имя: Пароль:
1C
1C 7.7
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 мегабайтных иксемелей рекурсия может и много, но обычные иксемели для обмена заявками всякими и даже что побольше грузит вообщем без напряга