Какова наилучшая практика для парсинга удаленного контента с помощью jQuery?
После вызова jQuery ajax для извлечения всего документа XHTML, каков наилучший способ выбора определенных элементов из результирующей строки? Возможно, есть библиотека или плагин, который решает эту проблему?
jQuery может выбирать только элементы XHTML, которые существуют в строке, если они обычно разрешены в div в спецификации W3C; поэтому мне интересно выбирать такие вещи, как
, и
.
Согласно документации jQuery:
- Предотrotation кэширования в ASP.NET MVC для определенных действий с использованием атрибута
- Задержка jquery hover event?
- Эффект jQuery .slideRight
- Проверьте, существует ли событие на элементе
- Клавиши захвата, введенные на виртуальную клавиатуру Android, используя javascript
http://docs.jquery.com/Core/jQuery#htmlownerDocument
Строка HTML не может содержать элементы, которые недействительны в div, например html, head, body или title.
Поэтому, поскольку мы установили, что jQuery не предоставляет способ сделать это, как бы я выбрал эти элементы? Например, если вы можете показать мне, как выбрать название удаленной страницы, это было бы прекрасно!
Спасибо, Пит
- jQuery text fade / переход из одного текста в другой?
- Выбор пустого ввода текста с помощью jQuery
- fancy box работает с iframes в функции beforeShow?
- Вызов функции jQuery после завершения .each ()
- Проверьте, воспроизводится ли видео YouTube и запускает скрипт
- Выделение селектора jQuery
- Проблема при получении текста в формате JSON, содержащем разрывы строк с помощью jQuery
- jQuery или CSS-селектор, чтобы выбрать все идентификаторы, начинающиеся с некоторой строки
Вместо того, чтобы взломать jQuery для этого, я бы посоветовал вам отказаться от jQuery в течение минуты и использовать raw XML-методы. Используя методы XML Dom, вы можете сделать это:
window.onload = function(){ $.ajax({ type: 'GET', url: 'text.html', dataType: 'html', success: function(data) { //cross platform xml object creation from w3schools try //Internet Explorer { xmlDoc=new ActiveXObject("Microsoft.XMLDOM"); xmlDoc.async="false"; xmlDoc.loadXML(data); } catch(e) { try // Firefox, Mozilla, Opera, etc. { parser=new DOMParser(); xmlDoc=parser.parseFromString(data,"text/xml"); } catch(e) { alert(e.message); return; } } alert(xmlDoc.getElementsByTagName("title")[0].childNodes[0].nodeValue); } }); }
Не вмешиваться в iframe и т. Д.
Просто идея, протестированная в FF / Safari, кажется, работает, если вы создаете iframe для временного хранения документа. Конечно, если вы это делаете, может быть разумнее использовать свойство src iframe для загрузки документа и делать все, что угодно, в «onload».
$(function() { $.ajax({ type: 'GET', url: 'result.html', dataType: 'html', success: function(data) { var $frame = $("").hide(); $frame.appendTo('body'); var doc = $frame.get(0).contentWindow.document; doc.write(data); var $title = $("title", doc); alert('Title: '+$title.text() ); $frame.remove(); } }); });
Я должен был добавить iframe к телу, чтобы получить его .contentWindow.
Вдохновленный от этого ответа , но с отсрочкой:
function fetchDoc(url) { var dfd; dfd = $.Deferred(); $.get(url).done(function (data, textStatus, jqXHR) { var $iframe = $('').appendTo('body'); var $doc = $iframe.contents(); var doc = $doc[0]; $iframe.load(function() { dfd.resolveWith(doc, [data, textStatus, jqXHR]); return $iframe.remove(); }); doc.open(); doc.write(data); return doc.close(); }).fail(dfd.reject); return dfd.promise(); };
И курите это с:
fetchDoc('/foo.html').done(function (data, textStatus, jqXHR) { alert($('title', this).text()); });
LIVE DEMO (нажмите «Запустить»)
Как насчет быстрого переименования тегов?
$.ajax({ type : "GET", url : 'results.html', dataType : "html", success: function(data) { data = data.replace(/html/g, "xhtmlx"); data = data.replace(/head/g, "xheadx"); data = data.replace(/title/g, "xtitlex"); data = data.replace(/body/g, "xbodyx"); alert($(data).find("xtitlex").text()); } });
Это работает. Я просто разделил строительные блоки для лучшей читаемости.
Проверьте объяснения и встроенные комментарии, чтобы понять, как это работает, и почему это нужно сделать так.
Разумеется, это невозможно использовать для получения междоменного контента, поскольку вам нужно либо проксировать вызовы с помощью вашего скрипта, либо думать о интеграции как flXHR (Cross-Domain Ajax с Flash)
call.html
asd
jquery.js (jQuery 1.3.2 несжатый) test.html действительный XHTML-документ
xmlDoc.js
// helper function to create XMLDocument out of a string jQuery.createXMLDocument = function( s ) { var xmlDoc; // is it a IE? if ( window.ActiveXObject ) { xmlDoc = new ActiveXObject('Microsoft.XMLDOM'); xmlDoc.async = "false"; // prevent erros as IE tries to resolve the URL in the DOCTYPE xmlDoc.resolveExternals = false; xmlDoc.validateOnParse = false; xmlDoc.loadXML(s); } else { // non IE. give me DOMParser // theoretically this else branch should never be called // but just in case. xmlDoc = ( new DOMParser() ).parseFromString( s, "text/xml" ); } return xmlDoc; };
output.js
// Output the title of the loaded page // And get the script-tags and output either the // src attribute or code function headerData(data) { // give me the head element var x = jQuery("head", data).eq(0); // output title alert(jQuery("title", x).eq(0).text()); // for all scripttags which include a file out put src jQuery("script[src]", x).each(function(index) { alert((index+1)+" "+jQuery.attr(this, 'src')); }); // for all scripttags which are inline javascript output code jQuery("script:not([src])", x).each(function(index) { alert(this.text); }); }
ready.js
$(document).ready(function() { $('#getit').click(function() { $.ajax({ type : "GET", url : 'test.html', dataType : "xml", // overwrite content-type returned by server to ensure // the response getst treated as xml beforeSend: function(xhr) { // IE doesn't support this so check before using if (xhr.overrideMimeType) { xhr.overrideMimeType('text/xml'); } }, success: function(data) { headerData(data); }, error : function(xhr, textStatus, errorThrown) { // if loading the response as xml failed try it manually // in theory this should only happen for IE // maybe some if (textStatus == 'parsererror') { var xmlDoc = jQuery.createXMLDocument(xhr.responseText); headerData(xmlDoc); } else { alert("Failed: " + textStatus + " " + errorThrown); } } }); }); });
В Opera все работает без createXMLDocument
и функции beforeSend
.
Дополнительный обман необходим для Firefox (3.0.11) и IE6 (не может тестировать IE7, IE8, другие браузеры), поскольку у них есть проблема, когда возвращаемый сервером Content-Type:
не указывает, что это xml. Мой веб-сервер возвратил Content-Type: text/html; charset=UTF-8
Content-Type: text/html; charset=UTF-8
для test.html.
В этих двух браузерах jQuery вызвал обратный вызов error
с помощью textStatus
говорит parsererror
. Потому что в строке 3706 в jQuery.js
data = xml ? xhr.responseXML : xhr.responseText;
data
устанавливаются равными нулю. Как и в FF и IE, xhr.responseXML
является нулевым. Это происходит потому, что они не получают, что возвращаемые данные являются xml (как Opera). И только xhr.responseText
устанавливается со всем xhtml-кодом. Поскольку данные являются нулевыми, строка 3708
if ( xml && data.documentElement.tagName == "parsererror" )
выбрасывает исключение, которое улавливается в строке 3584, а статус – parsererror
.
В FF я могу решить проблему, используя функцию overrideMimeType()
перед отправкой запроса.
Но IE не поддерживает эту функцию в объекте XMLHttpRequest, поэтому мне нужно сгенерировать сам XMLDocument, если выполняется обратный вызов ошибки, а ошибка – parsererror
.
пример для test.html
Plugins | jQuery Plugins
Бесстыдно скопировано и адаптировано из другого моего ответа ( простой пример jQuery ajax, не находящий элементов в возвращенном HTML ), это выбирает HTML удаленной страницы, тогда функция parseHTML создает для него временный элемент div и помещает лот внутри, проходит через он и возвращает запрошенный элемент. Затем jQuery оповещает текст () внутри.
$(document).ready(function(){ $('input').click(function(){ $.ajax({ type : "POST", url : 'ajaxtestload.html', dataType : "html", success: function(data) { alert( data ); // shows whole dom var gotcha = parseHTML(data, 'TITLE'); // nodeName property returns uppercase if (gotcha) { alert($(gotcha).html()); // returns null }else{ alert('Tag not found.'); } }, error : function() { alert("Sorry, The requested property could not be found."); } }); }); }); function parseHTML(html, tagName) { var root = document.createElement("div"); root.innerHTML = html; // Get all child nodes of root div var allChilds = root.childNodes; for (var i = 0; i < allChilds.length; i++) { if (allChilds[i].nodeName == tagName) { return allChilds[i]; } } return false; }
Чтобы получить несколько элементов или список тегов скриптов, скажем, я думаю, вам нужно будет улучшить функцию parseHTML, но эй-доказательство концепции 🙂
Если вы хотите найти значение специально названных полей (т. Е. Входы в форме), что-то вроде этого найдет их для вас:
var fields = ["firstname","surname", ...."foo"]; function findFields(form, fields) { var form = $(form); fields.forEach(function(field) { var val = form.find("[name="+field+"]").val(); ....
Как насчет этого: Загрузить XML из строки
$.get('yourpage.html',function(data){ var content = $('').append(data).find('#yourelement').html(); });
Вы также можете просто временно обернуть внутри div. Вам даже не нужно добавлять его в DOM.
После parsingа строки XML в XML DOM
я либо использовал бы jQuery
на нем напрямую (вы можете сделать это, предоставив контекст селектора jQUery
, например $(':title', xdoc.rootElement)
или используя XPath
( работает в Firefox, есть, предположительно, библиотеки для IE, но у меня не было хорошего успеха с ними).