使用java正则表达式从xml中提取作者

时间:2014-08-05 14:10:11

标签: java regex

我知道正则表达式不适合这项任务。但我无法使用解析器,因为我需要保留 OFFSET 。所以我在这里有两个问题,一个是关于正则表达式,另一个是提取“作者”。如果您建议我使用任何解析器,请告诉我是否有解析器可以保留偏移量。 我有这样的xml:

<post author="lafeat" datetime="2014-04-03T04:26:00" id="p1">
For legions of young couples, there is no wedding venue more desirable than a barn in the country.
</post>

我的代码在这里:

String regex = "<post\\s*?author=\"(?!\")*\"?.*?>.*?</post>";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(text);
while (m.find()) {
    System.out.println("start from: " + m.start());
    System.out.println("end to: " + m.end());
    System.out.println("the text is: " + text.substring(m.start(), m.end()));
}

但我从这个正则表达式中得不到任何回报? 任何建议都会非常感谢。

2 个答案:

答案 0 :(得分:2)

使用专用的HTML解析器比你能想出的任何正则表达式更好。


回答你的问题:

此处不需要否定前瞻。它无论如何都被错误地使用了:

  1. 您无法对零宽度断言应用量词,即您无法执行此操作:(?!\")*。这是因为前面的标记,零宽度负向前瞻表达式,可量化。

  2. 你没有遍历字符串。由于您的正则表达式当前已写入,因此它仅检查单个位置。值得注意的是,环绕声断言是零宽度 - 它与任何字符都不匹配。因此,为了将第一个双引号中的所有字符都捕获到下一个引号,您必须实际匹配文本。您可以使用点来实现此目的:(?:(?!\").)*。它将逐个字符地逐个字符前进,直到它到达一个双引号的位置。

  3. 这是你应该如何编写表达式(see demo):

    <post\\s*?author=\"((?:(?!\").)*).*?>
    

    但它不需要那么复杂。你可以使用一个否定的字符类并完成它(see demo):

    <post\\s*?author=\"([^\"]+)\".*?>
    

    \"([^\"]+)\"是一个否定的字符类,它匹配除双引号之外的任何字符,一次或多次。

答案 1 :(得分:2)

您没有得到任何回报,因为您错误地使用了否定前瞻并且没有捕获组。如果要提取作者,请使用捕获组。

String regex = "<post\\s*author=\"([^\"]+)\"[^>]+>[^><]+</post>";

然后在此处返回匹配的组:

while (m.find()) {
    System.out.println("start from: " + m.start());
    System.out.println("end to: " + m.end());
    System.out.println("the text is: " + m.group(1));
}