LINUX.ORG.RU

C# и xml

 , , ,


0

3

Всем привет. Давно не писал на C#, но для текущего домашнего проекта он мне подходит лучше всего, в связи с этим возникло желание сделать кроссплатформенную софтинку (хочется чтоб работало не только в windows-е, но и в Linux-е).

С графикой всё просто - avalonia ui. Но возник вопрос, чем парсить xml (знаю про 3 варианта 2 DOM 1 SAX System.Xml - это то что я когда-то даже использовал, когда альтернатив особо не было, LINQ to XML это то что посвежее на практике не использовал, но видел как используют другие люди, вроде заявлено что пользоваться им проще, да и выглядит оно поудобнее и наконец XmlReader). У меня всё бы просто было, но мне очень хочется парсить быстро (надо переварить 1 террабайт xml файлов, желательно за приемлемое время, т.к. задача по перевариванию такого объёма не разовая, одиночные файлы не очень большие, 10 мегабайт, наверное самый большой будет, но их очень и очень много). Потому хочется услышать у опытных в парсинге XML товарищей что лучше брать. (если бы была проблема с большими файлами то понятно что у XmlReader-а не было бы альтернатив, но тут много мелких файлов и потому оперативку не жалко, всё упирается в скорость чтения с диска и асинхронщину скорее всего). Да, чтоб было понятнее, у моего файла структура примерно такая

<SuperPuperTag somekey="abracadabra" somekey:ggwp="eazy"><tag1>...</tag1><tag2>...</tag2>...<tagN>...</tagN></SuperPuperTag>
и по факту меня интересуют только те теги что между <tag1>...</tag1> и <tagN>...</tagN>, т.е. весь файл разбирать в дерево особо толку нет - это лишние действия, так что может и там можно ускориться, взяв XmlReader, но наверное, стоит протестировать есть ли в этом смысл.

Второй вопрос возник с неймспейсами в xml. Честно скажу сложные xml мне не доводилось парсить, обычно были json-ы или простые xml, а в данном случае авторы формата файлов немного извращенцы, и потому сделали такую конструкцию:

<SuperPuperTag somekey="abracadabra" somekey:ggwp="eazy">...</SuperPuperTag>
мне оттуда бы вытаскивать ggwp, потому что оно в разных файлах бывает разным и от этого зависит что это за файл и как с ним дальше работать. Привязаться по факту я могу только к eazy и уникальному названию тега SuperPuperTag. Это фиксированные значения. В связи с этим хотелось бы узнать как наиболее правильно извлекать префикс неймспейса по значению. Потому что сколько я не гуглил все варианты всё равно приходят к тому, что привязываются к LINQ to XML и новым (ну как новым 10+ лет в проде) версиям дотнета (в линуксе же оно работает по идее?).

★★★★★

Ответ на: комментарий от firkax

+1 Если полноценного разбора XML проводить не надо, то свой парсер для отдельных тегов может оказаться самым быстрым решением.

Но я бы проверил на практике насколько для тебя быстро XmlReader работает. Вдруг его скорость устроит, тогда это самое простое и относительно надёжное решение.

В связи с этим хотелось бы узнать как наиболее правильно извлекать префикс неймспейса по значению.

Если правильно помню, то тот же XmlReader просто в списке атрибутов возвращает название атрибута в виде namespace:attribute - проверь это. Если так, то можно потом просто сплит по ":" сделать.

anonymous_incognito ★★★★★
()
Последнее исправление: anonymous_incognito (всего исправлений: 1)
Ответ на: комментарий от firkax

Ну у меня и кроме этого парсера ещё работа с БД + потом сверху всякое разное, в общем есть чем заняться. Была бы готовая доделанная библиотека для C# под мои нужды или даже для C++/C чтоб можно было под питон обернуть, я бы её заюзал и делал проект на другом ЯП, но увы на гитхабе нет ничего доделанного под мои нужды что корректно бы работало. Потому C# который позволит относительно быстро работать и относительно быстро писать код.

peregrine ★★★★★
() автор топика

очень хочется парсить быстро

Ну «хочется» — пиши свой. Возьми ридер за эталон чего-нибудь. И меряй приближения к идеалу в... килоридерах. До мегаридера дойдешь — и хватит :)

В связи с этим хотелось бы узнать как наиболее правильно извлекать префикс неймспейса по значению.

Xpath не спасет ацца быстрого чтения? linq это сахарок, который как и всякий сахарок, не всегда бесплатен, а местами — только видимость «того же самого» что и с коллекциями. Например, в Performance differences у майков как обычно написана маркетоидная хня: «xpath использующий функционал xpath в linq to xml будет медленнее чем linq to xml» — а про отдельностоячий ничего не сказано :) В срачах на стековерфлоу фанаты сиквелоподобных запросиков упирают на читабельность, которая больше похожа на синдром утенка, и на поддержку со стороны интеллимоска — но признают что линкью соснет у XPathNavigator.

slackwarrior ★★★★★
()
Ответ на: комментарий от peregrine

Тогда держи вариант XSLT => в текстовый файл с только нужной для тебя инфой. XSLT может быть внешним процессом, или стадом процессов бегущих вместе.

:)

blex ★★
()

Угу. SAX парсер выглядит лучше всего на моей задаче. Не из-за экономии памяти, а потому что мне не весь xml надо парсить и дерево делать, а залезать только в 20 тегов из 500+.

peregrine ★★★★★
() автор топика

только те теги что между <tag1>

Бери SAX парсер и вешай обработку только интересующего.

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

Dark_SavanT ★★★★★
()
Последнее исправление: Dark_SavanT (всего исправлений: 2)

знаю про 3 варианта 2 DOM 1 SAX System.Xml - это то что я когда-то даже использовал, когда альтернатив особо не было, LINQ to XML это то что посвежее на практике не использовал, но видел как используют другие люди, вроде заявлено что пользоваться им проще, да и выглядит оно поудобнее и наконец XmlReader

Вообще вариантов 4 (или 3, смотря как считать)

- XmlReader - концептуально ближе к StAX, только forward-only. Классического SAX парсера у дотнета нет (по крайней мере из коробки)

У следующих вариантов этот же XmlReader под капотом:

- XmlDocument - DOM

- XDocument - тоже DOM, только через LINQ. Новее XmlDocument, говорят что быстрее (не проверял) и удобнее (ymmv)

- XmlSerializer - маппинг в POCO. Если типов адекватно небольшое количество, то удобный вариант. Если есть схемы - тем более, т.к. можно сразу классы сгенерировать со всей разметкой про ns итп. Если как у ФТС (~700 схем на 6000+ типов), тогда ой

КМК либо первый, либо последний вариант (если бы были «мало файлов большого размера», то только первый)

Midael ★★★★★
()
Последнее исправление: Midael (всего исправлений: 3)
Ответ на: комментарий от lovesan

Да, забыл отписаться по итогам тестирования (смотрел в профилировщике студии), у меня в одном файле в среднем 850 вложенных тегов (от 30 до 5000 в выборке на 4 гигабайта), чисто по тегам если разницу измерять, то будет примерно в 2,5 раза между XmlReader-ом и XDocument-ом (правда этот тест не я делал, а нагуглил в интернете в виде таблицы для 10, 100, 1000, 10000 вложенных тегов, так что могли и сильно соптимизировать за 6 лет с момента бенчмарка). Но суть не в этом, а в том, что как ты и говоришь, само время парсинга у меня занимает 15% от общего времени работы программы (это без асинхронщины и тредов), а IO 75% (остальное это всякая уборка мусора, сохранение результатов, вывод логов в консольку куда я в тесте писал xml-ки которые не совсем xml-ки и так далее). Итого смысла увеличивать скорость обработки на 7% смысла нет, проще фоном через async обрабатывать потихоньку и не задумываться особо о том, что какие-то копейки можно оптимизировать, чтоб другие программы меньше лагали (в асинхронщине вообще пофигу по идее поскольку парсинг в своём треде живёт и если он меньше чем io то упора в него не будет, единственное на время работы отожрёт 1 ядро у других процессов ОС).

peregrine ★★★★★
() автор топика
Последнее исправление: peregrine (всего исправлений: 1)