Как я могу получить HTML, содержащийся в теге тела iframe, без замены символов? - PullRequest
0 голосов
/ 01 сентября 2011

В настоящее время я пытаюсь получить содержимое тела iframe без искажения содержимого браузером.

Я мог бы сделать это, включив содержимое в текстовую область, однако я хочу этого избежать.

использование .innerHTML приводит к специальным символам, таким как < > и &преобразуется в &lt;, &gt; и &amp; соответственно.

Для тестирования создайте HTML-файл, содержащий:

{ 
 "id": 5, 
 "testtext":"I am > than this & < that", 
 "html":"<div>\"worky\"</div>" 
}

, а затем другую страницу, которая включает этот файл вiframe:

<!doctype html>
<html>
  <head>
    <script src="http://code.jquery.com/jquery-latest.js"></script>
  </head>
  <body>
    <iframe id="myIframe" name="myIframe" src="test.html"></iframe><br />
    Result:<br />
    <textarea id='result'></textarea>
    <script>
      $("#myIframe").load(function(){
        var iframeBody = window.frames.myIframe.document
            .getElementsByTagName("body")[0], result;
        result = iframeBody.innerHTML;
        $("#result").val(result);
      });
    </script>
  </body>
</html>

Я пробовал это:

result = $(iframeBody).contents().map(function(){
      return this.nodeValue ? this.nodeValue : this.innerHTML;
}).get().join("");

однако он теряет div.

РЕДАКТИРОВАТЬ:

У меня есть какое-то решение,

var iframeBody, result;
$("#myIframe").load(function(){
  iframeBody = window.frames.myIframe.document
    .getElementsByTagName("body")[0];
  result = $(iframeBody).contents().map(function(){
    if (this.nodeValue) {
        return this.nodeValue   
    }
    else {
        return $(this).clone().wrap('<p>').parent().html();
    }
  }).get().join("");
  $("#result").val(result);
});

Однако оно по-прежнему будет кодировать вещи в html, которые не являются html.Я не уверен, если я в порядке с этим.

ИЗМЕНИТЬ СНОВА

Вот немного больше контекста.Я изменяю транспорт jjery iframe ajax для работы, не требуя textarea в iframe для хранения контента, когда контент не является HTML.По большей части он работает нормально без текстовой области, однако в конечном итоге искажает любые специальные символы HTML, когда вы извлекаете этот текст с использованием .innerHTML.Один из способов избежать искажения - получить текст с помощью .nodeValue, однако это не сработает, когда вы натолкнетесь на элемент html.Если по какой-либо причине вы возвращаете json, который содержит строку html, он должен иметь возможность извлекать эту строку json точно так, как она была возвращена в iframe, что означает, что все символы остаются без изменений.

Для целейтестирование, это jsfiddle достаточно теста.Представьте, что div, используемый в скрипте, является телом iframe, и вы можете проверить результаты в jsfiddle.Проблема, которая у меня есть, на самом деле не имеет ничего общего с iframe или событием загрузки.

http://jsfiddle.net/P623a/2/

В этой скрипке единственной проблемой является & преобразование в & изнутриdiv внутри json.

Решение

Я просто потребую, чтобы страница была правильно закодирована (application / json, script или plain / text)если ответ является json / jsonp / script и содержит элемент dom.Если при этих условиях он не закодирован должным образом, запускается обработчик ошибок.

При правильном кодировании iframe в конечном итоге будет иметь тег body, содержащий your content, который можно получить с помощью .innerText при сохранении специальных символов.

Ответы [ 5 ]

5 голосов
/ 06 сентября 2011

Браузер интерпретирует данные в iframe как HTML, и, насколько мне известно, не дает способа получить исходный текст (в виде исходного кода).

Вот варианты, которые я могу придумать:

  • Сделайте ответ верным HTML - оберните его в документ и закодируйте нужные данные, примерно так:

    <!DOCTYPE html>
    <html>
    <head>
    <body>
    { 
     "id": 5, 
     "testtext":"I am &gt; than this &amp; &lt; that", 
     "html":"&lt;div&gt;\"worky\"&lt;/div&gt;" 
    }
    
  • Отправьте свой ответ с типом MIME, который не интерпретируется как HTML, например application/json или text/plain. Браузер, вероятно, создаст вокруг него документ (поместив данные, скажем, в pre), и вы можете получить его таким же образом.

В любом случае вы можете получить innerText (или textContent, в зависимости от браузера) документа или nodeValue текстового узла, содержащего ваши данные, например:

var iframeBody = iframe.contentDocument.body,
    json = iframeBody.textContent || iframeBody.innerText;
1 голос
/ 06 сентября 2011

Я думаю, что вы должны сначала попробовать действительный html, если вы планируете использовать nodeValue или иначе, вы не можете просто предположить, что браузер добавит тело для вас, это совсем не html:

{ 
 "id": 5, 
 "testtext":"I am > than this & < that", 
 "html":"<div>\"worky\"</div>" 
}

Странно пытаться разобрать дом, который не HTML!Дело в том, что если вы хотите получить какой-либо шанс манипулировать или перемещаться с помощью jQuery, вы должны, по крайней мере, обернуть все вещи в один большой контейнер, например:

<div>
// even if you don't want use body or html tag, things must be wrapped here
</div>

Я думаю, что существует проблема неправильного понимания того, что и каквы пытаетесь удовлетворить ваши потребности, не должно быть проще загрузить какой-нибудь json (как вы написали) ?!вы пытаетесь бросить куб ... если вы все равно не хотите анализировать свои чистые данные, вы можете проверить что-то вроде этого:

<p>
<p>id<span>5</span></p>
<p>testtext<span>I "am" > than this & < that</span></p>
</p>

Конечно, вы просто не можете вставить html какпростой текст, потому что, как браузер должен знать, что делать?Просто сделайте простой тест:

var div = $('<div/>').appendTo('body').html('I "am" > than this & < that');
console.log('plainText :', div.text(), ', html :', div.html());
// works as expected...
1 голос
/ 04 сентября 2011

Вы устанавливаете обработчик события загрузки iframe после тега iframe, у которого уже есть источник.Поэтому вполне возможно, что iframe загружается до того, как присоединится обработчик события load.Я не говорю, что это проблема, но это создаст проблему, если iframe загружается быстро.Вы можете предоставить встроенный обработчик событий загрузки в самом теге iframe.

Попробуйте это

<!doctype html>
<html>
  <head>
    <script src="http://code.jquery.com/jquery-latest.js"></script>
    <script type="text/javascript">
    function copyIframeContent(iframe){
        var iframeContent = $(iframe).contents();
        $("#result").html(iframeContent.find('body').html());
    }
    </script>
  </head>
  <body>
    <iframe id="myIframe" onload="copyIframeContent(this);" name="myIframe" src="test.html"></iframe><br />
    Result:<br />
    <textarea id='result'></textarea>
  </body>
</html>

Надеюсь, это вам поможет.

1 голос
/ 01 сентября 2011

Код, который вы имеете в test1.html, не имеет "тела", вы не можете .getElementsByTagName("body"), если его нет.Попробуйте:

$("#myIframe").load(function(){
    $("#result").val($(this).contents().text());
});
0 голосов
/ 04 сентября 2011

Можете ли вы url-кодировать строку JSON, прежде чем передать ее в iframe?Например ... если вы измените html-строку: "<div>\"worky\"</div>" на "&lt;div>\"worky\"&lt;/div>", она будет отображать div html.Элементы div записываются в dom при загрузке iframe, поэтому вам нужно предотвратить его синтаксический анализ элементов html в вашей строке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...