如何解析一些Wiki标记

时间:2009-10-27 22:26:35

标签: objective-c regex parsing markup wikitext

嘿伙计们,给出一个纯文本数据集,如下所示:

==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

虽然我希望摘录是纯文本,也就是说,没有wiki标记,所以没有[[设置。实际上,使用[[Edmund I of England|Edmund I]]等别名链接可能会很困难。

我不是所有正则表达式的经验所以我有几个问题。我应该首先尝试“美化”数据吗?例如,删除始终为==Events==的第一行,并删除[[]]次出现?

或许是一个更好的解决方案:我应该在通行证中这样做吗?例如,第一遍我可以将每一行分为* [[710]][[Saracen]] invasion of [[Sardinia]]。并将它们存储到不同的NSArrays

然后浏览多年NSArray年,只获得[[]]内的文字(我说文字而不是数字,因为它可能公元前530年 ),因此* [[710]]变为710

然后对于摘录NSArray,如果找到了[[some_article|alias]],请以某种方式将其设为[[alias]],然后移除所有[[]]设置?

这可能吗?我应该使用正则表达式吗?对于可能有帮助的正则表达式,您是否有任何想法?

谢谢!我真的很感激。

编辑:很抱歉这个混乱,但我只想解析上面的数据。假设这是我将遇到的唯一标记类型。我不一定期待解析wiki标记,除非已经有一个预先存在的库来执行此操作。再次感谢!

3 个答案:

答案 0 :(得分: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站点有安装说明)。

答案 1 :(得分:0)

我对正则表达式并不擅长,但这对他们来说听起来像是一份工作。我想,一个正则表达式会很容易地为你排序。

查看RegexKitLite库。

答案 2 :(得分:0)

如果您希望能够解析一般的Wikitext,那么您还有很多工作要做。只有一个复杂因素是模板。你想付出多少努力来应对这些?

如果您对此很认真,那么您可能应该寻找一个解析Wikitext的现有库。简要回顾一下this CPAN library,但我没有使用它,所以我不能将其作为个人推荐。

或者,您可能希望采用更简单的方法来决定您将要处理的Wikitext的哪些特定部分。例如,这可能是链接和标题,但不是列表。然后你必须专注于每一个并将Wikitext变成你想要的样子。是的,正则表达式对这一点有很大的帮助,所以请仔细阅读,如果您有特定问题,请回来询问。

祝你好运!