Читаем XML, хочется получить ТаблицаЗначений через XDTO

1. tarassov 112 28.05.15 12:17 Сейчас в теме
Хочется делать следующее преобразование.
Имеем на входе некий произвольный XML. У меня, к примеру тот, что возвращает http://gw.edostavka.ru:11443/pvzlist.php или в явном виде:

<?xml version="1.0" encoding="UTF-8"?>
<PvzList>
<Pvz
Code="ABK1"
Name="На Чертыгашева"
CityCode="823"
City="Абакан"
Address="ЧЕРТЫГАШЕВА УЛ, д.126, оф.5"
</Pvz>
<Pvz
Code="ALV1"
Name="На Восстания 1905 года"
CityCode="1196"
City="Александров"
Address="ВОССТАНИЯ 1905Г., д.2"
</Pvz>
</PvzList>
Показать

Требуется получить из него обыкновенную таблицу значений.
Причем хочется обойтись одним каким-либо хитрым заклинанием :)
Кажется, это должны уметь объекты XDTO, но как?
...
Конечно можно бы было обойтись без XDTO и прописать все в явном виде:
...
тзПВЗ = Новый ТаблицаЗначений;
тзПВЗ.Колонки.Добавить("Название", Новый ОписаниеТипов("Строка"));
тзПВЗ.Колонки.Добавить("КодПВЗ",  Новый ОписаниеТипов("Строка"));
тзПВЗ.Колонки.Добавить("Город",  Новый ОписаниеТипов("Строка"));
тзПВЗ.Колонки.Добавить("Адрес",  Новый ОписаниеТипов("Строка"));
тзПВЗ.Колонки.Добавить("КодГорода",  Новый ОписаниеТипов("Строка"));

ЧтениеXMLДанных = Новый ЧтениеXML; 
ЧтениеXMLДанных.УстановитьСтроку(СтрокаXML); 
ОбъектXDTO = ФабрикаXDTO.ПрочитатьXML(ЧтениеXMLДанных);
СписокПВЗ = ОбъектXDTO.ПолучитьСписок("Pvz");
Для каждого ПВЗ Из СписокПВЗ Цикл
	стр = тзПВЗ.Добавить();
	стр.Название = ПВЗ.Name;
	стр.КодПВЗ = ПВЗ.Code;
	стр.Город = ПВЗ.City;
	стр.Адрес = ПВЗ.Address;
	стр.КодГорода = ПВЗ.CityCode;
КонецЦикла;
Показать

Но хочется большего!

Ищу способ так прочитать XML, чтобы на выходе мне получилась таблица значений сразу, без каких бы то ни было циклов.
Понимаю, что надо каким-то образом использовать СериализаторXDTO.

Причем, способ "в лоб" не работает, конструкция
ЧтениеXMLДанных = Новый ЧтениеXML; 
ЧтениеXMLДанных.УстановитьСтроку(СтрокаXML); 
ТЗ = СериализаторXDTO.ПрочитатьXML(ЧтениеXMLДанных); 		

таблицу значений не вернет, и это понятно, ведь 1С не понимает структуры входящего XML без дополнительных объяснений

Т.е нужно как-то описать схему XML, либо создать ПакетXDTO. Но как, какую структуру там задать?

Пока не могу ничего придумать, кроме как пойти еще одним обходным путем, а именно использовать ПреобразованиеXSL, преодразуя входящий XML в вид пригодный для понимания 1С в рамках ее пространств имен.
Мне это удалось следующим образом:

Схема XSL-преобразования

<?xml version="1.0" encoding="UTF-8"?>

<ValueTable
xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://v8.1c.ru/8.1/data/core" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<column>
<Name xsi:type="xs:string">КодПВЗ</Name>
<ValueType>
<Type>xs:string</Type>
<StringQualifiers>
<Length>0</Length>
<AllowedLength>Variable</AllowedLength>
</StringQualifiers>
</ValueType>
</column>
<column>
<Name xsi:type="xs:string">Название</Name>
<ValueType>
<Type>xs:string</Type>
<StringQualifiers>
<Length>0</Length>
<AllowedLength>Variable</AllowedLength>
</StringQualifiers>
</ValueType>
</column>
<column>
<Name xsi:type="xs:string">Город</Name>
<ValueType>
<Type>xs:string</Type>
<StringQualifiers>
<Length>0</Length>
<AllowedLength>Variable</AllowedLength>
</StringQualifiers>
</ValueType>
</column>
<column>
<Name xsi:type="xs:string">Адрес</Name>
<ValueType>
<Type>xs:string</Type>
<StringQualifiers>
<Length>0</Length>
<AllowedLength>Variable</AllowedLength>
</StringQualifiers>
</ValueType>
</column>
<column>
<Name xsi:type="xs:string">КодГорода</Name>
<ValueType>
<Type>xs:string</Type>
<StringQualifiers>
<Length>0</Length>
<AllowedLength>Variable</AllowedLength>
</StringQualifiers>
</ValueType>
</column>

<xsl:for-each select="PvzList/Pvz">
<row>
<Value><xsl:value-of select="@Code"/></Value>
<Value><xsl:value-of select="@Name"/></Value>
<Value><xsl:value-of select="@City"/></Value>
<Value><xsl:value-of select="@Address"/></Value>
<Value><xsl:value-of select="@CityCode"/></Value>
</row>
</xsl:for-each>

</ValueTable>
Показать

код в 1С:
Преобразование_ПВЗ = Новый ПреобразованиеXSL;
Преобразование_ПВЗ.ЗагрузитьИзСтроки(Схема);
СтрокаXML_ПВЗ = Преобразование_ПВЗ.ПреобразоватьИзСтроки(СтрокаXML);
ЧтениеXML_ПВЗ = Новый ЧтениеXML();
ЧтениеXML_ПВЗ.УстановитьСтроку(СтрокаXML_ПВЗ);
ТЗ2 = СериализаторXDTO.ПрочитатьXML(ЧтениеXML_ПВЗ);

Работает успешно.
Код сократился.
Но весьма смущает то, что приходится входящий XML еще раз переписывать, прежде чем сериализовать.
Как обойтись без этого?
Как описать такой НаборСхемXML, на основании которого можно бы было создать ФабрикаXDTO, преобразующую входящий XML в ТаблицаЗначений сразу, в одно действие?
user1393353; klinval; +2 Ответить
По теме из базы знаний
Вознаграждение за ответ
Показать полностью
Ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
2. ture 606 28.05.15 12:34 Сейчас в теме
(1) tarassov, это forum.infostart.ru вдруг забыли.

преобразование xml через другой xml это вообще за пределами.
ща мсдн почитаем....
4. tarassov 112 28.05.15 12:39 Сейчас в теме
(2) ture,
преобразование xml через другой xml это вообще за пределами
- почему же, если теперь в 1С есть объект ПреобразованиеXSL, который оказалось весьма удобно использовать для разных нужд в 1С (см. http://infostart.ru/public/352722/ и http://infostart.ru/public/347510/). С этим как раз проблем нет. Через правильно написанную схему XSL для ПреобразованиеXSL у меня ТаблицаЗначений успешно получается. Вопрос не в этом!

Вопрос в том, как то же самое сделать используя только механизм XDTO?
5. Поручик 4674 28.05.15 12:41 Сейчас в теме
(2) Просвети. Вдруг и мне пригодится.
6. tarassov 112 28.05.15 12:45 Сейчас в теме
(5) Поручик, Читай внимательнее мой (1) заглавный вопрос. там как раз описано, как получить из одного XML другой XML, с иной структурой.
Мой вопрос в другом.
Как внешний XML сериализовать в объект ТаблицаЗначений?
Какой НаборСхемXML для этого нужно создать?
7. Поручик 4674 28.05.15 13:03 Сейчас в теме
(6) Создаёте XDTO-пакет и читаете через фабрику XDTO.
http://infostart.ru/public/167459/
8. tarassov 112 28.05.15 13:06 Сейчас в теме
(7) Поручик,
да, вопрос именно в этом. Как создать XDTO-пакет, который преобразует мой XML в в объект ТаблицаЗначений?
Покажите мне хотя бы подходящий пример такого пакета
9. Поручик 4674 28.05.15 13:10 Сейчас в теме
(8) Ну так для начала прочитайте все статьи цикла, то есть теоретическую матчасть.
10. tarassov 112 28.05.15 13:16 Сейчас в теме
(9) Поручик,
Я прочитал. Но как соотнести в пакете структуру моего XML с таблицей значений, так и не понял. Поэтому и спрашиваю
11. Fragster 1139 28.05.15 13:34 Сейчас в теме
(1) tarassov, все правильно. либо вручную перенос реквизитов из объекта XDTO (со схемой/пакетом или без) в ТЗ, либо XSLT преобразование, и прямая десериализация через сериализатор XDTO.больше способов нет :)
13. tarassov 112 28.05.15 13:38 Сейчас в теме
(11) Fragster, Точно нет? А вот тут (9) Поручик, намекают, что есть. Так как?
17. kasper076 105 28.05.15 14:28 Сейчас в теме
(1) tarassov, XDTO ничего не преобразовывает. Если структура ХМЛ-файла соответствует схеме XDTO, то можно получить нужный объект, если нет, то нельзя. Если вы создаете свою схему, то и получить вы сможете свой объект.
18. tarassov 112 28.05.15 15:58 Сейчас в теме
(17) kasper076,
Если структура ХМЛ-файла соответствует схеме XDTO, то можно получить нужный объект
В этом и вопрос - можно ли сделать такую схему XDTO, что бы ей с одной стороны соответствовала структура неизмененного ХМЛ-файла, а с другой - нужный объект 1С, в моем случае ТаблицаЗначений? И если можно, то как?
26. kasper076 105 01.06.15 15:16 Сейчас в теме
(18) tarassov, схема описывающая ТЗ уже есть. И если объект соответствует этой схеме, то это ТЗ, а если не соответствует, то это не ТЗ. Третьего не дано. Все что можно сделать это привести к нужному виду с помощью XSLT.
3. ture 606 28.05.15 12:38 Сейчас в теме
теги вложенных не содержат, на сайте правильно закрыты "/>" , в примере нет
14. tarassov 112 28.05.15 13:47 Сейчас в теме
(3) ture, нет там никаких ошибок. У меня это место работает. Это ты скорее всего неточно скопировал, либо на сайт как-то кривовато выложилось. То есть это не проблема.
Я спрашивал не о XSL, а о XDTO
12. ture 606 28.05.15 13:34 Сейчас в теме
Граждане! У меня тут куча народу. Я сходил в соседний комната к людям, где звания выше.
Ну ботинком в меня не кинули за идею преобразований, но осадочек остался. Я так понимаю, вещь не тривиальная и плохо отлаживается, а ошибки можно искать неделями.
Рекомендовали писать прозрачный код на том языке, который мне знаком лучше и в коде делать требуемое, не полагаясь на схемы преобразования.
15. tarassov 112 28.05.15 13:53 Сейчас в теме
(12) ture,
Рекомендовали писать прозрачный код на том языке, который мне знаком лучше и в коде делать требуемое, не полагаясь на схемы преобразования
- почему же так категорично?
Посмотри публикации у нас на тему преобразований. Мне вот очень понравилась идея (11) Fragster - http://infostart.ru/public/352812/
16. ture 606 28.05.15 13:56 Сейчас в теме
(15) tarassov, я хз, снова не пойду, с меня одного раза хватило.
19. Fragster 1139 28.05.15 16:03 Сейчас в теме
(15) tarassov, в случае моей обработки идет преобразование Структура 1с с данными + XML с шаблоном => тут заполнение шаблона через DOM + XPATH => результирующий XML.
В случае (0) - либо через XSLT: XML с данными + XML с правилами преобразования => XML по схеме сериализатора для ТЗ => ТЗ, либо через код: XML [+ схема] => Объект XDTO + код на языке 1с => ТЗ.

Собственно, XSLT также работает через XPATH.
tarassov; +1 Ответить
20. Serginio 938 28.05.15 16:21 Сейчас в теме
Пример передачи через COM

ЗаписьXML = ВнешнееСоединение.NewObject("ЗаписьXML");
ЗаписьXML.УстановитьСтроку();
ВнешнееСоединение.СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Результат);
ХранилищеВСтроке = ЗаписьXML.Закрыть();


ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(ХранилищеВСтроке);
Тз = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
Показать

Или

ЗаписьXML = новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Тз);
ХранилищеВСтроке = ЗаписьXML.Закрыть();


ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(ХранилищеВСтроке);
Тз = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
Показать
21. tarassov 112 28.05.15 16:29 Сейчас в теме
(20) Serginio,
Это, как я понимаю, пример передачи таблицы значений из 1С.
А вопрос был об обратном процессе. Передача в 1С.
22. Fragster 1139 28.05.15 17:20 Сейчас в теме
Да не будет другого способа - либо код по заполнению полей ТЗ в 1с, либо преобразование XML под схему ТЗ для сериализатора XDTO.
23. spezc 782 28.05.15 17:28 Сейчас в теме
Имхо без спешки, без суеты, пройтись по хмл, и запихнуть все в ТЗ. Старый дедовский способ, проверенный годами на обменах. Не надо гнаться за универсальностью и красотой. Есть задача и результат ее выполнения. Получите результат.
24. tarassov 112 28.05.15 17:42 Сейчас в теме
(23) spezc,
Как получать результат, я сразу же описал во введении.
Меня интересует в данном случае именно теория (и немного красота).
Можно общий вопрос разбить на два подвопроса:
1. Как описать ПакетXDTO для таблицы значений с пятью строковыми колонками
2. Как сопоставить методами XDTO этому пакету XML иной структуры (Либо докажите, что это будет невозможно)
25. Serginio 938 29.05.15 10:22 Сейчас в теме
(24) Выгружаешь пакет
Процедура ЗпаисатьПакет(Фабрика,URIПространстваИмен,ИмяФайла) Экспорт
 
 		 НаборСхем = Фабрика.ЭкспортСхемыXML(URIПространстваИмен);
        Для Счетчик = 0 по НаборСхем.Количество() - 1 Цикл
            Схема = НаборСхем.Получить(Счетчик);
            Схема.ОбновитьЭлементDOM();
            ЗаписьDOM = Новый ЗаписьDOM;
            ЗаписьXMLСтрока = Новый ЗаписьXML;
            ЗаписьXMLСтрока.УстановитьСтроку();
            ЗаписьXMLФайл = Новый ЗаписьXML;
            ЗаписьDOM.Записать(Схема.ДокументDOM, ЗаписьXMLСтрока);
            ЗаписьXMLФайл.ОткрытьФайл(ИмяФайла +"[" + Формат(Счетчик,"ЧЦ=10;ЧГ=0;ЧН=") + "].xsd");
            ЗаписьXMLФайл.ЗаписатьБезОбработки(ЗаписьXMLСтрока.Закрыть());
            ЗаписьXMLФайл.Закрыть()
        КонецЦикла;    
  
 КонецПроцедуры
Показать


Например
ПИ="http://v8.1c.ru/8.1/data/core";
ЗпаисатьПакет(ФабрикаXDTO,ПИ,"C:\Core1C");


Затем можешь работать с файлом схемы
Например загрузить в VS

    public partial class ValueTable
    {
        
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("column")]
        public ValueTableColumn[] column;
        
        /// <remarks/>
        [System.Xml.Serialization.XmlArrayItemAttribute("column", typeof(string), DataType="NMTOKEN", IsNullable=false)]
        public string[][] index;
        
        /// <remarks/>
        [System.Xml.Serialization.XmlArrayItemAttribute("Value", typeof(object))]
        public object[][] row;
    }
Показать
27. CagoBHuK 32 04.09.15 14:18 Сейчас в теме
Забавно наблюдать, как люди, которые ничего не понимают в XML пытаются опрокинуть человека, который хоть что-то соображает в XSL. Уважаемый, дорогой автор, ты пошел правильным путем, не обращай внимание на тех, кто тебе рассказывает про пакеты XDTO. Ты прекрасно сможешь конвертнуть любую структуру ХМЛ в сериализованную ТаблицаЗначений через ПреобразованиеXSL, а затем прочитать ее в нативный 1С объект через СериализаторXDTO без применения рудиментов в виде XDTO. Не останавливайся на достигнутом: таким образом ты сможешь читать и более сложные объекты: например, структуру, одно свойство которой - массив со значениями, другое - соответствие со значениями, а третье - вообще ссылка на документ нужного тебе типа.

Все в твоих руках! Если тебе потребуется помощь, обращайся в скайп - поддержу. CagoBHuK_MATRIX.
RussXXX; kassbar; serge.kuh; akR00b; Olenevod; Gorr; МихаилМ; tarassov; +8 Ответить
28. Olenevod 33 05.07.17 10:06 Сейчас в теме
Пробовал выполнять преобразования по указанному шаблону автора. Не знаю ошибка у него или нет, но обращение к элементам в цикле должно быть не через "@" а через "./"

т.е. конструкция
<xsl:for-each select="PvzList/Pvz"> 
<row> 
<Value><xsl:value-of select="@Code"/></Value> 
<Value><xsl:value-of select="@Name"/></Value> 
... 
</row> 
</xsl:for-each>


не работает

Надо так
<xsl:for-each select="PvzList/Pvz"> 
<row> 
<Value><xsl:value-of select="./Code"/></Value> 
<Value><xsl:value-of select="./Name"/></Value> 
... 
</row> 
</xsl:for-each>


причем, что еще заметил в цикле нельзя вызывать шаблон
типа

<xsl:for-each select="PvzList/Pvz"> 
<row> 
	<xsl:apply-templates select="Pvz" /> 
</row> 

<xsl:template match="Pvz">
	<Value><xsl:value-of select="./Code"/></Value> 
	<Value><xsl:value-of select="./Name"/></Value>
</xsl:template>
Показать
29. tarassov 112 05.07.17 10:22 Сейчас в теме
(28) Почитай http://infostart.ru/public/504776/ - там я привожу пример успешной реализации этой схемы
30. Olenevod 33 05.07.17 15:37 Сейчас в теме
(29) Спасибо. Но по всей видимости вы дали мне не ту ссылку, т.к. в указанной статье нет ни слова про XSL. Там тема немного другая.
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот