innerHTML将CDATA转换为注释

时间:2011-08-15 13:40:42

标签: javascript html dom cdata

我正在尝试使用javascript将一些HTML插入到页面中,而我插入的HTML包含CDATA块。

我发现,在Firefox和Chrome中,CDATA正在转换为评论。

HTML不在我的控制之下,因此我很难避免使用CDATA。

以下测试用例,当页面上有一个id为“test”的div:

document.getElementById('test').innerHTML = '<![CDATA[foo]]> bar'

导致以下HTML被添加到'test'div:

<!--[CDATA[foo]]--> bar

有什么方法可以使用javascript将包含CDATA的HTML逐字插入到文档中吗?

7 个答案:

答案 0 :(得分:3)

document.createCDATASection应该这样做,但问题的真正答案是,尽管HTML 5确实有CDATA sections跨浏览器支持,但它们非常不稳定。

修改

CDATA部分不在HTML 4定义中,因此大多数浏览器都无法识别它们。

但它不需要完整的DOM解析器。这是一个简单的词汇解决方案,可以解决问题。

function htmlWithCDATASectionsToHtmlWithout(html) {
    var ATTRS = "(?:[^>\"\']|\"[^\"]*\"|\'[^\']*\')*",
        // names of tags with RCDATA or CDATA content.
        SCRIPT = "[sS][cC][rR][iI][pP][tT]",
        STYLE = "[sS][tT][yY][lL][eE]",
        TEXTAREA = "[tT][eE][xX][tT][aA][rR][eE][aA]",
        TITLE = "[tT][iI][tT][lL][eE]",
        XMP = "[xX][mM][pP]",
        SPECIAL_TAG_NAME = [SCRIPT, STYLE, TEXTAREA, TITLE, XMP].join("|"),
        ANY = "[\\s\\S]*?",
        AMP = /&/g,
        LT = /</g,
        GT = />/g;
    return html.replace(new RegExp(
        // Entities and text
        "[^<]+" +
        // Comment
        "|<!--"+ANY+"-->" +
        // Regular tag
        "|<\/?(?!"+SPECIAL_TAG_NAME+")[a-zA-Z]"+ATTRS+">" +
        // Special tags
        "|<\/?"+SCRIPT  +"\\b"+ATTRS+">"+ANY+"<\/"+SCRIPT  +"\\s*>" +
        "|<\/?"+STYLE   +"\\b"+ATTRS+">"+ANY+"<\/"+STYLE   +"\\s*>" +
        "|<\/?"+TEXTAREA+"\\b"+ATTRS+">"+ANY+"<\/"+TEXTAREA+"\\s*>" +
        "|<\/?"+TITLE   +"\\b"+ATTRS+">"+ANY+"<\/"+TITLE   +"\\s*>" +
        "|<\/?"+XMP     +"\\b"+ATTRS+">"+ANY+"<\/"+XMP     +"\\s*>" +
        // CDATA section.  Content in capturing group 1.
        "|<!\\[CDATA\\[("+ANY+")\\]\\]>" +
        // A loose less-than
        "|<", "g"),

        function (token, cdataContent) {
          return "string" === typeof cdataContent
              ? cdataContent.replace(AMP, "&amp;").replace(LT, "&lt;")
                .replace(GT, "&gt;")
              : token === "<"
              ? "&lt;"  // Normalize loose less-thans.
              : token;
        });
}

鉴于

<b>foo</b><![CDATA[<i>bar</i>]]>

它产生

<b>foo</b>&lt;i&gt;bar&lt;/i&gt;

并且在script或其他特殊标记或注释中给出了类似于CDATA部分的内容,它正确地不会与它混淆:

<script>/*<![CDATA[*/foo=bar<baz&amp;//]]></script><![CDATA[fish: <><]]>

变为

<script>/*<![CDATA[*/foo=bar<baz&amp;//]]></script>fish: &lt;&gt;&lt;

答案 1 :(得分:2)

您可以尝试使用innerText代替innerHTML

答案 2 :(得分:2)

我只是使用正则表达式删除CDATA标记,如下所示:

document.getElementById('test').innerHTML = '<![CDATA[foo]]> bar'.replace(/<!\[CDATA\[(.*)\]\]>/g, "$1")

这导致'test'具有:

foo bar

这样就保留了CDATA部分的内容,而不必担心任何一部分被注释掉。不幸的是,这可能会破坏您的文档开始使用CDATA部分所需的任何内容。

答案 3 :(得分:1)

转换&lt;,&gt;和&amp;这样的迹象:

document.getElementById('test').innerHTML = '&lt;![CDATA[foo]]&gt bar'

答案 4 :(得分:1)

这是因为CDATA<>&lt;&gt;)转换为其html实体。尝试将实体转换回<>

您可以详细了解here

答案 5 :(得分:0)

如果你的页面是XHTML而不是HTML,那么自动评论&#34;功能&#34; CDATA可能不会发生。你需要跳过XHTML所需的箍,例如DOCTYPE,以及其他任何东西。

看起来有点武断,依赖于CDATA的任何应用程序都被破坏了恕我直言,但希望你能让它运转起来。

答案 6 :(得分:0)

我在2020年仍然遇到了这个问题:-(
与OP的细微差别是:我需要将 XML(不是html)插入div。
不幸的是,使用@Mike Samuel的答案将最初的<?xml ...转换为&lt;?xml ...
我只需要在正则表达式中添加以下子句:"|<\\?[xX][mM][lL]"+ANY+"\\?>"

针对xml的完整功能:

function xmlWithCDATASectionsToXmlWithout(xml) {
    var ATTRS = "(?:[^>\"\']|\"[^\"]*\"|\'[^\']*\')*",
        // names of tags with RCDATA or CDATA content.
        SCRIPT = "[sS][cC][rR][iI][pP][tT]",
        STYLE = "[sS][tT][yY][lL][eE]",
        TEXTAREA = "[tT][eE][xX][tT][aA][rR][eE][aA]",
        TITLE = "[tT][iI][tT][lL][eE]",
        XMP = "[xX][mM][pP]",
        SPECIAL_TAG_NAME = [SCRIPT, STYLE, TEXTAREA, TITLE, XMP].join("|"),
        ANY = "[\\s\\S]*?",
        AMP = /&/g,
        LT = /</g,
        GT = />/g;
    return xml.replace(new RegExp(
            // Entities and text
            "[^<]+" +
            // initial XML TAG
            "|<\\?[xX][mM][lL]"+ANY+"\\?>" +
            // Comment
            "|<!--"+ANY+"-->" +
            // Regular tag
            "|<\/?(?!"+SPECIAL_TAG_NAME+")[a-zA-Z]"+ATTRS+">" +
            // Special tags
            "|<\/?"+SCRIPT  +"\\b"+ATTRS+">"+ANY+"<\/"+SCRIPT  +"\\s*>" +
            "|<\/?"+STYLE   +"\\b"+ATTRS+">"+ANY+"<\/"+STYLE   +"\\s*>" +
            "|<\/?"+TEXTAREA+"\\b"+ATTRS+">"+ANY+"<\/"+TEXTAREA+"\\s*>" +
            "|<\/?"+TITLE   +"\\b"+ATTRS+">"+ANY+"<\/"+TITLE   +"\\s*>" +
            "|<\/?"+XMP     +"\\b"+ATTRS+">"+ANY+"<\/"+XMP     +"\\s*>" +
            // CDATA section.  Content in capturing group 1.
            "|<!\\[CDATA\\[("+ANY+")\\]\\]>" +
            // A loose less-than
            "|<", "g"
        ),
        function (token, cdataContent) {
            return "string" === typeof cdataContent
                    ? cdataContent.replace(AMP, "&amp;").replace(LT, "&lt;")
                        .replace(GT, "&gt;")
                    : token === "<"
                    ? "&lt;"  // Normalize loose less-thans.
                    : token;
        }
    );
}