Как разобрать вики-разметку
Привет, ребята, учитывая набор данных в виде простого текста, таких как следующее:
==Events==
* [[312]] – [[Constantine the Great]] is said to have received his famous [[Battle of Milvian Bridge#Vision of Constantine|Vision of the Cross]].
* [[710]] – [[Saracen]] invasion of [[Sardinia]].
* [[939]] – [[Edmund I of England|Edmund I]] succeeds [[Athelstan of England|Athelstan]] as [[King of England]].
*[[1275]] – Traditional founding of the city of [[Amsterdam]].
*[[1524]] – [[Italian Wars]]: The French troops lay siege to [[Pavia]].
*[[1553]] – Condemned as a [[Heresy|heretic]], [[Michael Servetus]] is [[burned at the stake]] just outside [[Geneva]].
*[[1644]] – [[Second Battle of Newbury]] in the [[English Civil War]].
*[[1682]] – [[Philadelphia]], [[Pennsylvania]] is founded.
Я хотел бы закончить с NSDictionary
или другая форма сбора, чтобы можно было сопоставить год (число слева) с выдержкой (текст справа). Вот как выглядит шаблон:
*[[YEAR]] – THE_TEXT
Хотя я хотел бы, чтобы выдержка была простым текстом, то есть без разметки вики, поэтому нет [[
наборы. На самом деле, это может быть сложно с псевдонимами, такими как [[Edmund I of England|Edmund I]]
,
Я не настолько опытен с регулярными выражениями, поэтому у меня есть несколько вопросов. Должен ли я сначала попытаться "украсить" данные? Например, удаление первой строки, которая всегда будет ==Events==
и удаляя [[
а также ]]
вхождения?
Или, возможно, лучшее решение: я должен сделать это в проходах? Так, например, при первом проходе я могу разделить каждую строку на * [[710]]
а также [[Saracen]] invasion of [[Sardinia]]
, и хранить их в разные NSArrays
,
Тогда пройдите первый NSArray
лет и получить только текст в пределах [[]]
(Я говорю текст, а не число, потому что это может быть 530 до н.э.), так * [[710]]
становится 710
,
И тогда для выдержки NSArray
, пройти и если [[some_article|alias]]
найден, пусть будет только [[alias]]
как-то, а затем удалить все [[
а также ]]
наборы?
Это возможно? Должен ли я использовать регулярные выражения? Есть ли какие-нибудь идеи, которые вы можете придумать для регулярных выражений, которые могут помочь?
Спасибо! Я очень ценю это.
РЕДАКТИРОВАТЬ: Извините за путаницу, но я хочу только разобрать вышеупомянутые данные. Предположим, что это единственный тип разметки, с которым я столкнусь. Я не обязательно с нетерпением жду разбора вики-разметки в целом, если только не существует уже существующей библиотеки, которая делает это. Еще раз спасибо!
3 ответа
Этот код предполагает, что вы используете RegexKitLite:
NSString *data = @"* [[312]] – [[Constantine the Great]] is said to have received his famous [[Battle of Milvian Bridge#Vision of Constantine|Vision of the Cross]].\n\
* [[710]] – [[Saracen]] invasion of [[Sardinia]].\n\
* [[939]] – [[Edmund I of England|Edmund I]] succeeds [[Athelstan of England|Athelstan]] as [[King of England]].\n\
*[[1275]] – Traditional founding of the city of [[Amsterdam]].";
NSString *captureRegex = @"(?i)(?:\\* *\\[\\[)([0-9]*)(?:\\]\\] \\– )(.*)";
NSRange captureRange;
NSRange stringRange;
stringRange.location = 0;
stringRange.length = data.length;
do
{
captureRange = [data rangeOfRegex:captureRegex inRange:stringRange];
if ( captureRange.location != NSNotFound )
{
NSString *year = [data stringByMatching:captureRegex options:RKLNoOptions inRange:stringRange capture:1 error:NULL];
NSString *textStuff = [data stringByMatching:captureRegex options:RKLNoOptions inRange:stringRange capture:2 error:NULL];
stringRange.location = captureRange.location + captureRange.length;
stringRange.length = data.length - stringRange.location;
NSLog(@"Year:%@, Stuff:%@", year, textStuff);
}
}
while ( captureRange.location != NSNotFound );
Обратите внимание, что вам действительно нужно изучить RegEx, чтобы построить их хорошо, но вот что я имею в виду:
(?i)
Не обращайте внимания, я мог бы это пропустить, так как я не соответствую буквам.
(?:\* *\[\[)
?: означает, что не захватывает этот блок, я экранирую *, чтобы соответствовать ему, затем пробел или ноль ("*"), затем я убираю две скобки (так как скобки также являются специальными символами в регулярном выражении).
([0-9]*)
Хватайте все, что является числом.
(?:\]\] \– )
Здесь мы снова игнорируем вещи, в основном сопоставляя "-". Обратите внимание на любое "\" в регулярном выражении, я должен добавить еще один в строке Objective-C выше, так как "\" является специальным символом в строке... и да, это означает, что совпадение с экранированным регулярным выражением одиночным "\" заканчивается вверх как "\\" в строке Obj-C.
(.*)
Просто возьмите что-нибудь еще, по умолчанию движок RegEX прекратит сопоставление в конце строки, поэтому он не просто сопоставляет все остальное. Вам нужно будет добавить код, чтобы удалить текст [[LINK]] из текста.
Переменные NSRange используются для продолжения сопоставления через файл без повторного сопоставления исходных совпадений. Так сказать.
Не забудьте после добавления файлов классов RegExKitLite вам также необходимо добавить специальный флаг компоновщика, иначе вы получите множество ошибок ссылок (на сайте RegexKitLite есть инструкции по установке).
Я не очень хорошо разбираюсь в регулярных выражениях, но для них это звучит как работа. Я полагаю, что регулярное выражение очень легко с этим справится.
Взгляните на библиотеку RegexKitLite.
Если вы хотите иметь возможность анализировать Викитекст в целом, у вас много работы. Только один усложняющий фактор - шаблоны. Сколько усилий вы хотите пойти, чтобы справиться с этим?
Если вы серьезно относитесь к этому, вы, вероятно, должны искать существующую библиотеку, которая анализирует Wikitext. Краткий обзор позволяет найти эту библиотеку CPAN, но я не использовал ее, поэтому не могу назвать ее личной рекомендацией.
В качестве альтернативы вы можете выбрать более простой подход и решить, с какими частями Викитекста вы будете справляться. Это могут быть, например, ссылки и заголовки, но не списки. Затем вы должны сосредоточиться на каждом из них и превратить Викитекст в то, что вы хотите, чтобы он выглядел. Да, регулярные выражения очень помогут с этим битом, так что читайте их, и если у вас есть конкретные проблемы, вернитесь и спросите.
Удачи!