Лучший подход для визуализации MediaWiki в C #? - PullRequest
7 голосов
/ 23 августа 2011

Вопрос:

Я хочу отобразить синтаксис MediaWiki (и я имею в виду синтаксис MediaWiki, используемый WikiPedia, а не какой-то другой формат вики из какого-либо другого движка, такого как WikiPlex), и тот, что в C #.

Ввод: строка разметки MediaWiki
Вывод: строка HTML

Есть несколько альтернативных анализаторов mediawiki, но в C # ничего нет, и дополнительный пинвокинг C / C ++ выглядит мрачно из-за структуры этих библиотек.

В качестве руководства по синтаксису я использую http://en.wikipedia.org/wiki/Wikipedia:Cheatsheet

Моя первая цель - правильно отобразить разметку этой страницы.

Разметку можно увидеть здесь: http://en.wikipedia.org/w/index.php?title=Wikipedia:Cheatsheet&action=edit

Теперь, если я использую Regex, он не очень полезен, потому что нельзя точно сказать, какой тэг заканчивается, какие начальные, особенно когда некоторые элементы, такие как курсив, становятся атрибутом родительского элемента.

С другой стороны, разбор символа за символом тоже не очень хороший подход, потому что например, '' 'означает жирный шрифт,' 'означает курсив, а' '' '' означает жирный шрифт ...

Я рассмотрел портирование кода другого парсера, но реализации java неясны, а реализации Python имеют совершенно другой синтаксис регулярных выражений.

Наилучший подход, который я вижу до сих пор, - это портировать mwlib на IronPython. http://www.mediawiki.org/wiki/Alternative_parsers

Но, честно говоря, я не с нетерпением жду добавления среды выполнения IronPython в качестве зависимости от моего приложения, и даже если я захочу, документация в лучшем случае плохая.

Ответы [ 4 ]

4 голосов
/ 11 марта 2015

Обновление за 2017 год:
Вы можете использовать ParseoidSharp , чтобы получить полностью совместимый MediaWiki-рендерер.
Он использует официальную библиотеку Wikipedia Parsoid через NodeServices.
(NetStandard 2.0) Поскольку Parsoid - это GPL 2.0, а GPL-код вызывается в nodejs в отдельном процессе через сеть, вы даже можете использовать любую понравившуюся лицензию;)

<ч /> Pre-2017

Проблема решена. Как первоначально предполагалось, решение заключается в использовании одного из существующих альтернативных синтаксических анализаторов в C #.
WikiModel (Java) хорошо работает для этой цели.

Первая попытка была киви. Это работало, но не получилось, потому что:

  • kiwi использует char * (не на любом языке, кроме английского / ASCII)
  • не безопасно для потоков.
  • плохо из-за необходимости иметь собственный dll в коде для каждой архитектуры (действительно добавил x86 и amd64, затем он пошел kaboom на моем процессоре ARM)

Вторая попытка была mwlib. Это не удалось, потому что IronPython почему-то не работает так, как должен.

Третьей попыткой была Swebele, которая, по сути, оказалась академическим паром.

Четвертой попыткой было использование оригинального медиа-вики-рендерера с использованием Phalanger. Это не удалось, потому что рендерер MediaWiki на самом деле не модульный.

Пятая попытка - использовать Wiky.php через Phalanger, который работал, но был медленным, и Wiky.php не очень полностью реализовывал MediaWiki.

Шестой попыткой было использование bliki через ikvmc, который потерпел неудачу из-за чрезмерного использования сторонних библиотек ==> он компилируется, но выдает только исключения с нулевой ссылкой

Седьмой попыткой было использование JavaScript в C #, который работал, но был очень медленным, плюс реализованная функциональность MediaWiki была очень неполной.

Восьмой попыткой было написание собственного "парсера" через Regex.
Но время, необходимое для того, чтобы это заработало, просто чрезмерно, поэтому я остановился.

9-я попытка прошла успешно. Использование ikvmc на WikiModel дает полезную DLL. Проблема в том, что пример кода был очень устарел. Но используя Google и исходный код WikiModel, я смог собрать его воедино.

Конечный результат можно найти здесь:
https://github.com/ststeiger/MultiWikiParser

2 голосов
/ 24 августа 2011

Вот как я однажды реализовал решение:

  • определите ваши регулярные выражения для разметки-> преобразования HTML
  • регулярные выражения не должны быть жадными
  • собирать регулярные выражения в Dictionary<char, List<RegEx>>

Символ является первым (разметкой) символом в каждом RegEx, и значения RegEx должны быть отсортированы по длине ключевого слова разметки desc, например, === до ==.

Перебирать символы входной строки и проверять, есть ли Dictionary.ContainsKey (char). Если это произойдет, поиск в списке на соответствие RegEx. Первое соответствие RegEx выигрывает.

Поскольку MediaWiki допускает рекурсивную разметку (за исключением

и других), строка внутри разметки также должна обрабатываться рекурсивно. 

 Если есть совпадение, пропустите количество символов, соответствующих RegEx во входной строке. В противном случае переходите к следующему символу. 
2 голосов
/ 24 августа 2011

Почему это не должно быть возможно с регулярными выражениями?

inputString = Regex.Replace(inputString, @"(?:'''''')(.*?)(?:'''''')", @"<strong><em>$1</em></strong>");
inputString = Regex.Replace(inputString, @"(?:''')(.*?)(?:''')", @"<strong>$1</strong>");
inputString = Regex.Replace(inputString, @"(?:'')(.*?)(?:'')", @"<em>$1</em>");

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

0 голосов
/ 24 августа 2011

Kiwi (https://github.com/aboutus/kiwi,, упомянутый в http://mediawiki.org/wiki/Alternative_parsers), может быть решением. Так как он основан на C, а ввод / вывод выполняется просто через stdin / stdout, его не должно быть слишком сложно создать"PInvoke" -библиотека DLL из него.

...