我正在尝试使用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逐字插入到文档中吗?
答案 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, "&").replace(LT, "<")
.replace(GT, ">")
: token === "<"
? "<" // Normalize loose less-thans.
: token;
});
}
鉴于
<b>foo</b><![CDATA[<i>bar</i>]]>
它产生
<b>foo</b><i>bar</i>
并且在script
或其他特殊标记或注释中给出了类似于CDATA部分的内容,它正确地不会与它混淆:
<script>/*<![CDATA[*/foo=bar<baz&//]]></script><![CDATA[fish: <><]]>
变为
<script>/*<![CDATA[*/foo=bar<baz&//]]></script>fish: <><
答案 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 = '<![CDATA[foo]]> bar'
答案 4 :(得分:1)
这是因为CDATA
将<
和>
(<
和>
)转换为其html实体。尝试将实体转换回<
和>
。
您可以详细了解here。
答案 5 :(得分:0)
如果你的页面是XHTML而不是HTML,那么自动评论&#34;功能&#34; CDATA可能不会发生。你需要跳过XHTML所需的箍,例如DOCTYPE,以及其他任何东西。
看起来有点武断,依赖于CDATA的任何应用程序都被破坏了恕我直言,但希望你能让它运转起来。
答案 6 :(得分:0)
我在2020年仍然遇到了这个问题:-(
与OP的细微差别是:我需要将 XML(不是html)插入div。
不幸的是,使用@Mike Samuel的答案将最初的<?xml ...
转换为<?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, "&").replace(LT, "<")
.replace(GT, ">")
: token === "<"
? "<" // Normalize loose less-thans.
: token;
}
);
}