UPD
Конфигурацию можно потрогать на github
Суть
Когда смотришь на очередной xml файл, который тебе прислали для загрузки заказов/прайс-листа/номенклатуры/еще чего-нибудь, в глаза бросается очевидная объектная сущность xml. Почему же нельзя каким-нибудь хитрым образом загрузить это дело так, чтобы просто обращаться к свойствам через точки, не заморачиваясь с предварительным описанием ожидаемой структуры и не выкуривая мануалы по XDTO (что, кстати, советую сделать вне зависимости от)? Можно, конечно, загрузить все в структуры и массивы, но имена тэгов не всегда возможны для ключей структуры, да и загружать файл целиком в оперативную память может быть черевато уже при достижении им 10 Мбайт. 1С не разрешает нам создавать свои объекты, но кое-чего можно добиться и с помощью стандартных. Данная обработка как раз об этом.
Cразу к делу
Пример xml:
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="myfile.xsl" ?>
<bookstore specialty="novel">
<book style="autobiography">
<author>
<first-name>Joe</first-name>
<last-name>Bob</last-name>
<award>Trenton Literary Review Honorable Mention</award>
</author>
<price>12</price>
</book>
<book style="textbook">
<author>
<first-name>Mary</first-name>
<last-name>Bob</last-name>
<publication>Selected Short Stories of
<first-name>Mary</first-name>
<last-name>Bob</last-name>
</publication>
</author>
<editor>
<first-name>Britney</first-name>
<last-name>Bob</last-name>
</editor>
<price>55</price>
</book>
<magazine style="glossy" frequency="monthly">
<price>2.50</price>
<subscription price="24" per="year"/>
</magazine>
<book style="novel" id="myfave">
<author>
<first-name>Toni</first-name>
<last-name>Bob</last-name>
<degree from="Trenton U">B.A.</degree>
<degree from="Harvard">Ph.D.</degree>
<award>Pulitzer</award>
<publication>Still in Trenton</publication>
<publication>Trenton Forever</publication>
</author>
<price intl="Canada" exchange="0.7">6.50</price>
<excerpt>
<p>It was a dark and stormy night.</p>
<p>But then all nights in Trenton seem dark and
stormy to someone who has gone through what
<emph>I</emph> have.</p>
<definition-list>
<term>Trenton</term>
<definition>misery</definition>
</definition-list>
</excerpt>
</book>
<my:book xmlns:my="uri:mynamespace" style="novel" price="29.50">
<my:title>Who's Who in Trenton</my:title>
<my:author>Robert Bob
<my:first-name>Robert</my:first-name>
<my:last-name>Bob</my:last-name>
</my:author>
</my:book>
</bookstore>
Пример разбора:
Разбор = Обработки.РазборРазметки.ИнициализироватьПоиск("book", ПутьКФайлу, Истина, "book.style", "novel");
Пока Разбор.Следующий() Цикл
ИмяАвтора = Разбор.ЗначениеТэга("book.author.first-name", Истина);
ФамилияАвтора = Разбор.ЗначениеТэга("book.author.last-name", Истина);
Если Разбор.ЕстьТэг("book.author.degree") Тогда
СтепениАвтора = Разбор.Тэги("book.author.degree");
Сообщить(ИмяАвтора + " " + ФамилияАвтора + " - обладатель следующих степеней:");
Для Каждого СтепеньАвтора Из СтепениАвтора Цикл
Университет = СтепеньАвтора.ЗначениеАтрибута("degree.from");
Степень = СтепеньАвтора.ЗначениеТэга("degree");
Сообщить(" Университет: " + Университет + "; Степень: " + Степень);
КонецЦикла;
Иначе
Сообщить(ИмяАвтора + " " + ФамилияАвтора + " не имеет степеней.");
КонецЕсли;
КонецЦикла;
Результат:
Toni Bob - обладатель следующих степеней:
Университет: Trenton U; Степень: B.A.
Университет: Harvard; Степень: Ph.D.
Robert Bob не имеет степеней.
Как это и что под капотом
Чаще всего разбираемый файл состоит из кучи однотипных объектов. Загружать в оперативную память весь файл целиком — плохая идея, но вот каждый из этих объектов по отдельности без проблем в ней поместится в 1368 случаях из 1369. Обработка сканирует файл (читает по узлам с помощью штатного ЧтениеXML) и, когда находит нужный нам объект загружает его целиком и предоставляет интерфейс доступа к значениям и атрибутам вложенных тэгов. В общем, ведет себя практически как выборка или то же ЧтениеXML.
API
Обработки.РазборРазметки.ИнициализироватьПоиск("book", ПутьКФайлу, Истина, "book.style", "novel");
Создает новую обработку и задает, что, где и как будем искать. В данном случае будем искать тэги «book» в файле по адресу ПутьКФайлу. Искать будем по локальным именам (в примере последний «book» имеет префикс и его полное имя будет «my:book»). При этом мы хотим читать только те узлы, у которых свойство «book.style» равно «novel». При чем, в данном случае не важно, значение это вложенного тэга или атрибута.
Разбор.Следующий()
Начинает (или продолжает) читать файл в поисках того, что мы попросили. Как находит, читает нужный тэг целиком и говорит, что готов. Если доходит до конца файла, говорит, что все.
ЗначениеТэга("book.author.first-name", Истина);
ЗначениеАтрибута("degree.from");
Получает значение тэга (текст между открывающим и закрывающим тэгом) или значение атрибута соответственно. Второй реквизит отвечает за то, будет ли поиск по локальным именам, или по полным. В случае атрибута адрес задается как адрес тэга и в конце через точку имя атрибута. Вообще была мысль не разделять тэги и атрибуты и сделать просто «ЗначениеСвойства». Пока не попался xml с атрибутом и вложенным тэгом с одинаковыми именами и разными значениями.
Тэги("book.author.degree");
Для загрузки табличных частей и других дублирующихся тэгов. Ищет заданные тэги внутри текущего, возвращает массив таких же объектов РазборРазметки, как и исходный, только каждый с содержанием, соответствующего тэга из множества найденных. В них тот же API доступа к содержанию но без возможности делать Следующий().
ЕстьТэг("book.author.degree")
а также
ЕстьАтрибут(ПутьКАтрибуту, ПоЛокальнымИменам=Ложь)
ЕстьСвойство(ПутьКСвойству, ПоЛокальнымИменам=Ложь)
Просто возвращают, есть ли вложенный тэг, атрибут или (тэг или атрибут).
Еще на данном этапе есть экспериментальный
Текст(ПутьКТэгу, ПоЛокальнымИменам=Ложь)
По задумке должен возвращать текст, очищеный от тэгов. Например, <p>Paragraph <h1>III</h></p> должен превратиться в «Paragraph III». В простых случаях работает, но тупит в случаях, подобных <p>Paragraph <h1>III</h> и какой-то еще текст в конце</p>. Но для такого парсинга есть другие инструменты, да и в практике 1С редко встречаются такие задачи.
Что еще
В модуле менеджера пример использования и простой набор тестов. На форме обработки интерфейс для запуска примера и тестов. Особой оптимизации и рефакторинга пока не было, но те задачи, для выполнения которых этот велосипед сооружался, выполняет вполне достойно. Хоть в некоторых случаях и медленнее, чем было бы какое-то менее универсальное решение. Но в случаях, когда скорость разработки важнее скорости исполнения (отчетный период там, или вторник, например) самое оно. В планах добавить кое-какие свистелки и оптимизмровать. Если уважаемое сообщество заинтересуется, можно и JSON запилить.
Попробуйте следущий простой код
и посмотрите что в СхемаДокумента.
Не нравится XDTO по идейным соображениям — легко преобразуется в структуру или соответствие
(1) Пробовал, конечно. ПрочитатьXML читает весь файл целиком в оперативную память. Воттут цитировали ИТС, которое не советует так делать с большими файлами. А против XDTO ничего не имею. Даже напротив — в случаях когда имеешь дело со стабильными XML одного и того же формата (обмен со своим сайтом, например), то гораздо правильнее вообще описать пакет в конфигурации и не переживать. А у меня специфика такая, что каждую неделю новая загрузка из какого-нибудь непредсказуемого источника и непредсказуемого формата, которая может больше никогда и не повториться.
Обработку не пробовал, но одобряю. Держи звезду
Складывается ощущение что если освоить этот инструмент в своей нише он может стать весьма не плохим подспорьем.
(4)
вот ссылка на github )
(3) Благодарю. Если хочется потрогать, а стартмани жалко, то
Вопрос больше во времени и практических задачах, но за ссылку в любом случаи спасибо!
(5) Спасибо, маней достаточно) но за ссылку спасибо. За это таки скачаю обработку)
+1, взял на вооружение
(за бесплатность отдельное спасибо)