簡體   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