Имя: Пароль:
1C
1С v8
Прочитать описания элементов из XSD-схемы с указанием полного пути к каждому элементу.
0 SleepyHead
 
гуру
13.07.20
07:38
Частно приходится сталкиваться с задачей сравнения регламентированных отчетов (НДС, ЕНВД, Налог на прибыль, РСВ, СЗВ-М и так далее).
Две подзадачи
1. Понять, чем отличается корректировка отчета от первичного
2. Отчет подготовлен в 1С, выгружен, подгружен в СБИС-контур, далее могли быть внесены изменения и отправлены. Понять, чем отличается версия в СБИС от версии 1с.


Сделал внешний отчет, в котором XML-файлы разбираются рекурсивно, отчеты сравниваются, все красиво. Чтобы отчет выглядел читабельно для пользователя, идентификаторы элементов узлов нужно представить в читаемом виде.
Пока что реализовал это прямо в обработке, в макете, сопоставляю полное имя элемента и его текстовой представление, пример:

Файл\Документ\НомКорр - номер корректировки
Файл\Документ\ВерсФорм - версия формата

и так далее.


Описания форматов опубликованы, их легко найти в том же консультанте. Однако, создавать макет сопоставления для каждого вида отчета - как-то скучновато, да и версии форматов периодически меняются.

Что хочу:
1. Взять XSD-схему с описанием формата файла отчетности
2. Разобрать ее и вытянуть описания всех элементов, как описано выше.

Что получилось: нашел тему на инфостарте, где приведен пример чтения XSD-схемы (http://catalog.mista.ru/public/311011/) Однако, там разбираются способы чтения самого XML-файла при помощи схемы. а у меня задача другая , получить описания элементов и не более того.


Текст схемы на примере отчета по прибыли я нашел на сайте налоговой, загнал ее в текстовый макет, и прочитал эту схему. А что дальше с ней делать, пока не понял.
Посмотрел полученную схему в отладчике, не понял, с чего начать ее рекурсивный разбор, чтобы выйти на описания элементов
(Файл\Документ\НомКорр например)

Обращаюсь к ием, кто со схемами работал.

        Макет = ПолучитьМакет("Схема_PRIB_05_08");
        
        ЧтениеСхемы = Новый ЧтениеXML;
        ЧтениеСхемы.УстановитьСтроку(Макет.ПолучитьТекст());
        
        ПостроительДОМ = Новый ПостроительDOM;
        ДокументДом = ПостроительДОМ.Прочитать(ЧтениеСхемы);
        
        ПостроительСхем = Новый ПостроительСхемXML;
        Схема = ПостроительСхем.СоздатьСхемуXML(ДокументДом);
1 quest
 
13.07.20
08:58
ФабрикаXDTO имеет все что тебе надо - пакеты, описания и т.д. Читай схему в Фабрику и работай с типами как тебе надо.
2 SleepyHead
 
гуру
13.07.20
10:15
(1) Спасибо, вот только в самом регл. отчете схема не указана. Но в этом направлении подумаю.
3 quest
 
13.07.20
11:19
а как тогда отчет собирается? руками пишутся элементы?
4 SleepyHead
 
гуру
13.07.20
14:15
(3) Наименования атрибутов и блоков вписал в макет внешнего отчета, например:

Файл\Документ\НомКорр -> Номер корректировки.

В отчете видно "Номер корректировки".


Если не впишу в макет, то отчет тоже сформируется, но с идентификаторами элементов из самого XML-файла: "Файл\Документ\НомКорр".
5 SleepyHead
 
гуру
13.07.20
15:42
(1) Фабрику создал, пакеты вижу, но как извлечь оттуда описания элементов - не понимаю, хоть тресни :((

Посмотрел саму схему. Очень похоже на обычный XML-файл, и структура в общем понятная. Если разобрать его рекурсивно, то можно выделить идентификаторы элементов из тегов xs:element, а описания из вложенного теша xs:annotation \ xs:documentation

Но изобретать велосипед не хочется. Может быть , есть примеры разбора пакетов фабрики? На инфостарте не нашел пока.
6 quest
 
13.07.20
16:48
лучше изобрети. сам разберешься и на инфостарте потом опубликуешь
7 SleepyHead
 
гуру
13.07.20
17:06
(6) Разобрался, путем изобретения небольшого велосипеда под решение моей конкретной маленькой задачи.
    Насчет публикации на инфостарте - сомневаюсь, что это будет кому-то интересно, потому что задача очень специфическая. Там полно статей, которые решают проблему чтения/записи  XML через схемы и фабрику, а мне нужно получить описания элементов, и не более того.

Схема - этот тот же самый файл XML, который можно разбирать рекурсивно. Нужно анализировать только узлы "xs:element" и "xs:attribute", а внутри них собирать описания элементов.

Тестовый код делал в форме обработки, получилось буквально несколько десятков строк.
В итоге получил массив структур (потому что разбирал на клиенте) с полями "путь", "Наименование", где путь - это полный путь от корня XML-файла, а Наименование - это описание элемента или атрибута из схемы, вот результат, вытащенный отладчиком:

"Файл\Документ"    "Состав и структура документа"
"Файл\Документ\СвНП"    "Сведения о налогоплательщике"
"Файл\Документ\СвНП\НПЮЛ"    "Налогоплательщик - организация (обособленное подразделение)"
"Файл\Документ\СвНП\НПЮЛ\СвРеоргЮЛ"    "Сведения о реорганизованной (ликвидированной) организации (обособленном подразделении)"
"Файл\Документ\СвНП\НПЮЛ\СвРеоргЮЛ\ФормРеорг"    "Код формы реорганизации (ликвидации) / изменения полномочий (закрытия) обособленного подразделения"
"Файл\Документ\СвНП\НПЮЛ\СвРеоргЮЛ\ИННЮЛ"    "ИНН реорганизованной организации (обособленного подразделения) / изменившего полномочия (закрытого) обособленного подразделения"
"Файл\Документ\СвНП\НПЮЛ\СвРеоргЮЛ\КПП"    "КПП реорганизованной организации (обособленного подразделения) / изменившего полномочия (закрытого) обособленного подразделения"
"Файл\Документ\СвНП\НПЮЛ\НаимОрг"    "Наименование организации (обособленного подразделения)"
"Файл\Документ\СвНП\НПЮЛ\ИННЮЛ"    "ИНН организации"
"Файл\Документ\СвНП\НПЮЛ\КПП"    "КПП"
"Файл\Документ\СвНП\Тлф"    "Номер контактного телефона"
"Файл\Документ\Подписант"    "Лицо, подписавшее документ"
"Файл\Документ\Подписант\ФИО"    "Фамилия, имя, отчество"
"Файл\Документ\Подписант\СвПред"    "Сведения о представителе налогоплательщика, налогового агента"
"Файл\Документ\Подписант\СвПред\НаимДок"    "Наименование и реквизиты документа, подтверждающего полномочия представителя налогоплательщика, налогового агента"
"Файл\Документ\Подписант\СвПред\НаимОрг"    "Наименование организации - представителя налогоплательщика, налогового агента "
"Файл\Документ\Подписант\ПрПодп"    "Признак лица, подписавшего документ"
"Файл\Документ\Прибыль"    "Налоговая декларация по налогу на прибыль организаций"
"Файл\Документ\Прибыль\НалПУ"    "Сумма налога, подлежащая уплате в бюджет, по данным налогоплательщика (налогового агента)"
"Файл\Документ\Прибыль\НалПУ\НалПУАв"    "Сумма налога, подлежащая уплате в бюджет, по данным налогоплательщика (налогового агента) - для организаций, уплачивающих авансовые платежи и налог на прибыль организаций"

и так далее.

А вот код:

&НаКлиенте
Процедура Тест(Команда)
    
    СтрокаСхемы = ПолучитьТекстИзМакета("Макет");
    ЧтениеСхемы = Новый ЧтениеXML;
    ЧтениеСхемы.УстановитьСтроку(СтрокаСхемы);
        
    ПостроительДОМ = Новый ПостроительDOM;
    ДокументДом = ПостроительДОМ.Прочитать(ЧтениеСхемы);
    
    МассивОписаний = Новый Массив;
    РазобратьРекурсивно(ДокументДом.ЭлементДокумента, "", МассивОписаний);

КонецПроцедуры

&НаКлиенте
Процедура РазобратьРекурсивно(УзелРодитель, Знач ПолныйПуть, МассивОписаний)
Перем Узел, УзелДокументации, Имя, Представление, ТекущийПолныйПуть, ЭтоАтрибут;

    Если ВРег(УзелРодитель.ИмяЭлемента)=ВРег("xs:element") ИЛИ ВРег(УзелРодитель.ИмяЭлемента)=ВРег("xs:attribute") Тогда
        Имя = ПолучитьЗначениеАтрибута(УзелРодитель, "name");
        ТекущийПолныйПуть = ПолныйПуть + ?(ЗначениеЗаполнено(ПолныйПуть), "\", "") + Имя;
        ЭтоАтрибут = ВРег(УзелРодитель.ИмяЭлемента)=ВРег("xs:attribute");
    Иначе
        Имя = "";
        ТекущийПолныйПуть = ПолныйПуть;
        ЭтоАтрибут = Ложь;
    КонецЕсли;
    
    Для Каждого Узел из УзелРодитель.ДочерниеУзлы Цикл
        Если ВРег(Узел.ИмяЭлемента)=ВРег("xs:annotation") Тогда
            Если ЗначениеЗаполнено(ТекущийПолныйПуть) И Найти(ТекущийПолныйПуть, "\")>0 Тогда
                Представление = "";
                Для Каждого УзелДокументации из Узел.ДочерниеУзлы Цикл
                    Если ЗначениеЗаполнено(Имя) И УзелДокументации.ТипУзла=ТипУзлаDOM.Элемент И ВРег(УзелДокументации.ИмяЭлемента)=ВРег("xs:documentation") Тогда
                        Представление = Представление + ?(ЗначениеЗаполнено(Представление), Символы.ПС, "") + УзелДокументации.ТекстовоеСодержимое;
                    КонецЕсли;
                КонецЦикла;
                МассивОписаний.Добавить(Новый Структура("Путь,Наименование", ТекущийПолныйПуть, Представление));
            КонецЕсли;
        ИначеЕсли НЕ ЭтоАтрибут Тогда
            РазобратьРекурсивно(Узел, ТекущийПолныйПуть, МассивОписаний);
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

&НаКлиенте
Функция ПолучитьЗначениеАтрибута(Узел, Знач ИмяАтрибута)
    ТекЭлемент = Узел.Атрибуты.ПолучитьИменованныйЭлемент(ИмяАтрибута);
    Возврат ?(ТекЭлемент=Неопределено, "", ТекЭлемент.Значение);
КонецФункции


&НаСервере
Функция ПолучитьТекстИзМакета(Знач ИмяМакета)
    
    Возврат РеквизитФормыВЗначение("Объект").ПолучитьМакет(ИмяМакета).ПолучитьТекст();
    
КонецФункции