innerHTML преобразует CDATA в комментарии - PullRequest
4 голосов
/ 15 августа 2011

Я пытаюсь вставить HTML-код на страницу, используя JavaScript, а вставляемый HTML-код содержит блоки CDATA.

В Firefox и Chrome я обнаружил, что CDATA преобразуется в комментарий.

HTML не находится под моим контролем, поэтому мне трудно избежать использования CDATA.

Следующий тестовый случай, когда на странице есть div с идентификатором «test»:

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

вызывает добавление следующего HTML-кода в div 'test':

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

Можно ли как-нибудь вставить, дословно, HTML, содержащий CDATA, в документ с использованием javascript?

Ответы [ 6 ]

3 голосов
/ 15 августа 2011

document.createCDATASection должен сделать это, но реальный ответ на ваш вопрос заключается в том, что хотя HTML 5 имеет секции CDATA кросс-браузерная поддержка для них довольно нечеткая.

EDIT

Разделы 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;

и что-то, похожее на раздел CDATA внутри script или другого специального тега или комментария, корректно не смешивается с ним:

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

становится

<script>/*<![CDATA[*/foo=bar<baz&amp;//]]></script>fish: &lt;&gt;&lt;
2 голосов
/ 15 августа 2011

Я бы просто удалил теги CDATA, используя регулярное выражение, например, так:

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

В результате 'test' будет иметь:

foo bar

Таким образом, содержимое CDATAразделы сохраняются без необходимости беспокоиться о комментировании.К сожалению, это может нарушить все, что требовалось вашим документам для использования разделов CDATA.

2 голосов
/ 15 августа 2011

Вы можете попробовать использовать innerText вместо innerHTML.

1 голос
/ 15 августа 2011

Это потому, что CDATA преобразует < и > (&lt; и &gt;) в их HTML-сущности. Попробуйте преобразовать сущности обратно в < и >.

Подробнее об этом можно прочитать здесь .

1 голос
/ 15 августа 2011

преобразовать <,> и знаки & как это:

document.getElementById('test').innerHTML = '&lt;![CDATA[foo]]&gt bar'
0 голосов
/ 12 октября 2015

Если вы сделаете свою страницу XHTML, а не HTML, то "функция" автоматического комментирования CDATA может не произойти. Вам нужно перепрыгнуть через обручи, которые требует XHTML, такие как DOCTYPE и все остальное.

Кажется немного произвольным, любое приложение, которое зависит от CDATA, сломано ИМХО, но, надеюсь, у вас все получится.

...