Русский
Русский
English
Статистика
Реклама

Импорт ЕГРЮЛ ФНС средствами Apache NiFi. Шаг 2 преобразование XML в JSON

В одном из проектов возникла необходимость перевести процессы импорта данных сторонних систем на микросервисную архитектуру. В качестве инструмента выбран Apache NiFi. В качестве первого подопытного выбран импорт ЕГРЮЛ ФНС.


В предыдущей статье было описано, как получить файлы XML с данными ЕГРЮЛ, которые требуется импортировать.


В данной статье описан способ преобразования XML в JSON.



Используемые процессоры и контроллеры


Для преобразования XML в JSON используется процессор ConvertRecord. В котором используются два контроллера: FnsEgrulXmlReader типа XMLReader для чтения данных из XML и FnsEgrulJsonWriter типа JsonRecordSetWriter для записи этих данных в JSON.





Для работы контроллерам XMLReader и JsonRecordSetWriter требуются сведения о структуре читаемых и записываемых данных, т.е. схема данных. Я использовал схему AVRO. Для ее хранения в NiFi используется контроллер AvroSchemaRegistry. В нем задается имя схемы в поле Property и ее содержимое в поле Value



AVRO схема должна описывать структуру данных, соответствующую XSD-схеме, опубликованной на сайте ФНС. Не обязательно описывать всю структуру. Достаточно лишь в части тех данных, которые требуется импортировать.


Пример исходного XML
<?xml version="1.0" encoding="windows-1251" ?><EGRUL ДатаВыг="2020-05-20"><СвЮЛ ДатаВып="2020-05-20" ОГРН="1234567890123" ДатаОГРН="2002-12-30" ИНН="1234567890" КПП="123456789" СпрОПФ="ОКОПФ" КодОПФ="12300" ПолнНаимОПФ="Общества с ограниченной ответственностью">  <СвНаимЮЛ НаимЮЛПолн="ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ" НаимЮЛСокр="ООО">    <ГРНДата ГРН="1234567890123" ДатаЗаписи="2002-12-30" />  </СвНаимЮЛ>  <СвАдресЮЛ>    <АдресРФ Индекс="143500" КодРегион="50" КодАдрКладр="500000570000011">      <Регион ТипРегион="ОБЛАСТЬ" НаимРегион="МОСКОВСКАЯ" />      <Город ТипГород="ГОРОД" НаимГород="ИСТРА" />      <Улица ТипУлица="ПЕРЕУЛОК" НаимУлица="ВОЛОКОЛАМСКИЙ" />      <ГРНДата ГРН="1234567890123" ДатаЗаписи="2016-02-22" />      <ГРНДатаИспр ГРН="1234567890123" ДатаЗаписи="2019-03-08" />    </АдресРФ>  </СвАдресЮЛ>  <СвОбрЮЛ ОГРН="1234567890123" ДатаОГРН="2002-12-30" РегНом="12:12:12345" ДатаРег="1997-12-24" НаимРО="Московская областная регистрационная палата">    <СпОбрЮЛ КодСпОбрЮЛ="01" НаимСпОбрЮЛ="Создание юридического лица до 01.07.2002" />    <ГРНДата ГРН="1234567890123" ДатаЗаписи="2002-12-30" />  </СвОбрЮЛ>  <СвРегОрг КодНО="5081" НаимНО="Межрайонная инспекция Федеральной налоговой службы" АдрРО="144000,РОССИЯ,МОСКОВСКАЯ ОБЛ,,ЭЛЕКТРОСТАЛЬ Г,,СОВЕТСКАЯ УЛ,26А,,">    <ГРНДата ГРН="1234567890123" ДатаЗаписи="2019-01-31" />  </СвРегОрг>  <СвСтатус>    <СвСтатус КодСтатусЮЛ="105" НаимСтатусЮЛ="Регистрирующим органом принято решение о предстоящем исключении юридического лица из ЕГРЮЛ (недействующее юридическое лицо)" />    <СвРешИсклЮЛ ДатаРеш="2020-05-18" НомерРеш="12345" ДатаПубликации="2020-05-20" НомерЖурнала="1" />    <ГРНДата ГРН="1234567890123" ДатаЗаписи="2020-05-20" />  </СвСтатус>  <СвУчетНО ИНН="1234567890" КПП="123456789" ДатаПостУч="1998-01-20">    <СвНО КодНО="5017" НаимНО="Инспекция Федеральной налоговой службы" />    <ГРНДата ГРН="1234567890123" ДатаЗаписи="2007-11-01" />  </СвУчетНО>  <СвРегПФ РегНомПФ="123456789012" ДатаРег="1998-01-15">    <СвОргПФ КодПФ="060010" НаимПФ="Государственное учреждение - Управление Пенсионного фонда РФ" />    <ГРНДата ГРН="1234567890123" ДатаЗаписи="2006-05-05" />  </СвРегПФ>  <СвРегФСС РегНомФСС="123456789012345" ДатаРег="1998-01-15">    <СвОргФСС КодФСС="5023" НаимФСС="Филиал 23 Государственного учреждения - Московского областного регионального отделения Фонда социального страхования Российской Федерации" />    <ГРНДата ГРН="1234567890123" ДатаЗаписи="2016-11-01" />  </СвРегФСС>  <СведДолжнФЛ>    <ГРНДатаПерв ГРН="1234567890123" ДатаЗаписи="2005-07-20" />    <СвФЛ Фамилия="ИВАНОВ" Имя="ИВАН" Отчество="ИВАНОВИЧ" ИННФЛ="123456789012">      <ГРНДата ГРН="1234567890123" ДатаЗаписи="2020-03-18" />    </СвФЛ>    <СвДолжн ВидДолжн="02" НаимВидДолжн="Руководитель юридического лица" НаимДолжн="ГЕНЕРАЛЬНЙ ДИРЕКТОР">      <ГРНДата ГРН="1234567890123" ДатаЗаписи="2020-03-18" />    </СвДолжн>  </СведДолжнФЛ>  <СвУчредит>    <УчрФЛ>      <ГРНДатаПерв ГРН="1234567890123" ДатаЗаписи="2005-07-20" />      <СвФЛ Фамилия="ИВАНОВ" Имя="ИВАН" Отчество="ИВАНОВИЧ" ИННФЛ="123456789012">        <ГРНДата ГРН="1234567890123" ДатаЗаписи="2020-03-18" />      </СвФЛ>      <ДоляУстКап НоминСтоим="20000">        <РазмерДоли>          <Процент>50</Процент>        </РазмерДоли>        <ГРНДата ГРН="1234567890123" ДатаЗаписи="2005-07-20" />        <ГРНДатаИспр ГРН="1234567890123" ДатаЗаписи="2018-08-30" />      </ДоляУстКап>    </УчрФЛ><УчрФЛ>      <ГРНДатаПерв ГРН="1234567890123" ДатаЗаписи="2005-07-20" />      <СвФЛ Фамилия="ПЕТРОВ" Имя="ПЕТР" Отчество="ПЕТРОВИЧ" ИННФЛ="123456789021">        <ГРНДата ГРН="1234567890123" ДатаЗаписи="2020-03-18" />      </СвФЛ>      <ДоляУстКап НоминСтоим="20000">        <РазмерДоли>          <Процент>50</Процент>        </РазмерДоли>        <ГРНДата ГРН="1234567890123" ДатаЗаписи="2005-07-20" />        <ГРНДатаИспр ГРН="1234567890123" ДатаЗаписи="2018-08-30" />      </ДоляУстКап>    </УчрФЛ>  </СвУчредит>  <СвОКВЭД>    <СвОКВЭДОсн КодОКВЭД="47.11" НаимОКВЭД="Торговля розничная преимущественно пищевыми продуктами, включая напитки, и табачными изделиями в неспециализированных магазинах" ПрВерсОКВЭД="2014">      <ГРНДата ГРН="1234567890123" ДатаЗаписи="2005-07-20" />      <ГРНДатаИспр ГРН="1234567890123" ДатаЗаписи="2018-08-30" />    </СвОКВЭДОсн>  </СвОКВЭД>  <СвЗапЕГРЮЛ ИдЗап="1234567890" ГРН="1234567890123" ДатаЗап="2002-12-30">    <ВидЗап КодСПВЗ="11101" НаимВидЗап="Внесение в Единый государственный реестр юридических лиц сведений о юридическом лице, зарегистрированном до 1 июля 2002 года" />    <СвРегОрг КодНО="5017" НаимНО="Инспекция МНС России по г.Истре Московской области" />    <СвСвид Серия="12" Номер="123456789" ДатаВыдСвид="2002-12-30" />  </СвЗапЕГРЮЛ>  <СвЗапЕГРЮЛ ИдЗап="1234567891" ГРН="1234567890123" ДатаЗап="2005-07-20">    <ВидЗап КодСПВЗ="12101" НаимВидЗап="Государственная регистрация изменений, внесенных в учредительные документы юридического лица, связанных с внесением изменений в сведения о юридическом лице, содержащиеся в Едином государственном реестре юридических лиц, на основании заявления" />    <СвРегОрг КодНО="5017" НаимНО="Инспекция Федеральной налоговой службы по г.Истре Московской области" />    <СведПредДок>      <НаимДок>ЗАЯВЛЕНИЕ О ГОСУДАРСТВЕННОЙ РЕГИСТРАЦИИ ИЗМЕНЕНИЙ, ВНОСИМХ В УЧРЕДИТЕЛЬНЕ ДОКУМЕНТ  ЮРИДИЧЕСКОГО ЛИЦА</НаимДок>      <НомДок>1</НомДок>      <ДатаДок>2005-07-14</ДатаДок>    </СведПредДок>    <СведПредДок>      <НаимДок>УСТАВ</НаимДок>      <НомДок>2</НомДок>      <ДатаДок>2005-07-14</ДатаДок>    </СведПредДок>    <СведПредДок>      <НаимДок>РЕШЕНИЕ</НаимДок>      <НомДок>3</НомДок>      <ДатаДок>2005-07-14</ДатаДок>    </СведПредДок>    <СведПредДок>      <НаимДок>КВИТАНЦИЯ</НаимДок>      <НомДок>4</НомДок>      <ДатаДок>2005-07-14</ДатаДок>    </СведПредДок>    <СвСвид Серия="12" Номер="123456789" ДатаВыдСвид="2005-07-20" />  </СвЗапЕГРЮЛ></СвЮЛ></EGRUL>

Пример получаемого JSON
[ {  "reportDate" : "2020-05-20",  "ogrn" : "1234567890123",  "ogrnDate" : "2002-12-30",  "inn" : "1234567890",  "kpp" : "123456789",  "opfCode" : "12300",  "opfName" : "Общества с ограниченной ответственностью",  "name" : {    "fullName" : "ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ",    "shortName" : "ООО"  },  "address" : {    "addressRF" : {      "region" : {        "type" : "ОБЛАСТЬ",        "name" : "МОСКОВСКАЯ"      },      "district" : null,      "town" : {        "type" : "ГОРОД",        "name" : "ИСТРА"      },      "settlement" : null,      "street" : {        "type" : "ПЕРЕУЛОК",        "name" : "ВОЛОКОЛАМСКИЙ"      },      "index" : "143500",      "regionCode" : "50",      "kladr" : "500000570000011",      "house" : null,      "building" : null,      "apartment" : null    }  },  "termination" : null,  "capital" : null,  "manageOrg" : null,  "director" : [ {    "fl" : {      "lastName" : "ИВАНОВ",      "firstName" : "ИВАН",      "patronymic" : "ИВАНОВИЧ",      "inn" : "123456789012"    },    "position" : {      "ogrnip" : null,      "typeCode" : "02",      "typeName" : "Руководитель юридического лица",      "name" : "ГЕНЕРАЛЬНЙ ДИРЕКТОР"    },    "disqualification" : null  } ],  "founders" : {    "founderULRF" : null,    "founderULForeign" : null,    "founderFL" : [ {      "fl" : {        "lastName" : "ИВАНОВ",        "firstName" : "ИВАН",        "patronymic" : "ИВАНОВИЧ",        "inn" : "123456789012"      },      "capitalPart" : {        "nominal" : 20000.0,        "size" : {          "percent" : 50.0,          "decimalPart" : null,          "simplePart" : null        }      }    }, {      "fl" : {        "lastName" : "ПЕТРОВ",        "firstName" : "ПЕТР",        "patronymic" : "ПЕТРОВИЧ",        "inn" : "123456789021"      },      "capitalPart" : {        "nominal" : 20000.0,        "size" : {          "percent" : 50.0,          "decimalPart" : null,          "simplePart" : null        }      }    } ],    "founderGov" : null,    "founderPIF" : null  },  "capitalPart" : null,  "holderReestrAO" : null,  "okved" : {    "mainOkved" : {      "code" : "47.11",      "name" : "Торговля розничная преимущественно пищевыми продуктами, включая напитки, и табачными изделиями в неспециализированных магазинах"    },    "addOkved" : null  }} ]

AVRO схема
{ "type": "record", "name": "СвЮЛ",  "fields": [    { "name": "reportDate", "aliases": [ "ДатаВып" ], "type": "string" },    { "name": "ogrn", "aliases": [ "ОГРН" ], "type": "string" },    { "name": "ogrnDate", "aliases": [ "ДатаОГРН" ], "type": "string" },    { "name": "inn", "aliases": [ "ИНН" ], "type": "string" },    { "name": "kpp", "aliases": [ "КПП" ], "type": "string" },    { "name": "opfCode", "aliases": [ "КодОПФ" ], "type": "string" },    { "name": "opfName", "aliases": [ "ПолнНаимОПФ" ], "type": "string" },    { "name": "name", "aliases": [ "СвНаимЮЛ" ], "namespace": "СвЮЛ",      "type": { "type": "record", "name": "СвНаимЮЛ.СвЮЛ",        "fields": [          { "name": "fullName", "aliases": [ "НаимЮЛПолн" ], "type": "string" },          { "name": "shortName", "aliases": [ "НаимЮЛСокр" ], "type": "string" }        ]      }    },    { "name": "address", "aliases": [ "СвАдресЮЛ" ], "namespace": "СвЮЛ",      "type": { "type": "record", "name": "СвАдресЮЛ.СвЮЛ",        "fields": [          { "name": "addressRF", "aliases": [ "АдресРФ" ], "namespace": "СвАдресЮЛ.СвЮЛ",            "type": { "type": "record", "name": "АдресРФ.СвАдресЮЛ.СвЮЛ",              "fields": [                { "name": "region", "aliases": [ "Регион" ], "namespace": "АдресРФ.СвАдресЮЛ.СвЮЛ",                  "type": { "type": "record", "name": "Регион.АдресРФ.СвАдресЮЛ.СвЮЛ",                    "fields": [                      { "name": "type", "aliases": [ "ТипРегион" ], "type": "string" },                      { "name": "name", "aliases": [ "НаимРегион" ], "type": "string" }                    ]                  }                },                { "name": "district", "aliases": [ "Район" ], "namespace": "АдресРФ.СвАдресЮЛ.СвЮЛ",                  "type": { "type": "record", "name": "Район.АдресРФ.СвАдресЮЛ.СвЮЛ",                    "fields": [                      { "name": "type", "aliases": [ "ТипРайон" ], "type": "string" },                      { "name": "name", "aliases": [ "НаимРайон" ], "type": "string" }                    ]                  }                },                { "name": "town", "aliases": [ "Город" ], "namespace": "АдресРФ.СвАдресЮЛ.СвЮЛ",                  "type": { "type": "record", "name": "Город.АдресРФ.СвАдресЮЛ.СвЮЛ",                    "fields": [                      { "name": "type", "aliases": [ "ТипГород" ], "type": "string" },                      { "name": "name", "aliases": [ "НаимГород" ], "type": "string" }                    ]                  }                },                { "name": "settlement", "aliases": [ "НаселПункт" ], "namespace": "АдресРФ.СвАдресЮЛ.СвЮЛ",                  "type": { "type": "record", "name": "НаселПункт.АдресРФ.СвАдресЮЛ.СвЮЛ",                    "fields": [                      { "name": "type", "aliases": [ "ТипНаселПункт" ], "type": "string" },                      { "name": "name", "aliases": [ "НаимНаселПункт" ], "type": "string" }                    ]                  }                },                { "name": "street", "aliases": [ "Улица" ], "namespace": "АдресРФ.СвАдресЮЛ.СвЮЛ",                  "type": { "type": "record", "name": "Улица.АдресРФ.СвАдресЮЛ.СвЮЛ",                    "fields": [                      { "name": "type", "aliases": [ "ТипУлица" ], "type": "string" },                      { "name": "name", "aliases": [ "НаимУлица" ], "type": "string" }                    ]                  }                },                { "name": "index", "aliases": [ "Индекс" ], "type": "string" },                { "name": "regionCode", "aliases": [ "КодРегион" ], "type": "string" },                { "name": "kladr", "aliases": [ "КодАдрКладр" ], "type": "string" },                { "name": "house", "aliases": [ "Дом" ], "type": "string" },                { "name": "building", "aliases": [ "Корпус" ], "type": "string" },                { "name": "apartment", "aliases": [ "Кварт" ], "type": "string" }              ]            }          }        ]      }    },    { "name": "termination", "aliases": [ "СвПрекрЮЛ" ], "namespace": "СвЮЛ",      "type": { "type": "record", "name": "СвПрекрЮЛ.СвЮЛ",        "fields": [          { "name": "method", "aliases": [ "СпПрекрЮЛ" ], "namespace": "СвПрекрЮЛ.СвЮЛ",            "type": { "type": "record", "name": "СпПрекрЮЛ.СвПрекрЮЛ.СвЮЛ",              "fields": [                { "name": "code", "aliases": [ "КодСпПрекрЮЛ" ], "type": "string" },                { "name": "name", "aliases": [ "НаимСпПрекрЮЛ" ], "type": "string" }              ]            }          },          { "name": "date", "aliases": [ "ДатаПрекрЮЛ" ], "type": "string" }        ]      }    },    { "name": "capital", "aliases": [ "СвУстКап" ], "namespace": "СвЮЛ",      "type": { "type": "record", "name": "СвУстКап.СвЮЛ",        "fields": [          { "name": "type", "aliases": [ "НаимВидКап" ], "type": "string" },          { "name": "amount", "aliases": [ "СумКап" ], "type": "double" },          { "name": "partRUR", "aliases": [ "ДоляРубля" ], "namespace": "СвУстКап.СвЮЛ",            "type": { "type": "record", "name": "ДоляРубля.СвУстКап.СвЮЛ",              "fields": [                { "name": "num", "aliases": [ "Числит" ], "type": "long" },                { "name": "denom", "aliases": [ "Знаменат" ], "type": "long" }              ]            }          }        ]      }    },    { "name": "manageOrg", "aliases": [ "СвУпрОрг" ], "namespace": "СвЮЛ",      "type": { "type": "record", "name": "СвУпрОрг.СвЮЛ",        "fields": [          { "name": "egrulData", "aliases": [ "НаимИННЮЛ" ], "namespace": "СвУпрОрг.СвЮЛ",            "type": { "type": "record", "name": "НаимИННЮЛ.СвУпрОрг.СвЮЛ",              "fields": [                { "name": "ogrn", "aliases": [ "ОГРН" ], "type": "string" },                { "name": "inn", "aliases": [ "ИНН" ], "type": "string" },                { "name": "fullName", "aliases": [ "НаимЮЛПолн" ], "type": "string" }              ]            }          }        ]      }    },    { "name": "director", "aliases": [ "СведДолжнФЛ" ], "namespace": "СвЮЛ",      "type": { "type": "array",        "items": [          { "name": "СведДолжнФЛ.СвЮЛ", "type": "record",            "fields": [              { "name": "fl", "aliases": [ "СвФЛ" ], "namespace": "СведДолжнФЛ.СвЮЛ",                "type": { "type": "record", "name": "СвФЛ.СведДолжнФЛ.СвЮЛ",                  "fields": [                    { "name": "lastName", "aliases": [ "Фамилия" ], "type": "string" },                    { "name": "firstName", "aliases": [ "Имя" ], "type": "string" },                    { "name": "patronymic", "aliases": [ "Отчество" ], "type": "string" },                    { "name": "inn", "aliases": [ "ИННФЛ" ], "type": "string" }                  ]                }              },              { "name": "position", "aliases": [ "СвДолжн" ], "namespace": "СведДолжнФЛ.СвЮЛ",                "type": { "type": "record", "name": "СвДолжн.СведДолжнФЛ.СвЮЛ",                  "fields": [                    { "name": "ogrnip", "aliases": [ "ОГРНИП" ], "type": "string" },                    { "name": "typeCode", "aliases": [ "ВидДолжн" ], "type": "string" },                    { "name": "typeName", "aliases": [ "НаимВидДолжн" ], "type": "string" },                    { "name": "name", "aliases": [ "НаимДолжн" ], "type": "string" }                  ]                }              },              { "name": "disqualification", "aliases": [ "СвДискв" ], "namespace": "СведДолжнФЛ.СвЮЛ",                "type": { "type": "record", "name": "СвДискв.СведДолжнФЛ.СвЮЛ",                  "fields": [                    { "name": "startDate", "aliases": [ "ДатаНачДискв" ], "type": "string" },                    { "name": "endDate", "aliases": [ "ДатаОкончДискв" ], "type": "string" },                    { "name": "decisionDate", "aliases": [ "ДатаРеш" ], "type": "string" }                  ]                }              }            ]          }        ]      }    },    { "name": "founders", "aliases": [ "СвУчредит" ], "namespace": "СвЮЛ",      "type": { "type": "record", "name": "СвУчредит.СвЮЛ",        "fields": [          { "name": "founderULRF", "aliases": [ "УчрЮЛРос" ], "namespace": "СвУчредит.СвЮЛ",            "type": { "type": "array",              "items": [                { "name": "УчрЮЛРос.СвУчредит.СвЮЛ", "type": "record",                  "fields": [                    { "name": "egrulData", "aliases": [ "НаимИННЮЛ" ], "namespace": "УчрЮЛРос.СвУчредит.СвЮЛ",                      "type": { "type": "record", "name": "НаимИННЮЛ.УчрЮЛРос.СвУчредит.СвЮЛ",                        "fields": [                          { "name": "ogrn", "aliases": [ "ОГРН" ], "type": "string" },                          { "name": "inn", "aliases": [ "ИНН" ], "type": "string" },                          { "name": "fullName", "aliases": [ "НаимЮЛПолн" ], "type": "string" }                        ]                      }                    },                    { "name": "oldRegData", "aliases": [ "СвРегСтарые" ], "namespace": "УчрЮЛРос.СвУчредит.СвЮЛ",                      "type": { "type": "record", "name": "СвРегСтарые.УчрЮЛРос.СвУчредит.СвЮЛ",                        "fields": [                          { "name": "regNumber", "aliases": [ "РегНом" ], "type": "string" },                          { "name": "regDate", "aliases": [ "ДатаРег" ], "type": "string" },                          { "name": "regOrg", "aliases": [ "НаимРО" ], "type": "string" }                        ]                      }                    },                    { "name": "capitalPart", "aliases": [ "ДоляУстКап" ], "namespace": "УчрЮЛРос.СвУчредит.СвЮЛ",                      "type": { "type": "record", "name": "ДоляУстКап.УчрЮЛРос.СвУчредит.СвЮЛ",                        "fields": [                          { "name": "nominal", "aliases": [ "НоминСтоим" ], "type": "double" },                          { "name": "size", "aliases": [ "РазмерДоли" ], "namespace": "ДоляУстКап.УчрЮЛРос.СвУчредит.СвЮЛ",                            "type": { "type": "record", "name": "РазмерДоли.ДоляУстКап.УчрЮЛРос.СвУчредит.СвЮЛ",                              "fields": [                                { "name": "percent", "aliases": [ "Процент" ], "type": "double" },                                { "name": "decimalPart", "aliases": [ "ДробДесят" ], "type": "double" },                                { "name": "simplePart", "aliases": [ "ДробПрост" ], "namespace": "РазмерДоли.ДоляУстКап.УчрЮЛРос.СвУчредит.СвЮЛ",                                  "type": { "type": "record", "name": "ДробПрост.РазмерДоли.ДоляУстКап.УчрЮЛРос.СвУчредит.СвЮЛ",                                    "fields": [                                      { "name": "num", "aliases": [ "Числит" ], "type": "long" },                                      { "name": "denom", "aliases": [ "Знаменат" ], "type": "long" }                                    ]                                  }                                }                              ]                            }                          }                        ]                      }                    }                  ]                }              ]            }          },          { "name": "founderULForeign", "aliases": [ "УчрЮЛИн" ], "namespace": "СвУчредит.СвЮЛ",            "type": { "type": "array",              "items": [                { "name": "УчрЮЛИн.СвУчредит.СвЮЛ", "type": "record",                  "fields": [                    { "name": "egrulData", "aliases": [ "НаимИННЮЛ" ], "namespace": "УчрЮЛИн.СвУчредит.СвЮЛ",                      "type": { "type": "record", "name": "НаимИННЮЛ.УчрЮЛИн.СвУчредит.СвЮЛ",                        "fields": [                          { "name": "ogrn", "aliases": [ "ОГРН" ], "type": "string" },                          { "name": "inn", "aliases": [ "ИНН" ], "type": "string" },                          { "name": "fullName", "aliases": [ "НаимЮЛПолн" ], "type": "string" }                        ]                      }                    },                    { "name": "foreignReg", "aliases": [ "СвРегИн" ], "namespace": "УчрЮЛИн.СвУчредит.СвЮЛ",                      "type": { "type": "record", "name": "СвРегИн.УчрЮЛИн.СвУчредит.СвЮЛ",                        "fields": [                          { "name": "oksm", "aliases": [ "ОКСМ" ], "type": "string" },                          { "name": "country", "aliases": [ "НаимСтран" ], "type": "string" },                          { "name": "regDate", "aliases": [ "ДатаРег" ], "type": "string" },                          { "name": "regNumber", "aliases": [ "РегНомер" ], "type": "string" },                          { "name": "regOrg", "aliases": [ "НаимРегОрг" ], "type": "string" },                          { "name": "address", "aliases": [ "АдрСтр" ], "type": "string" }                        ]                      }                    },                    { "name": "capitalPart", "aliases": [ "ДоляУстКап" ], "namespace": "УчрЮЛИн.СвУчредит.СвЮЛ",                      "type": { "type": "record", "name": "ДоляУстКап.УчрЮЛИн.СвУчредит.СвЮЛ",                        "fields": [                          { "name": "nominal", "aliases": [ "НоминСтоим" ], "type": "double" },                          { "name": "size", "aliases": [ "РазмерДоли" ], "namespace": "ДоляУстКап.УчрЮЛИн.СвУчредит.СвЮЛ",                            "type": { "type": "record", "name": "РазмерДоли.ДоляУстКап.УчрЮЛИн.СвУчредит.СвЮЛ",                              "fields": [                                { "name": "percent", "aliases": [ "Процент" ], "type": "double" },                                { "name": "decimalPart", "aliases": [ "ДробДесят" ], "type": "double" },                                { "name": "simplePart", "aliases": [ "ДробПрост" ], "namespace": "РазмерДоли.ДоляУстКап.УчрЮЛИн.СвУчредит.СвЮЛ",                                  "type": { "type": "record", "name": "ДробПрост.РазмерДоли.ДоляУстКап.УчрЮЛИн.СвУчредит.СвЮЛ",                                    "fields": [                                      { "name": "num", "aliases": [ "Числит" ], "type": "long" },                                      { "name": "denom", "aliases": [ "Знаменат" ], "type": "long" }                                    ]                                  }                                }                              ]                            }                          }                        ]                      }                    }                  ]                }              ]            }          },          { "name": "founderFL", "aliases": [ "УчрФЛ" ], "namespace": "СвУчредит.СвЮЛ",            "type": { "type": "array",              "items": [                { "name": "УчрФЛ.СвУчредит.СвЮЛ", "type": "record",                  "fields": [                    { "name": "fl", "aliases": [ "СвФЛ" ], "namespace": "УчрФЛ.СвУчредит.СвЮЛ",                      "type": { "type": "record", "name": "СвФЛ.УчрФЛ.СвУчредит.СвЮЛ",                        "fields": [                          { "name": "lastName", "aliases": [ "Фамилия" ], "type": "string" },                          { "name": "firstName", "aliases": [ "Имя" ], "type": "string" },                          { "name": "patronymic", "aliases": [ "Отчество" ], "type": "string" },                          { "name": "inn", "aliases": [ "ИННФЛ" ], "type": "string" }                        ]                      }                    },                    { "name": "capitalPart", "aliases": [ "ДоляУстКап" ], "namespace": "УчрФЛ.СвУчредит.СвЮЛ",                      "type": { "type": "record", "name": "ДоляУстКап.УчрФЛ.СвУчредит.СвЮЛ",                        "fields": [                          { "name": "nominal", "aliases": [ "НоминСтоим" ], "type": "double" },                          { "name": "size", "aliases": [ "РазмерДоли" ], "namespace": "ДоляУстКап.УчрФЛ.СвУчредит.СвЮЛ",                            "type": { "type": "record", "name": "РазмерДоли.ДоляУстКап.УчрФЛ.СвУчредит.СвЮЛ",                              "fields": [                                { "name": "percent", "aliases": [ "Процент" ], "type": "double" },                                { "name": "decimalPart", "aliases": [ "ДробДесят" ], "type": "double" },                                { "name": "simplePart", "aliases": [ "ДробПрост" ], "namespace": "РазмерДоли.ДоляУстКап.УчрФЛ.СвУчредит.СвЮЛ",                                  "type": { "type": "record", "name": "ДробПрост.РазмерДоли.ДоляУстКап.УчрФЛ.СвУчредит.СвЮЛ",                                    "fields": [                                      { "name": "num", "aliases": [ "Числит" ], "type": "long" },                                      { "name": "denom", "aliases": [ "Знаменат" ], "type": "long" }                                    ]                                  }                                }                              ]                            }                          }                        ]                      }                    }                  ]                }              ]            }          },          { "name": "founderGov", "aliases": [ "УчрРФСубМО" ], "namespace": "СвУчредит.СвЮЛ",            "type": { "type": "array",              "items": [                { "name": "УчрРФСубМО.СвУчредит.СвЮЛ", "type": "record",                  "fields": [                    { "name": "govOrg", "aliases": [ "ВидНаимУчр" ], "namespace": "УчрРФСубМО.СвУчредит.СвЮЛ",                      "type": { "type": "record", "name": "ВидНаимУчр.УчрРФСубМО.СвУчредит.СвЮЛ",                        "fields": [                          { "name": "code", "aliases": [ "КодУчрРФСубМО" ], "type": "string" },                          { "name": "name", "aliases": [ "НаимМО" ], "type": "string" },                          { "name": "regionCode", "aliases": [ "КодРегион" ], "type": "string" },                          { "name": "regionName", "aliases": [ "НаимРегион" ], "type": "string" }                        ]                      }                    },                    { "name": "capitalPart", "aliases": [ "ДоляУстКап" ], "namespace": "УчрРФСубМО.СвУчредит.СвЮЛ",                      "type": { "type": "record", "name": "ДоляУстКап.УчрРФСубМО.СвУчредит.СвЮЛ",                        "fields": [                          { "name": "nominal", "aliases": [ "НоминСтоим" ], "type": "double" },                          { "name": "size", "aliases": [ "РазмерДоли" ], "namespace": "ДоляУстКап.УчрРФСубМО.СвУчредит.СвЮЛ",                            "type": { "type": "record", "name": "РазмерДоли.ДоляУстКап.УчрРФСубМО.СвУчредит.СвЮЛ",                              "fields": [                                { "name": "percent", "aliases": [ "Процент" ], "type": "double" },                                { "name": "decimalPart", "aliases": [ "ДробДесят" ], "type": "double" },                                { "name": "simplePart", "aliases": [ "ДробПрост" ], "namespace": "РазмерДоли.ДоляУстКап.УчрРФСубМО.СвУчредит.СвЮЛ",                                  "type": { "type": "record", "name": "ДробПрост.РазмерДоли.ДоляУстКап.УчрРФСубМО.СвУчредит.СвЮЛ",                                    "fields": [                                      { "name": "num", "aliases": [ "Числит" ], "type": "long" },                                      { "name": "denom", "aliases": [ "Знаменат" ], "type": "long" }                                    ]                                  }                                }                              ]                            }                          }                        ]                      }                    },                    { "name": "founderImplUL", "aliases": [ "СвОргОсущПр" ], "namespace": "УчрРФСубМО.СвУчредит.СвЮЛ",                      "type": { "type": "array",                        "items": [                          { "name": "СвОргОсущПр.УчрРФСубМО.СвУчредит.СвЮЛ", "type": "record",                            "fields": [                              { "name": "egrulData", "aliases": [ "НаимИННЮЛ" ], "namespace": "СвОргОсущПр.УчрРФСубМО.СвУчредит.СвЮЛ",                                "type": { "type": "record", "name": "НаимИННЮЛ.СвОргОсущПр.УчрРФСубМО.СвУчредит.СвЮЛ",                                  "fields": [                                    { "name": "ogrn", "aliases": [ "ОГРН" ], "type": "string" },                                    { "name": "inn", "aliases": [ "ИНН" ], "type": "string" },                                    { "name": "fullName", "aliases": [ "НаимЮЛПолн" ], "type": "string" }                                  ]                                }                              }                            ]                          }                        ]                      }                    },                    { "name": "founderImplFL", "aliases": [ "СвФЛОсущПр" ], "namespace": "УчрРФСубМО.СвУчредит.СвЮЛ",                      "type": { "type": "array",                        "items": [                          { "name": "СвФЛОсущПр.УчрРФСубМО.СвУчредит.СвЮЛ", "type": "record",                            "fields": [                              { "name": "fl", "aliases": [ "СвФЛ" ], "namespace": "СвФЛОсущПр.УчрРФСубМО.СвУчредит.СвЮЛ",                                "type": { "type": "record", "name": "СвФЛ.СвФЛОсущПр.УчрРФСубМО.СвУчредит.СвЮЛ",                                  "fields": [                                    { "name": "lastName", "aliases": [ "Фамилия" ], "type": "string" },                                    { "name": "firstName", "aliases": [ "Имя" ], "type": "string" },                                    { "name": "patronymic", "aliases": [ "Отчество" ], "type": "string" },                                    { "name": "inn", "aliases": [ "ИННФЛ" ], "type": "string" }                                  ]                                }                              }                            ]                          }                        ]                      }                    }                  ]                }              ]            }          },          { "name": "founderPIF", "aliases": [ "УчрПИФ" ], "namespace": "СвУчредит.СвЮЛ",            "type": { "type": "array",              "items": [                { "name": "УчрПИФ.СвУчредит.СвЮЛ", "type": "record",                  "fields": [                    { "name": "PIFName", "aliases": [ "СвНаимПИФ" ], "namespace": "УчрПИФ.СвУчредит.СвЮЛ",                      "type": { "type": "record", "name": "СвНаимПИФ.УчрПИФ.СвУчредит.СвЮЛ",                        "fields": [                          { "name": "name", "aliases": [ "НаимПИФ" ], "type": "string" }                        ]                      }                    },                    { "name": "manageOrg", "aliases": [ "СвУпрКомпПИФ" ], "namespace": "УчрПИФ.СвУчредит.СвЮЛ",                      "type": { "type": "record", "name": "СвУпрКомпПИФ.УчрПИФ.СвУчредит.СвЮЛ",                        "fields": [                          { "name": "egrulData", "aliases": [ "УпрКомпПиф" ], "namespace": "УчрПИФ.СвУчредит.СвЮЛ",                            "type": { "type": "record", "name": "УпрКомпПиф.УчрПИФ.СвУчредит.СвЮЛ",                              "fields": [                                { "name": "ogrn", "aliases": [ "ОГРН" ], "type": "string" },                                { "name": "inn", "aliases": [ "ИНН" ], "type": "string" },                                { "name": "fullName", "aliases": [ "НаимЮЛПолн" ], "type": "string" }                              ]                            }                          }                        ]                      }                    },                    { "name": "capitalPart", "aliases": [ "ДоляУстКап" ], "namespace": "УчрПИФ.СвУчредит.СвЮЛ",                      "type": { "type": "record", "name": "ДоляУстКап.УчрПИФ.СвУчредит.СвЮЛ",                        "fields": [                          { "name": "nominal", "aliases": [ "НоминСтоим" ], "type": "double" },                          { "name": "size", "aliases": [ "РазмерДоли" ], "namespace": "ДоляУстКап.УчрПИФ.СвУчредит.СвЮЛ",                            "type": { "type": "record", "name": "РазмерДоли.ДоляУстКап.УчрПИФ.СвУчредит.СвЮЛ",                              "fields": [                                { "name": "percent", "aliases": [ "Процент" ], "type": "double" },                                { "name": "decimalPart", "aliases": [ "ДробДесят" ], "type": "double" },                                { "name": "simplePart", "aliases": [ "ДробПрост" ], "namespace": "РазмерДоли.ДоляУстКап.УчрПИФ.СвУчредит.СвЮЛ",                                  "type": { "type": "record", "name": "ДробПрост.РазмерДоли.ДоляУстКап.УчрПИФ.СвУчредит.СвЮЛ",                                    "fields": [                                      { "name": "num", "aliases": [ "Числит" ], "type": "long" },                                      { "name": "denom", "aliases": [ "Знаменат" ], "type": "long" }                                    ]                                  }                                }                              ]                            }                          }                        ]                      }                    }                  ]                }              ]            }          }        ]      }    },    { "name": "capitalPart", "aliases": [ "СвДоляООО" ], "namespace": "СвЮЛ",      "type": { "type": "record", "name": "СвДоляООО.СвЮЛ",        "fields": [          { "name": "nominal", "aliases": [ "НоминСтоим" ], "type": "double" },          { "name": "size", "aliases": [ "РазмерДоли" ], "namespace": "СвДоляООО.СвЮЛ",            "type": { "type": "record", "name": "РазмерДоли.СвДоляООО.СвЮЛ",              "fields": [                { "name": "percent", "aliases": [ "Процент" ], "type": "double" },                { "name": "decimalPart", "aliases": [ "ДробДесят" ], "type": "double" },                { "name": "simplePart", "aliases": [ "ДробПрост" ], "namespace": "РазмерДоли.СвДоляООО.СвЮЛ",                  "type": { "type": "record", "name": "ДробПрост.РазмерДоли.СвДоляООО.СвЮЛ",                    "fields": [                      { "name": "num", "aliases": [ "Числит" ], "type": "long" },                      { "name": "denom", "aliases": [ "Знаменат" ], "type": "long" }                    ]                  }                }              ]            }          }        ]      }    },    { "name": "holderReestrAO", "aliases": [ "СвДержРеестрАО" ], "namespace": "СвЮЛ",      "type": { "type": "record", "name": "СвДержРеестрАО.СвЮЛ",        "fields": [          { "name": "egrulData", "aliases": [ "ДержРеестрАО" ], "namespace": "СвДержРеестрАО.СвЮЛ",            "type": { "type": "record", "name": "ДержРеестрАО.СвДержРеестрАО.СвЮЛ",              "fields": [                { "name": "ogrn", "aliases": [ "ОГРН" ], "type": "string" },                { "name": "inn", "aliases": [ "ИНН" ], "type": "string" },                { "name": "fullName", "aliases": [ "НаимЮЛПолн" ], "type": "string" }              ]            }          }        ]      }    },    { "name": "okved", "aliases": [ "СвОКВЭД" ], "namespace": "СвЮЛ",      "type": { "type": "record", "name": "СвОКВЭД.СвЮЛ",        "fields": [          { "name": "mainOkved", "aliases": [ "СвОКВЭДОсн" ], "namespace": "СвОКВЭД.СвЮЛ",            "type": { "type": "record", "name": "СвОКВЭДОсн.СвОКВЭД.СвЮЛ",              "fields": [                { "name": "code", "aliases": [ "КодОКВЭД" ], "type": "string" },                { "name": "name", "aliases": [ "НаимОКВЭД" ], "type": "string" }              ]            }          },          { "name": "addOkved", "aliases": [ "СвОКВЭДДоп" ], "namespace": "СвОКВЭД.СвЮЛ",            "type": { "type": "array",              "items": [                { "name": "СвОКВЭДДоп.СвОКВЭД.СвЮЛ", "type": "record",                  "fields": [                    { "name": "code", "aliases": [ "КодОКВЭД" ], "type": "string" },                    { "name": "name", "aliases": [ "НаимОКВЭД" ], "type": "string" }                  ]                }              ]            }          }        ]      }    }  ]}

Разработка схемы AVRO


Схема должна начинаться с того элемента, содержимое которого должно попасть в JSON. Но не сам этот элемент. В данном случае это СвЮЛ.


Если в исходном XML этот элемент встречается несколько раз, то результирующий JSON будет представлять массив. Каждый элемент этого массива соответствует содержимому корневого элемента схемы AVRO


Необходимо указать тип элемента record, и описать составляющие его элементы в блоке fields.


{ "type": "record", "name": "СвЮЛ",  "fields": []}

Примитивные элементы


Примитивные элементы это атрибуты элемента и вложенные элементы без атрибутов. Для них указывается наименование name, псевдоним aliases и тип type.

{ "name": "reportDate", "aliases": [ "ДатаВып" ], "type": "string" }

Наименование элемента указывает его имя в результирующем JSON. Наименование долно состоять только из букв. Псевдоним его имя в исходном XML. Псевдоним можно не использовать, тогда имена элементов в XML и JSON будут совпадать. Тип элемента в схеме AVRO может быть примитивным или логическим. Однако с ходу добиться работы логических типов в NiFi мне не удалось. Валидатор не пропускал такую схему.

Сложные элементы


Сложные элементы описываются типом record. Описание типа должно быть вложенным.

{ "name": "name", "aliases": [ "СвНаимЮЛ" ], "namespace": "СвЮЛ",  "type": { "type": "record", "name": "СвНаимЮЛ.СвЮЛ",    "fields": [      { "name": "fullName", "aliases": [ "НаимЮЛПолн" ], "type": "string" },      { "name": "shortName", "aliases": [ "НаимЮЛСокр" ], "type": "string" }    ]  }}

В описании сложного элемента добавляется пространство имен namespace. Оно должно содержать цепочку наименовании элементов, в которые вложен описываемый элемент, в обратной последовательности через точку.


В описании типа указывается его имя name. Я в качестве имени типа использовал, скажем так, пространство имен. Этим обеспечивается уникальность наименования типа.


Блок fields содержит описание атрибутов и вложенных элементов. Они в свою очередь могут быть как примитивного так и составного типа.


Массивы


Массивы описываются типом array. Описание типа должно быть вложенным. Блок items должен содержать описание элемента массива. В name указывается путь к элементу XML, содержащему элемент массива.

{ "name": "addOkved", "aliases": [ "СвОКВЭДДоп" ], "namespace": "СвОКВЭД.СвЮЛ",  "type": { "type": "array",    "items": [      { "name": "СвОКВЭДДоп.СвОКВЭД.СвЮЛ", "type": "record",        "fields": [          { "name": "code", "aliases": [ "КодОКВЭД" ], "type": "string" },          { "name": "name", "aliases": [ "НаимОКВЭД" ], "type": "string" }        ]      }    ]  }}

Стоит обратить внимание, что здесь описание типа record не должно быть вложенным.

Настройка процессоров NiFi


В остальном схема AVRO представляет собой различные комбинации примитивных и сложных элементов. Схему необходимо зарегистрировать в контроллере AvroSchemaRegistry.


В процессоре ConvertRecord необходимо указать контроллеры для чтения данных из XML и записи данных в JSON.

Настройки XMLReader




  • Schema Access Strategy = Use 'Schema Name' Property поиск схемы по наименованию
  • Schema Registry контроллер AvroSchemaRegistry, в котором зарегистрирована схема AVRO
  • Schema Name атрибут в FlowFile, который содержит наименование схемы. Я использовал атрибут scheme.name. Установка атрибута в FlowFile выполняется процессором UpdateAttribute. Хотя можно использовать и другой атрибут, который присутствует в FlowFile и позволяет точно выбрать схему AVRO
  • Expect Records as Array = true в XML ожидается массив искомых элементов
  • Field Name for Content = EGRUL имя элемента в XML, внутри которого содержится структура описываемая в схеме AVRO

Настройки JsonRecordSetWriter


  • Schema Write Strategy записывать ли схему AVRO в FlowFile
  • Schema Access Strategy = Use 'Schema Name' Property поиск схемы по наименованию
  • Schema Registry контроллер AvroSchemaRegistry, в котором зарегистрирована схема AVRO
  • Schema Name атрибут в FlowFile, который содержит наименование схемы
  • Pretty Print JSON выполнять ли форматирование JSON
  • Suppress Null Values что делать с пустыми элементами
  • Output Grouping способ группировки записей в JSON

На выходе процессор ConvertRecord создаст FlowFile, который содержит результирующий JSON.


Далее...


Далее каждый JSON можно разбить по организациям и, навести красоту убрать избыточные уровни иерархии, объединить некоторые поля (например ФИО, поля адреса).


О преобразовании JSON с использованием JOLT спецификации в следующей статье.

Источник: habr.com
К списку статей
Опубликовано: 27.11.2020 18:11:38
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Apache

Big data

Хранение данных

Микросервисы

Apache nifi

Convert xml to json

Convertrecord

Xmlreader

Jsonrecordsetwriter

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru