web-dev-qa-db-ja.com

Ajax HTML応答でbodyタグを検索する

私はコンテンツをフェッチしてこのコンテンツを次のように追加するためにajax呼び出しを行っています:

$(function(){
    var site = $('input').val();
    $.get('file.php', { site:site }, function(data){
        mas = $(data).find('a');
        mas.map(function(elem, index) {
            divs = $(this).html();
            $('#result').append('' + divs + '');
        })
    }, 'html');
});

問題は、abodyを変更しても何も得られないことです(エラーはなく、htmlもありません)。ボディが「a」と同じようにタグであると想定していますか?何が悪いのですか?

これは私にとってはうまくいきます:

 mas = $(data).find('a');

しかし、これはしません:

 mas = $(data).find('body');
21
Youss

bodyタグを取得するためにjQueryオブジェクト(つまり$(data))を介して返されたHTMLを解析することは失敗する運命にあります、私は恐れています。

その理由は、返されたdatastringであるためです(console.log(typeof(data))を試してください)。 jQueryドキュメント によると、複雑なHTMLマークアップを含む文字列からjQueryオブジェクトを作成すると、bodyなどのタグが削除される可能性があります。これは、オブジェクトを作成するために、HTMLマークアップが実際にDOMに挿入され、そのような追加のタグを許可できないために発生します。

ドキュメント からの関連する引用:

文字列がパラメーターとして$()に渡されると、jQueryは文字列を調べて、HTMLのように見えるかどうかを確認します。

[...]上記の例のように、HTMLが属性のない単一のタグよりも複雑な場合、要素の実際の作成はブラウザのinnerHTMLメカニズムによって処理されます。ほとんどの場合、jQueryは新しい要素を作成し、要素のinnerHTMLプロパティを渡されたHTMLスニペットに設定します。パラメーターに単一のタグ(オプションの終了タグまたはクイック終了)がある場合— $( "<img/> ")または$(" <img> ")、$(" <a> </ a> ")または$(" <a> ")— jQueryは、ネイティブJavaScript createElement()関数を使用して要素を作成します。

複雑なHTMLを渡す場合、ブラウザによっては、提供されたHTMLソースを正確に複製するDOMを生成しない場合があります。前述のように、jQueryはブラウザの.innerHTMLプロパティを使用して、渡されたHTMLを解析し、現在のドキュメントに挿入します。このプロセス中に、一部のブラウザは、<html>、<title>、<head>要素などの特定の要素を除外しますその結果、挿入された要素は、渡された元の文字列を表していない可能性があります。

私はこの簡単な解決策に終わりました:

var body = data.substring(data.indexOf("<body>")+6,data.indexOf("</body>"));
$('body').html(body);

headまたはその他のtagでも機能します。

(xml解析を使用したソリューションはより優れていますが、無効なXML応答を使用する場合は、「文字列解析」を行う必要があります。)

11
Yush0

私は少し実験し、原因をある程度特定しましたので、私が興味を持つであろう本当の答えが出るまで、ここに問題を理解するのに役立つハックがあります

$.get('/',function(d){
    // replace the `HTML` tags with `NOTHTML` tags
    // and the `BODY` tags with `NOTBODY` tags
    d = d.replace(/(<\/?)html( .+?)?>/gi,'$1NOTHTML$2>',d)
    d = d.replace(/(<\/?)body( .+?)?>/gi,'$1NOTBODY$2>',d)
    // select the `notbody` tag and log for testing
    console.log($(d).find('notbody').html())
})

編集:さらなる実験

コンテンツをiframeにロードすると、domオブジェクト階層を介してフレームコンテンツにアクセスできる可能性があります...

// get a page using AJAX
$.get('/',function(d){

    // create a temporary `iframe`, make it hidden, and attach to the DOM
    var frame = $('<iframe id="frame" src="/" style="display: none;"></iframe>').appendTo('body')

    // check that the frame has loaded content
    $(frame).load(function(){

        // grab the HTML from the body, using the raw DOM node (frame[0])
        // and more specifically, it's `contentDocument` property
        var html = $('body',frame[0].contentDocument).html()

        // check the HTML
        console.log(html)

        // remove the temporary iframe
        $("#frame").remove()

    })
})

編集:より多くの研究

ContentDocumentはiFrameのwindow.document要素を取得するための標準に準拠した方法のようですが、もちろんIEは標準を気にしません。そのため、これはクロスプラットフォームの方法でiFrameのwindow.document.bodyオブジェクトへの参照を取得...

var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
var iframeBody = iframeDoc.body;
// or for extra caution, to support even more obsolete browsers
// var iframeBody = iframeDoc.getElementsByTagName("body")[0]

参照: iframeのcontentDocument

6
Billy Moon

私は素晴らしいものを見つけました(私は思います!)

HTMLを文字列として取得しましたか?

_var results = //probably an ajax response
_

以下は、現在DOMにアタッチされている要素とまったく同じように機能するjqueryオブジェクトです。

_var superConvenient = $($.parseXML(response)).children('html');
_

superConvenientから何も取り除かれません!あなたはsuperConvenient.find('body')のようなことをすることもできます

_superConvenient.find('head > script');
_

superConvenientは、誰もが慣れているjquery要素とまったく同じように動作します!!!!

注意

この場合、文字列resultsはJQueryのparseXMLメソッドに供給されるため、有効なXMLである必要があります。 HTML応答の一般的な機能は_<!DOCTYPE>_タグであり、この意味でドキュメントを無効にします。このアプローチを使用する前に、_<!DOCTYPE>_タグを削除する必要がある場合があります。また、_<!--[if IE 8]>...<![endif]-->_などの機能に注意してください。タグを閉じないでください。例:

_<ul>
    <li>content...
    <li>content...
    <li>content...
</ul>
_

...およびブラウザによって寛大に解釈されますが、XMLパーサーがクラッシュするHTMLのその他の機能。

5
Gershom

私のために働いた正規表現ソリューション:

var head = res.match(/<head.*?>.*?<\/head.*?>/s);
var body = res.match(/<body.*?>.*?<\/body.*?>/s);

詳細説明: https://regex101.com/r/kFkNeI/1

0
Noel Schenk