[英]How to unescape HTML entities but leave XML entities untouched?
这是输入:
<div>The price is < 5 €</div>
它是有效的 HTML,但不是有效的 XML(因为€
未在 DTD 中声明)。 有效的 XML 如下所示:
<div>The price is < 5 €</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. " & ä
* @return XML String, HTML4 Entities replaced, but XML Entites remain (e.g. " und &)
*/
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< alert(x);</script>
包含一个脚本元素,其内容未使用实体进行编码,因此天真地替换<
这里会破坏脚本。 还有其他元素,如<xmp>
和<style>
,它们可能有与外部 XML 元素中的 CDATA 部分类似的问题。
如果您需要真正忠实的转换,或者您的 HTML 很乱,最好的办法可能是使用nu.validator 之类的东西将 HTML 解析为 DOM,然后使用如何从 Java 漂亮地打印 XML? 将 DOM 转换为有效的 XML。
即使您的输入是 XHTML,您也可能需要担心在 CDATA 部分中看起来像实体的字符序列。 同样,解析和重新渲染可能是您的最佳选择。
Apache公用StringUtils.unescapeHTML会这样做。 XML API通常会自己转义XML实体。 因此,您可以使用&
设置DOM属性或内容文本,并且生成的是&
。 您可以将字符保留在UTF-8中; 无需使它们成为数字实体。
当然,您也可以处理HTML DTD。 这也将填写字符。 这可能需要数十秒钟。 不幸的是,实体非常多,DTD包含且服务器运行缓慢,因此最好使用这些DTD制作本地XML目录或缓存实体处理程序。
import org.apache.commons.lang.StringEscapeUtils;
String html = "<div>The price is < 5 €</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.