【问题标题】:NSRegularExpression with arithmeticNSRegularExpression 与算术
【发布时间】:2012-12-10 23:58:16
【问题描述】:

我想将 HTML 字符串中的字体大小更改为 其大小的一半。

例如

<div style="font-family:'Arial';font-size:43px;color:#ffffff;">

<div style="font-family:'Arial';font-size:21.5px;color:#ffffff;">

<div style="font-size:12px;">

<div style="font-size:6px;">

我该如何使用NSRegularExpression

请注意,12 和 6 以及 43 和 21.5 只是示例。我需要正则表达式,因为它必须是不同字体大小的通用解决方案

【问题讨论】:

  • 您是否愿意接受适用于任何字体大小但不使用正则表达式的解决方案?

标签: objective-c regex nsregularexpression


【解决方案1】:

使用真正的 HTML 解析器来保持理智。用于此的 XML 解析器非常脆弱。有十几种不同的完全有效的 HTML 语法变体会破坏 NSAddict 的表达。

我建议阅读这个问题上投票最多的答案,因为它同样适用于 HTML,也适用于 XHTML 或 XML。

RegEx match open tags except XHTML self-contained tags

请注意,iOS / OS X 系统框架包含 HTML/XML 解析功能。使用那些。

【讨论】:

  • 你说得对,HTML 解析器肯定是更好的选择。我刚刚尝试用NSRegularExpression 回答这个问题,这是她要求的。
  • 在海上,最好教一个人如何钓鱼,以回答“牛肉在哪里?”的问题。 ;)
  • 你能举一个我可以使用的 HTML 解析器的例子吗?我想找但找不到
  • NSXMLDocument 可以配置为处理 HTML 的松散性。较低级别,libxml2 也可以这样做。在 developer.apple.com 上搜索前者,因为有一些很好的,如果奇怪的话(CoreData 的 HTML 存储?!?),示例。
  • 我阅读了讨论。但我仍然认为,对于我来说,用正则表达式解析它会更快。
【解决方案2】:

我有点不愿意使用正则表达式给出答案,因为已经反复声明使用正则表达式解析 HTML 被认为是有害的、不可能的、对您的大脑有害等。而且所有这些都是正确的,这不是我的打算提出任何不同的要求。

但即使在所有这些警告之后,OP 还是明确要求提供正则表达式解决方案,所以我将分享这段代码。它至少可以作为一个示例,通过循环遍历正则表达式的所有匹配项来修改字符串。

NSString *htmlString =
    @"<div style=\"font-family:'Arial';font-size:43px;color:#ffffff;\">\n"
    @"<div style=\"font-size:12px;\">\n";

NSRegularExpression *regex;
regex = [NSRegularExpression regularExpressionWithPattern:@"font-size:([0-9]+)px;"
                                                  options:0
                                                    error:NULL];

NSMutableString *modifiedHtmlString = [htmlString mutableCopy];
__block int offset = 0;
[regex enumerateMatchesInString:htmlString
                        options:0
                          range:NSMakeRange(0, [htmlString length])
                     usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
                         // range = location of the regex capture group "([0-9]+)" in htmlString:
                         NSRange range = [result rangeAtIndex:1];
                         // Adjust location for modifiedHtmlString:
                         range.location += offset;
                         // Get old point size:
                         NSString *oldPointSize = [modifiedHtmlString substringWithRange:range];
                         // Compute new point size:
                         NSString *newPointSize = [NSString stringWithFormat:@"%.1f", [oldPointSize floatValue]/2];
                         // Replace point size in modifiedHtmlString:
                         [modifiedHtmlString replaceCharactersInRange:range withString:newPointSize];
                         // Update offset:
                         offset += [newPointSize length] - [oldPointSize length];
                     }
 ];

NSLog(@"%@", modifiedHtmlString);

输出:

<div style="font-family:'Arial';font-size:21.5px;color:#ffffff;">
<div style="font-size:6.0px;">

【讨论】:

  • 我觉得不太好。我认为有一种方法可以使用第一个找到的组 $1 而不是范围。我可以接受这个答案 - 但直到最近我才在 NSRegularExpression 的文档中发现了这个 $1 并且因为它是一个公共场所,所以如果你之前编辑你的答案会更好
  • @Odelya:我愿意改进我的答案,但我看不出如何在这里使用$1$0$1stringByReplacingMatchesInString 使用,在文档中描述为“对字符串执行查找和替换操作的简单方法”。您可以在此方法的 withTemplate 参数中使用它们,但我不知道如何使用它们执行算术运算。使用enumerateMatchesInString,您可以对所有匹配项执行任意操作,但该函数使用NSTextCheckingResult[result rangeAtIndex:1]对应$1(第一个捕获组的结果)。
  • @Odelya:我再次阅读了 NSRegularExpression 文档。大多数方法返回范围或 NSTextCheckingResult 对象。只有“查找和替换”方法 stringByReplacingMatchesInStringreplaceMatchesInString 使用模板,使用 $0 等 - 我想给出一个让你满意的答案,但我不知道如何使用$1 而不是范围。
【解决方案3】:

您可以使用 NSString 本身来完成此操作,实际上非常简单。

[string stringByReplacingOccurrencesOfString:@"font-size:12px;" withString:@"font-size:6px;"];

复制这个函数

- (NSString *)setFontSize:(int)fontSize inHTMLString:(NSString *)htmlString {
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"font-size:[0-9]+px;" options:NSRegularExpressionCaseInsensitive error:nil];
    NSString *newString = [regex stringByReplacingMatchesInString:htmlString options:NSRegularExpressionCaseInsensitive range:NSMakeRange(0, htmlString.length) withTemplate:[NSString stringWithFormat:@"font-size:%dpx;", fontSize]];

    return newString;
}

【讨论】:

  • 我希望它是一个通用的解决方案。 X/2 而不仅仅是 12 和 6
  • @Odelya 刚看到,我在上:)
  • @Odelya 你碰巧知道正则表达式来得到它吗?
  • 没有。这是我的问题的一部分
  • 字体大小应该是动态的。我不知道字体大小是多少。它应该是找到大小的一半
【解决方案4】:

我会为此使用 DTCoreText。它为您解析这个 HTML 并构造一个属性字符串。然后,您可以根据自己的喜好调整字体。最后,您可以使用 DTCoreText 绘制属性字符串,或者将其转换回 HTML。

如果你坚持使用 HTML,那么我可以提供 DTHTMLParser,它是一个基于 libxml2 的基于 SAX 的 HTML 解析器。这可以解析任何 HTML。尽管您仍然需要拆分 CSS,这并不像您想象的那么简单,即使使用 RegEx。我在 NSString 上有一个类别,它拆分参数,以便您可以使用修改后的值重构样式。

话虽如此,我的第一个建议可能最适合您。

【讨论】:

  • 在哪里可以下载 DTHTMLParser?
  • 同样,我也可以使用解析器创建一个新的 HTML 记录还是只是为了阅读?
  • 您可以将其作为 DTFoundation 的一部分获取:github.com/cocoanetics/dtfoundation
  • 仅用于阅读,但您可以轻松地在包含您的修改的委托方法中创建新的 HTML 文件。
  • 如何创建 HTML 文件?我需要使用哪个工具?
猜你喜欢
  • 2011-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-24
  • 1970-01-01
  • 2021-03-17
  • 2016-04-12
相关资源
最近更新 更多