繁体   English   中英

如何取消转义 HTML 实体但不影响 XML 实体?

[英]How to unescape HTML entities but leave XML entities untouched?

这是输入:

<div>The price is &lt; 5 &euro;</div>

它是有效的 HTML,但不是有效的 XML(因为&euro;未在 DTD 中声明)。 有效的 XML 如下所示:

<div>The price is &lt; 5 &#8364;</div>

你能推荐一些可以帮助我转义 HTML 实体并将它们转换为 XML 实体的 Java 库吗?

使用 apache commons lang 3,一个只替换 HTML 特定实体的类:

import org.apache.commons.text.translate.AggregateTranslator;
import org.apache.commons.text.translate.CharSequenceTranslator;
import org.apache.commons.text.translate.EntityArrays;
import org.apache.commons.text.translate.LookupTranslator;
import org.apache.commons.text.translate.NumericEntityUnescaper;


public class HtmlEscapeUtils {

  /**
   * @see {@link org.apache.commons.text.StringEscapeUtils#UNESCAPE_HTML4}
   */
  public static final CharSequenceTranslator UNESCAPE_HTML_SPECIFIC =
      new AggregateTranslator(
          new LookupTranslator(EntityArrays.ISO8859_1_UNESCAPE),
          new LookupTranslator(EntityArrays.HTML40_EXTENDED_UNESCAPE),
          new NumericEntityUnescaper());


  /**
   * @see {@link org.apache.commons.text.StringEscapeUtils#unescapeHtml4(String)}
   * @param input - HTML String with e.g. &quot; &amp; &auml;
   * @return XML String, HTML4 Entities replaced, but XML Entites remain (e.g. &quot; und &amp;)
   */
  public static final String unescapeHtmlToXml(final String input) {
    return UNESCAPE_HTML_SPECIFIC.translate(input);
  }

}

所有 HTML 命名字符引用的列表可在http://www.whatwg.org/specs/web-apps/current-work/multipage/entities.json 获得

如果您可以容忍偶尔出现的错误,您可以查看该文件并将独立 XML 中不允许的所有命名字符引用替换为相应的数字字符引用。

如果您的输入是 HTML 而不是 XHTML,那么这种简单的方法可能会遇到问题:

<script>var y=1, lt = 3, x = y&lt; alert(x);</script>

包含一个脚本元素,其内容未使用实体进行编码,因此天真地替换&lt; 这里会破坏脚本。 还有其他元素,如<xmp><style> ,它们可能有与外部 XML 元素中的 CDATA 部分类似的问题。

如果您需要真正忠实的转换,或者您的 HTML 很乱,最好的办法可能是使用nu.validator 之类的东西将 HTML 解析为 DOM,然后使用如何从 Java 漂亮地打印 XML? 将 DOM 转换为有效的 XML。

即使您的输入是 XHTML,您也可能需要担心在 CDATA 部分中看起来像实体的字符序列。 同样,解析和重新渲染可能是您的最佳选择。

Apache公用StringUtils.unescapeHTML会这样做。 XML API通常会自己转义XML实体。 因此,您可以使用&设置DOM属性或内容文本,并且生成的是&amp; 您可以将字符保留在UTF-8中; 无需使它们成为数字实体。

当然,您也可以处理HTML DTD。 这也将填写字符。 这可能需要数十秒钟。 不幸的是,实体非常多,DTD包含且服务器运行缓慢,因此最好使用这些DTD制作本地XML目录或缓存实体处理程序。

import org.apache.commons.lang.StringEscapeUtils;

    String html = "<div>The price is &lt; 5 &euro;</div>";
    String text = StringEscapeUtils.unescapeHtml(html);
    System.out.println("Text: " + text);

在UTF-8 Linux中的输出:

Text: <div>The price is < 5 €</div>

这表明属性值和内部文本应分段处理。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM