【问题标题】:Stripping HTML tags in Java [duplicate]在Java中剥离HTML标签[重复]
【发布时间】:2010-10-24 08:59:30
【问题描述】:

是否有现有的 Java 库提供从字符串中去除所有 HTML 标记的方法?我正在寻找与 PHP 中的 strip_tags 函数等效的东西。

我知道我可以使用this Stackoverflow question 中描述的正则表达式,但是我很好奇是否已经有一个 stripTags() 方法可以在 Apache Commons 库中的某个地方使用。

【问题讨论】:

  • 与此同时,我正在使用以下代码从字符串中删除所有 HTML 标记: String strippedHtml = rawHtml.replaceAll("", "");

标签: java html


【解决方案1】:

使用JSoup,它有很好的文档记录,可以在 Maven 上使用,并且在花了一天时间使用几个库之后,对我来说,这是我能想象到的最好的一个。我自己的意见是,这样的工作,将 html 解析为纯文本,应该可以在一行代码中 - >否则库以某种方式失败......只是说 ^^ 所以这就是 JSoup 的单行 - 在 Markdown4J 中,类似的东西不是有可能,在 Markdownj 中也是如此,在 htmlCleaner 中,大约 50 行代码真是让人头疼……

String plain = new HtmlToPlainText().getPlainText(Jsoup.parse(html));

你得到的是真正的纯文本(不仅仅是作为字符串的 html 源代码,就像在其他库中一样)-> 他在这方面做得很好。它的质量与 PHP 的 Markdownify 或多或少相同......

【讨论】:

  • Jsoup 的问题在于它还会删除新行,因此所有解析的输入都将在一行上。
  • 如果输入包含“%gt;tag<”,结果可以包含HTML标签或类似的。
  • 好的 Jules 但是这不是 JSoup 的问题..其他人在这方面更好吗?没关系,因为在将他提供给 JSoup 之前简单地解码 url 编码的 html 字符串对我来说感觉更好,而不是编写几行代码来实现 JSoup 的功能(如果这里的另一个库会更好的话)特别的东西)
  • @johnflan 不仅将换行符转换为空格,还将某些空格转换为换行符!尚未查看源代码,但如果您有一个由单个空格组成的TextNode,这似乎会发生。我不知道这背后的逻辑,但正如 HtmlToPlainText 的 Javadoc 中所说,“请注意,这是一个相当简单的格式化程序——对于现实世界的使用,你会想要接受和扩展。”
  • 可能HtmlToPlainText 来自旧版本。现在只是Jsoup.parse(html).text()
【解决方案2】:

这是我在谷歌上找到的。 对我来说效果很好。

String noHTMLString = htmlString.replaceAll("\\<.*?\\>", "");

【讨论】:

  • 这不会删除像 这样的非 html 标签吗?
  • 我不相信像这样的简短正则表达式 可以 涵盖所有 html 情况......特殊格式是什么?像 JSoup 这样的优秀库在生成纯文本(!)时甚至会关心格式......我的意思是,转换,你永远不会只使用正则表达式来实现这一点
  • 我建议添加 < >标签也是。字符串 noHTMLString = htmlString.replaceAll("(\\<.>|<.*?>)", "");顺便说一句,它删除了像 这样的非 html 标签
  • 并且,作为警告,您应该始终牢记 Stack Overflow 上最具传奇色彩的答案之一:stackoverflow.com/a/1732454/256788
【解决方案3】:

无论您做什么,请确保在开始尝试剥离标签之前对数据进行规范化。我最近参加了一个涵盖 XSS 过滤器规避的 Web 应用安全研讨会。人们通常会认为搜索&amp;lt;&amp;lt; 或其十六进制等效项就足够了。在看到一张幻灯片后,我被震撼了,其中包含 70 种 &amp;lt; 可以被编码以击败过滤器的方式。

更新:

下面是我提到的演示文稿,请参阅幻灯片 26 了解编码 &amp;lt; 的 70 种方法。

Filter Evasion: Houdini on the Wire

【讨论】:

  • 能否请您添加该幻灯片的链接?我相信没有多少编码方法对浏览器有效...
  • 如果我错了,请纠正我,但这个列表中的第一项不是浏览器实际解释为开始 HTML 标记的唯一一项吗?其余的要么按原样显示,要么在结果文档中显示为文字“
【解决方案4】:

可能有一些,但最强大的是使用实际的 HTML 解析器。有一个here,如果格式合理,您还可以使用 SAX 或其他 XML 解析器。

【讨论】:

  • 当然,如果你最终想要得到的是一个可以保证安全地包含在 HTML 输出中的字符串,那么 HTML 解析器不是你想要的,否则字符串 '&lt ;脚本>警报(“你好”);'将通过解析器并最终变得危险,即使它不是从...开始的......
  • 也许如果你能停止居高临下,它会更有用。我对 HTML 解析器非常熟悉,并且在过去 20 年中使用过很多。通常,HTML 解析器的输出将是一个 DOM 或类似的东西,但问题显然要求一个字符串,所以我假设您的建议是使用生成的解析 DOM 的 W3C DOM 属性textContent,或者如果使用输出不是 DOM 的解析器,则某些等价物。如果这是您推荐的,这是危险的,因为如果 HTML 内容在源文档中编码为实体,它将允许通过。
  • 也许吧。也许不是。但是,如果您对“解析器”的概念不清楚,我不会打赌。
  • @Jules, '<script>alert("hello");'将通过解析器并作为文本节点从另一端出来,文本内容为'
【解决方案5】:

在提出这个问题将近一周后,我可以肯定地说,Java API 或 Apache 库中没有可用的方法从字符串中去除 HTML 标记。您要么必须使用前面答案中描述的 HTML 解析器,要么编写一个简单的正则表达式来去除标签。

【讨论】:

  • 嗯,如果不是 HTML 解析器,您认为会做这样的事情吗?或者,就此而言,您认为您正在使用正则表达式做什么?
  • 我想他对正则表达式所做的事情与我对正则表达式所做的事情相同:从字符串中删除任何看起来好像是 HTML 标记的内容,以确保生成的字符串 (1) 是人类可读的,并且 (2) 如果嵌入网页中不会导致 XSS 漏洞。
【解决方案6】:

当使用 Jsoup 时,它甚至比上述答案中描述的更容易:

String html = "bla <b>hehe</b> <br> this is awesome simple";

String text = Jsoup.parse(html).text();

【讨论】:

  • 这对我有用,似乎与 Jsoup 将空格转换为换行符(TextNode 仅包含空格)或换行符转换为空格(正常的 Jsoup 行为)无关,这似乎是new HtmlToPlainText().getPlainText( Jsoup.parse( htmlHitLine ));的问题
  • 很高兴听到这个消息:))
【解决方案7】:

我使用nekoHtml 来做到这一点。它可以去除所有标签,但也可以轻松保留或去除标签子集。

【讨论】:

    【解决方案8】:

    我知道这个问题很老了,但是我也一直在找这个问题,似乎在java中找到一个好的简单的解决方案仍然不容易。

    今天我遇到了这个小函数库。它实际上是在试图模仿php的strip_tags函数。

    http://jmelo.lyncode.com/java-strip_tags-php-function/

    它的工作原理是这样的(从他们的网站复制):

        import static com.lyncode.jtwig.functions.util.HtmlUtils.stripTags;
    
        public class StripTagsExample {
          public static void main(String... args) {
            String result = stripTags("<!-- <a href='test'></a>--><a>Test</a>", "");
            // Produced result: Test
          }
        }
    

    【讨论】:

      【解决方案9】:

      您好,我知道这个帖子很旧,但它仍然在 Google 上名列前茅,我正在寻找解决相同问题的快速方法。找不到任何有用的东西,所以我想出了这个代码 sn-p - 希望它对某人有所帮助。它只是循环字符串并跳过所有标签。简单明了。

      boolean intag = false;
      String inp = "<H1>Some <b>HTML</b> <span style=blablabla>text</span>";
      String outp = "";
      
      for (int i=0; i < inp.length(); ++i)
      {
          if (!intag && inp.charAt(i) == '<')
              {
                  intag = true;
                  continue;
              }
              if (intag && inp.charAt(i) == '>')
              {
                  intag = false;
                  continue;
              }
              if (!intag)
              {
                  outp = outp + inp.charAt(i);
              }
      }   
      return outp;
      

      【讨论】:

      • 您可以考虑使用 StringBuilder 作为输出。您将如何处理格式错误的 HTML?如果我的 HTML 包含未转义的小于或大于字符怎么办?
      【解决方案10】:

      采用纯迭代方法,没有正则表达式:

      public String stripTags(final String html) {
      
          final StringBuilder sbText = new StringBuilder(1000);
          final StringBuilder sbHtml = new StringBuilder(1000);
      
          boolean isText = true;
      
          for (char ch : html.toCharArray()) {
              if (isText) { // outside html
                  if (ch != '<') {
                      sbText.append(ch);
                      continue;
                  } else {   // switch mode             
                      isText = false;      
                      sbHtml.append(ch); 
                      continue;
                  }
              }else { // inside html
                  if (ch != '>') {
                      sbHtml.append(ch);
                      continue;
                  } else {      // switch mode    
                      isText = true;     
                      sbHtml.append(ch); 
                      continue;
                  }
              }
          }
      
          return sbText.toString();
      }
      

      【讨论】:

        【解决方案11】:

        由于html片段的缩写(字符串截断),我也遇到了正则表达式无法检测到的未闭合html标签的问题。 例如:

        Lorem ipsum dolor sit amet, <b>consectetur</b> adipiscing elit. <a href="abc"
        

        所以,参考 2 个最佳答案(JSoup 和正则表达式),我更喜欢使用 JSoup 的解决方案:

        Jsoup.parse(html).text()
        

        【讨论】:

          【解决方案12】:

          Wicket 使用以下方法转义 html,位于:org.apache.wicket.util.string.Strings

          public static CharSequence escapeMarkup(final String s, final boolean escapeSpaces,
              final boolean convertToHtmlUnicodeEscapes)
          {
              if (s == null)
              {
                  return null;
              }
              else
              {
                  int len = s.length();
                  final AppendingStringBuffer buffer = new AppendingStringBuffer((int)(len * 1.1));
          
                  for (int i = 0; i < len; i++)
                  {
                      final char c = s.charAt(i);
          
                      switch (c)
                      {
                          case '\t' :
                              if (escapeSpaces)
                              {
                                  // Assumption is four space tabs (sorry, but that's
                                  // just how it is!)
                                  buffer.append("&nbsp;&nbsp;&nbsp;&nbsp;");
                              }
                              else
                              {
                                  buffer.append(c);
                              }
                              break;
          
                          case ' ' :
                              if (escapeSpaces)
                              {
                                  buffer.append("&nbsp;");
                              }
                              else
                              {
                                  buffer.append(c);
                              }
                              break;
          
                          case '<' :
                              buffer.append("&lt;");
                              break;
          
                          case '>' :
                              buffer.append("&gt;");
                              break;
          
                          case '&' :
          
                              buffer.append("&amp;");
                              break;
          
                          case '"' :
                              buffer.append("&quot;");
                              break;
          
                          case '\'' :
                              buffer.append("&#039;");
                              break;
          
                          default :
          
                              if (convertToHtmlUnicodeEscapes)
                              {
                                  int ci = 0xffff & c;
                                  if (ci < 160)
                                  {
                                      // nothing special only 7 Bit
                                      buffer.append(c);
                                  }
                                  else
                                  {
                                      // Not 7 Bit use the unicode system
                                      buffer.append("&#");
                                      buffer.append(new Integer(ci).toString());
                                      buffer.append(';');
                                  }
                              }
                              else
                              {
                                  buffer.append(c);
                              }
          
                              break;
                      }
                  }
          
                  return buffer;
              }
          }
          

          【讨论】:

          • 这是转义,不是剥离
          • 没错,这两者是有区别的!
          【解决方案13】:
          public static String stripTags(String str) {
              int startPosition = str.indexOf('<');
              int endPosition;
              while (startPosition != -1) {
                  endPosition = str.indexOf('>', startPosition);
                  str = str.substring(0, startPosition) + (endPosition != -1 ? str.substring(endPosition + 1) : "");
                  startPosition = str.indexOf('<');
              }
              return str;
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-07-11
            • 1970-01-01
            • 2014-06-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-08-03
            • 1970-01-01
            相关资源
            最近更新 更多