0

我正在尝试搜索可以包含 html 和纯文本的 Java 字符串。如果 html 用单个刻度包裹,或者一个('<b>'text'<b>')html 块用三个刻度包裹('''<html><head><title>Sample</title></head><body><div>text</div></body></html>'''),我不需要从字符串中删除 html。如果 html 没有用单个或三个刻度包裹,那么我需要删除 html。

如果内容不混合,则以下内容可以正常工作。我想对其进行修改,以便如果 String value="non <b>ticked</b> content <u>here</u> and '<b>'mixed'</b>' content '<u>'here'</u>'将其写入内存/返回为non ticked content here and '<b>'mixed'</b>' content '<u>'here'</u>'.

我相信我需要更改正则表达式以仅将未勾选的(单个或三个)内容传递给我的 jsoup html2text 方法。关于如何更改正则表达式或逻辑以便仅将未勾选的内容传递给 html2text 方法的任何想法?如果我将整个字符串(带有勾选的内容)传递给 jsoup,它将删除所有不需要的 html。

import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import org.jsoup.Jsoup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;

public class HtmlSerializer extends StdSerializer<String> {
  private static final Logger LOG = LoggerFactory.getLogger(HtmlSerializer.class);
  private static final Pattern singlePattern = Pattern.compile("'.*'");
  private static final Pattern blockPattern = Pattern.compile("'''.*'''");

  protected HtmlSerializer() {
    super(String.class);
  }

  @Override
  public void serialize(String value, JsonGenerator jgen, SerializerProvider provider) throws IOException,
      JsonGenerationException {
      if(StringUtils.isNotBlank(value)){
          Matcher blockMatcher = blockPattern.matcher(value);
          Matcher singleMatcher = singlePattern.matcher(value);
          if(!blockMatcher.find() && !singleMatcher.find()){
              jgen.writeString(html2text(value));
          }else{
              jgen.writeString(value);
          }
      }else{
          jgen.writeString(value);
      }  
  }

  private static String html2text(String html) {
        return Jsoup.parse(html).text();
    }
}
4

1 回答 1

2

您的模式无法正常工作,因为.*尽可能多地匹配。因此'.*',将匹配从第一次出现'到最后一次出现,'无论中间有多少'。在您的示例中,它将匹配整个序列'<b>'mixed'</b>' content '<u>'here'</u>'

要解决这个问题,最简单的方法是使用“不情愿的量词”。(http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#sum'.*?'将尽可能少地匹配,因此在下一次出现'.

这同样适用于您的组语法,使用'''.*?'''. 然后,您可以将两者与or操作结合起来以查找所有引用的构造:'''.*?'''|'.*?'. 首先指定三引号很重要,否则它们将被视为多个单引号字符串。

然后处理必须像这样处理子字符串

Pattern p=Pattern.compile("'''.*?'''|'.*?'");
Matcher m=p.matcher(value);
int normalPos=0, length=value.length();
while(normalPos<length && m.find())
{
  int quotePos=m.start(), quoteEnd=m.end();
  if(normalPos<quotePos) processNormally(value.substring(normalPos, quotePos));
  final boolean tripleQuote=m.end()-m.start()>=6 && value.charAt(quotePos+1)=='\'';
  final int skip=tripleQuote? 3: 1;
  processQuoted(value.substring(quotePos+skip, quoteEnd-skip));
  normalPos=quoteEnd;
}
if(normalPos<length) processNormally(value.substring(normalPos));
于 2013-09-12T17:22:22.847 回答