Имя: Пароль:
1C
1С v8
как загрузить данные из файла xml
0 Xelga
 
14.02.12
17:39
Есть файл xml, имеющий такую структуру
- <documents>
- <document>
 <typeName>Счет</typeName>
 <date>13.12.2011</date>
 <number>2011/3</number>
- <client>
 <clientShortName>Customer Name</clientShortName>
 <clientName>Customer Full Name</clientName>
 <clientId>123456VAT</clientId>
 <clientAddress>Address Address 2, City, Poland</clientAddress>
 <clientContractNumber>123456CN</clientContractNumber>
 </client>
- <lines>
- <line>
 <lineNum>1</lineNum>
 <itemDescription>2011/24/2 (test) proofreading</itemDescription>
 <itemActivityType>2011/24/2</itemActivityType>
 <orderedQuantity>3</orderedQuantity>
 <sum>110.70</sum>
 <VAT>0.2300</VAT>
 </line>
- <line>
 <lineNum>2</lineNum>
 <itemDescription>2011/24/2 (test) - translation</itemDescription>
 <itemActivityType>2011/24/2</itemActivityType>
 <orderedQuantity>30</orderedQuantity>
 <sum>738.00</sum>
 <VAT>0.2300</VAT>
 </line>
 </lines>
 <TotalLines>2</TotalLines>
 <TotalSum>848.70</TotalSum>
 </document>
- <document>
 <typeName>Счет</typeName>
 <date>22.11.2011</date>
 <number>draft-2011/1</number>
- <client>
 <clientShortName>Customer Name</clientShortName>
 <clientName>Customer Full Name</clientName>
 <clientId>123456VAT</clientId>
 <clientAddress>Address Address 2, City, Poland</clientAddress>
 <clientContractNumber>123456CN</clientContractNumber>
 </client>
- <lines>
- <line>
 <lineNum>1</lineNum>
 <itemDescription>2011/24/1 - перевод - English (United States) [EN-US] » Немецкий [DE]</itemDescription>
 <itemActivityType>2011/24/1 - перевод - English</itemActivityType>
 <orderedQuantity>50</orderedQuantity>
 <sum>615.00</sum>
 <VAT>0.2300</VAT>
 </line>
- <line>
 <lineNum>2</lineNum>
 <itemDescription>2011/24/1 - редактирование - English (United States) [EN-US] » Немецкий [DE]</itemDescription>
 <itemActivityType>2011/24/1 - редактирование - English</itemActivityType>
 <orderedQuantity>1</orderedQuantity>
 <sum>61.50</sum>
 <VAT>0.2300</VAT>
 </line>
 </lines>
 <TotalLines>2</TotalLines>
 <TotalSum>676.50</TotalSum>
 </document>
 </documents>
Нужно написать обработку, которая будет для каждого узла document, создавать Реализацию товаров и услуг, заполнять табличную часть из соответствующего узла lines.
Пытаюсь сделать обработку, посмотрела такой пример    
   Чтение = Новый ЧтениеXML;
   Чтение.ОткрытьФайл(ФайлЗагрузки);
Пока Чтение.Прочитать() Цикл
   Если Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
       ИмяУзла = Чтение.Имя; Сообщить("--" + ИмяУзла);
   ИначеЕсли Чтение.ТипУзла = ТипУзлаXML.Текст Тогда
       // В примере просто выводим текст в окно сообщений.  
      Сообщить("Текст:" + Чтение.Значение);
   КонецЕсли;
КонецЦикла;
Для моего файла по очереди считывается то Имя узла, то Значение.
Что-то вообще не могу понять, как мне здесь сделать два цикла, один, который бы создавал документы, другой, который должен заполнять табличную часть?
1 zzhiraf
 
14.02.12
17:46
Нужно создать файл xsd описания.
2 zzhiraf
 
14.02.12
17:47
Если его нет, можно воспользоваться специальными утилитами)
3 Xelga
 
14.02.12
17:50
(1) и что потом?
4 Xelga
 
14.02.12
17:51
Есть такой файл схемы, это оно?

<?xml version="1.0" encoding="UTF-8"?>
$utils.getWindowsNewLine()
<documents>

#foreach( $invoice in $utils.unwrap(${list}))
$utils.getWindowsNewLine()
<document>
$utils.getWindowsNewLine()
  <typeName>Счет</typeName>
$utils.getWindowsNewLine()
  <date>$utils.getCommonsDateFormatUtils().format( $utils.getXtrfDateUtils().parseDateString($invoice.displayInvoiceDate), 'dd.MM.yyyy')</date>
$utils.getWindowsNewLine()
  <number>$invoice.displayNumber</number>
$utils.getWindowsNewLine()
  <client>
$utils.getWindowsNewLine()
     <clientShortName>$invoice.customer.name</clientShortName>
$utils.getWindowsNewLine()
     <clientName>$invoice.customer.fullname</clientName>
$utils.getWindowsNewLine()
     <clientId>$invoice.customer.nIPVATEU</clientId>
$utils.getWindowsNewLine()
     <clientAddress>$invoice.customer.address.address $invoice.customer.address.address2, $invoice.customer.address.city, $invoice.customer.address.country.name</clientAddress>
$utils.getWindowsNewLine()
     <clientContractNumber>$invoice.customer.contractNumber</clientContractNumber>
$utils.getWindowsNewLine()
  </client>
$utils.getWindowsNewLine()
  <lines>
#set ($count=0)
#set ($sum=0)
   #foreach( $line in $utils.unwrap($invoice.getInvoiceItems()))
#set($count = $count+1)
$utils.getWindowsNewLine()
      <line>
$utils.getWindowsNewLine()
         <lineNum>$utils.toInteger($count)</lineNum>
$utils.getWindowsNewLine()
         <itemDescription>$line.getName()</itemDescription>
$utils.getWindowsNewLine()
         #set ($actType = $line.getName())
         #set ($index = $actType.indexOf('('))
         <itemActivityType>$actType.substring(0, $index).trim()</itemActivityType>
$utils.getWindowsNewLine()
         <orderedQuantity>$utils.toInteger($line.getQuantity())</orderedQuantity>
$utils.getWindowsNewLine()
#set($sum = $sum+$line.getLineBrutto())
         <sum>$line.getLineBrutto()</sum>
$utils.getWindowsNewLine()
         <VAT>$line.getVatRate()</VAT>
$utils.getWindowsNewLine()
      </line>
   #end
$utils.getWindowsNewLine()
  </lines>
$utils.getWindowsNewLine()
  <TotalLines>$utils.toInteger($count)</TotalLines>
$utils.getWindowsNewLine()
  <TotalSum>$sum</TotalSum>
$utils.getWindowsNewLine()
</document>
#end
$utils.getWindowsNewLine()
</documents>
5 andrewks
 
14.02.12
17:51
цикл будет один, просто надо использовать флажок начала документа, устанавливать его в Истину, если встретили <document>
начало элемента. после встречи конца элемента - записывать тек.док, устанавливать флаг в Ложь, и идти дальше
6 zzhiraf
 
14.02.12
17:52
Потом прочитать содержимое xml во внутренние структуры/массивы структур программы и обработать их как требуется.
7 zzhiraf
 
14.02.12
17:53
нет это не файл xml-схемы...
8 Xelga
 
14.02.12
17:54
(6) какими функциями это делать?
9 zzhiraf
 
14.02.12
17:55
Функциями объекта ФабрикаXDTO - ПрочитатьXML...
10 zzhiraf
 
14.02.12
17:56
Получите от поставщика файла xml, файл с xml-схемой (расширение xsd)
11 Xelga
 
14.02.12
17:58
Он мне отправил такую схему (4)
12 asady
 
14.02.12
17:59
(8) юзай штатный ПостроительDOM

   ЧтениеXML = новый ЧтениеXML;
   ЧтениеXML.ОткрытьФайл(ФайлЗагрузки);
   СообщениеОбОшибке = "Список записей не найден";
   построительДОМ = Новый ПостроительDOM;
   Попытка
       ДокументДОМ = построительДОМ.Прочитать(ЧтениеXML);
   Исключение
       Сообщить(ОписаниеОшибки());
       возврат;
   КонецПопытки;    
   Если ДокументДОМ.ЭлементДокумента.ИмяУзла<>"documents" Тогда
       goto ~Err;
   КонецЕсли;    
   узелdocuments = ДокументДОМ.ЭлементДокумента;
   СписокЭлементовdocument = узелdocuments.ПолучитьЭлементыПоИмени("document");
   Если СписокЭлементовdocument.Количество()=0 Тогда
       goto ~Err;
   КонецЕсли;    
   тУзелdocument =СписокЭлементовNodes.Элемент(0); //как пример
13 zzhiraf
 
14.02.12
17:59
Должно быть что-то типа этого:
   |<xs:schema xmlns:ent=""http://v8.1c.ru/8.1/data/enterprise"" xmlns:tns=""http://v8.1c.ru/8.1/data/enterprise/current-config"" xmlns:v8=""http://v8.1c.ru/8.1/data/core"" xmlns:xs=""http://www.w3.org/2001/XMLSchema"" targetNamespace=""http://my_exchange/"" attributeFormDefault=""unqualified"" elementFormDefault=""qualified"">
   |    <xs:import namespace=""http://v8.1c.ru/8.1/data/core""/>
   |    <xs:import namespace=""http://v8.1c.ru/8.1/data/enterprise""/>
   |    <xs:complexType name=""CatalogObject.Номенклатура"">
   |        <xs:sequence>
   |            <xs:element name=""IsFolder"" type=""xs:boolean""/>
   |            <xs:element name=""Ref"" type=""tns:CatalogRef.Номенклатура""/>
   |            <xs:element name=""DeletionMark"" type=""xs:boolean""/>
   |            <xs:element name=""Parent"" type=""tns:CatalogRef.Номенклатура""/>
   |            <xs:element name=""Code"" type=""xs:string""/>
   |            <xs:element name=""Description"" type=""xs:string""/>
   |            <xs:element name=""Артикул"" type=""xs:string"" minOccurs=""0""/>
   |            <xs:element name=""НаименованиеПолное"" type=""xs:string"" minOccurs=""0""/>
   |            <xs:element name=""Описание"" type=""xs:string"" minOccurs=""0""/>
   |            <xs:element name=""ФайлКартинки"" type=""xs:string"" minOccurs=""0""/>
   |            <xs:element name=""ОписаниеВФорматеHTML"" type=""xs:string"" minOccurs=""0""/>
   |            <xs:element name=""ДатаЗагрузкиВБазу"" type=""xs:dateTime"" minOccurs=""0""/>
   |            <xs:element name=""Автор"" type=""tns:CatalogRef.Пользователи""/>
   |        </xs:sequence>
   |    </xs:complexType>
   |</xs:schema>
14 Kyrales
 
14.02.12
18:39
Воспользуйся функцией считывания в дерево и оттуда уже спокойно создавай свои документы http://infostart.ru/public/84254/
15 Xelga
 
16.02.12
22:48
(13) Хочу сделать через фабрикуXDTO, получила схему документа, и что дальше? Ничего не понимаю, как прочитать файл xml, используя схему. Можно какой-нить конкретный пример?
16 Xelga
 
17.02.12
17:15
Нашла пример в Простые примеры разработки Габец, Гончаров, делаю по нему
у меня есть схема

<?xml version="1.0" encoding="utf-16"?>
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <xsd:element name="documents">
   <xsd:complexType>
     <xsd:sequence>
       <xsd:element name="document">
         <xsd:complexType>
           <xsd:sequence>
             <xsd:element name="typeName" type="xsd:string" />
             <xsd:element name="date" type="xsd:string" />
             <xsd:element name="number" type="xsd:string" />
             <xsd:element name="client">
               <xsd:complexType>
                 <xsd:sequence>
                   <xsd:element name="clientShortName" type="xsd:string" />
                   <xsd:element name="clientName" type="xsd:string" />
                   <xsd:element name="clientId" type="xsd:string" />
                   <xsd:element name="clientAddress" type="xsd:string" />
                   <xsd:element name="clientContractNumber" type="xsd:string" />
                 </xsd:sequence>
               </xsd:complexType>
             </xsd:element>
             <xsd:element name="lines">
               <xsd:complexType>
                 <xsd:sequence>
                   <xsd:element maxOccurs="unbounded" name="line">
                     <xsd:complexType>
                       <xsd:sequence>
                         <xsd:element name="lineNum" type="xsd:int" />
                         <xsd:element name="itemDescription" type="xsd:string" />
                         <xsd:element name="itemActivityType" type="xsd:string" />
                         <xsd:element name="orderedQuantity" type="xsd:int" />
                         <xsd:element name="sum" type="xsd:decimal" />
                         <xsd:element name="VAT" type="xsd:decimal" />
                       </xsd:sequence>
                     </xsd:complexType>
                   </xsd:element>
                 </xsd:sequence>
               </xsd:complexType>
             </xsd:element>
             <xsd:element name="TotalLines" type="xsd:int" />
             <xsd:element name="TotalSum" type="xsd:decimal" />
           </xsd:sequence>
         </xsd:complexType>
       </xsd:element>
     </xsd:sequence>
   </xsd:complexType>
 </xsd:element>
</xsd:schema>

Пишу код как в примере
   Чтение = Новый ЧтениеXML;
   Чтение.ОткрытьФайл(ФайлСхемы);
   
   НовыйПострительДом = Новый  ПостроительDOM;
   НовыйДокументДом = НовыйПострительДом.Прочитать(Чтение);
   
   НовыйПостроительСхем = Новый ПостроительСхемXML;
   
   НоваяСхема = НовыйПостроительСхем.СоздатьСхемуXML(НовыйДокументДом);
   
   НаборСхем = Новый НаборСхемXML;
   НаборСхем.Добавить(НоваяСхема);
   
   НоваяФабрика = Новый ФабрикаXDTO(НаборСхем);
   
   Чтение = Новый ЧтениеXML;
   Чтение.ОткрытьФайл(ФайлЗагрузки);
   
   Данные = НоваяФабрика.ПрочитатьXML(Чтение);
   Если Данные = Неопределено Тогда
       Возврат;
   КонецЕсли;
   
   Для Каждого Элемент Из Данные.Document Цикл
       
        ДатаДок = Элемент.Date;
        НомерДок = Элемент.Number;
        Сообщить(НомерДок+" от "+ДатаДок);
       
   КонецЦикла;    

Выдает ошибку "Итератор для значения не определен"
В отладке смотрю Данные, там вся структура загрузилась. Но не пойму как надо к ним обращаться? Как потом сделать обход по lines?
17 vmv
 
17.02.12
17:22
да в каждой типовой есть методы преобразования хмл в дерево.

зачем вообще создавать объекты на лету из хмл, логичнее их проичитать в более удобные структуры(деревья) и юзать уже их.
Есть минус, что при большом размере хмл - эта музыка будет вечной, ну то редко бывает, ибо все заполонила попсовая мелкопузая моль.

мдя, ето же миста - та пофик, музыку любят все!
18 vmv
 
17.02.12
17:30
я читаю так, вроде это старый кусок кода из обработки деревьев персонификации, какда писал не помню, зачем тоже - 3 года уже работает и ладно

// Методы обработки XML

Процедура ЧитатьXML(ИмяФайлаЧтение, РодительскаяСтрокаXML)
   
   // очистим дерево
   РодительскаяСтрокаXML.Строки.Очистить();
   
   XML = Новый ЧтениеXML();
   XML.ОткрытьФайл(ИмяФайлаЧтение);
   
   текСтрока = РодительскаяСтрокаXML.Строки.Добавить();
   ЗаполнитьЗначенияСвойств(текСтрока, РодительскаяСтрокаXML);
   текСтрока.Параметр = ИмяФайлаЧтение;
   СтрокиДерева = текСтрока.Строки;
   
   Пока XML.Прочитать() Цикл
       Если XML.ТипУзла = ТипУзлаXML.Текст Тогда
           // текст элемента, может быть только после начала элемента
           // в ТекСтрока сейчас должен быть узел
           текСтрока.Значение = XML.Значение;
       ИначеЕсли XML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
           СтрокиДерева = ДобавитьУзел(СтрокиДерева, XML, РодительскаяСтрокаXML);
       ИначеЕсли XML.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
           // установим родителя
           Если СтрокиДерева.Родитель.Родитель = Неопределено Тогда
               // нет узла верхнего уровня
               СтрокиДерева = СтрокиДерева.Родитель.Строки;
           Иначе
               СтрокиДерева = СтрокиДерева.Родитель.Родитель.Строки;
           КонецЕсли;
       КонецЕсли;

       Пока XML.ПрочитатьАтрибут() Цикл
           текСтрока = СтрокиДерева.Добавить();
           ЗаполнитьЗначенияСвойств(текСтрока, РодительскаяСтрокаXML);
           текСтрока.Параметр = XML.Имя;
           текСтрока.Значение = XML.Значение;
           а=1;
       КонецЦикла;

   КонецЦикла;
   XML.Закрыть();
   //Дерево = Новый ХранилищеЗначения(ДеревоXML);
   
КонецПроцедуры
19 zzhiraf
 
20.02.12
09:29
(16) Так если данные в структуру загрузились, то дальше какие проблемы?)
20 Xelga
 
21.02.12
11:21
(19) а проблемы 2:
  - в файле в структуре document содержатся сведения о документе, если документов несколько, то в цикле всё считывается нормально, а если документ только 1, то выдает ошибку "Итератор для значения не определен", соответственно в цикл не заходит и ничего не считывается
  - в документе дальше идет параметр lines, где мне надо построчно считать каждую строку Line, а я не знаю как это цикл встроить, как обратиться к этим элементам.

Такой у меня цикл чтения данных из файла

   Для Каждого Элемент Из Данные.Document Цикл
        ДатаДок = Элемент.Date;
        НомерДок = Элемент.Number;
        КлиентСокращенноеНаименование = Элемент.Client.ClientShortName;
        КлиентПолноеНаименование = Элемент.Client.ClientName;
        ИНН_КПП = Элемент.Client.ClientId;
        Адрес = Элемент.Client.ClientContractNumber;
   КонецЦикла;
Основная теорема систематики: Новые системы плодят новые проблемы.