Разбор строки html с использованием jquery
Я пытаюсь разобрать этот html через jQuery, чтобы получить data1, data2, data3. Пока я получаю data2 и data3, я не могу получить data3 с моим подходом. Я новичок в jQuery, поэтому, пожалуйста, простите мое невежество.
<html>
<body>
<div class="class0">
<h4>data1</h4>
<p class="class1">data2</p>
<div id="mydivid"><p>data3</p></div>
</div>
</body>
</html>
Вот как я называю это в своем jquery.
var datahtml = "<html><body><div class=\"class0\"><h4>data1</h4><p class=\"class1\">data2</p><div id=\"mydivid\"><p>data3</p></div></div></body></html>";
alert($(datahtml).find(".class0").text()); // Doesn't Work
alert($(datahtml).find(".class1").text()); // work
alert($(datahtml).find("#mydivid").text()); // work
Только alert($(datahtml).find(".class0").text());
не работает, остальные работают как ожидалось. Мне интересно, может быть, потому, что class0 имеет несколько тегов внутри него или что? Как получить данные1 в таком сценарии?
Ответы
Ответ 1
Его поведение является странным, поскольку оно igonores тега html и body и начинается с первого div с классом = "class0". Html анализируется как элементы DOM, но не добавляется в DOM. Для элементов, добавленных в DOM, селектор не игнорирует тег тела и применяет селектора в документе. Вам нужно добавить html в DOM, как показано ниже.
Живая демонстрация
$('#div1').append($(datahtml)); //Add in DOM before applying jquery methods.
alert($('#div1').find(".class0").text()); // Now it Works too
alert($('#div1').find(".class1").text()); // work
alert($('#div1').find("#mydivid").text()); // work
Если мы обернем ваш html в некоторый элемент html, чтобы сделать его отправной точкой вместо вашего первого div с class= "class0", тогда ваш селектор будет работать как ожидалось.
Живая демонстрация
var datahtml = "<html><body><div><div class=\"class0\"><h4>data1</h4><p class=\"class1\">data2</p><div id=\"mydivid\"><p>data3</p></div></div></div></body></html>";
alert($(datahtml).find(".class0").text()); // Now it Works too
alert($(datahtml).find(".class1").text()); // work
alert($(datahtml).find("#mydivid").text()); // work
Что jQuery сообщает о функции разбора jQuery jQuery() i.e. $()
При передаче сложного HTML некоторые браузеры не могут генерировать DOM что точно реплицирует предоставленный HTML-источник. Как уже упоминалось, jQuery использует свойство .innerHTML браузера для анализа прошедших HTML и вставьте его в текущий документ. Во время этого процесса некоторые браузеры отфильтровывают определенные элементы, такие как <html>
, <title>
или <head>
элементов. В результате вставленные элементы могут не быть представитель исходной строки.
Ответ 2
Ни один из текущих ответов не затронул реальную проблему, поэтому я отдам ей это.
var datahtml = "<html><body><div class=\"class0\"><h4>data1</h4><p class=\"class1\">data2</p><div id=\"mydivid\"><p>data3</p></div></div></body></html>";
console.log($(datahtml));
$(datahtml)
- объект jQuery, содержащий только элемент div.class0
, поэтому, когда вы вызываете .find
на нем, вы фактически ищете потомков div.class0
вместо всего HTML-документа, который вы ожидаете.
Быстрое решение состоит в том, чтобы обернуть анализируемые данные в элементе, чтобы .find
работал по назначению:
var parsed = $('<div/>').append(datahtml);
console.log(parsed.find(".class0").text());
Fiddle
Причина этого не очень проста, но я предполагаю, что поскольку jQuery выполняет "синтаксический анализ" более сложных строк html, просто отбрасывая вашу HTML-строку в отдельный созданный на месте фрагмент DOM, а затем извлекает анализируемые элементы, эта операция, скорее всего, заставит DOM-парсер игнорировать теги html
и body
, поскольку в этом случае они были бы незаконными.
Вот очень маленький набор тестов, который демонстрирует, что это поведение согласовано с помощью jQuery 1.8.2 вплоть до 1.6.4.
Изменить:, цитируя этот пост:
Проблема в том, что jQuery создает DIV и устанавливает innerHTML
, а затем принимает DIV, но поскольку элементы BODY и HEAD недействительны DIV childs, то они не создаются браузером.
Я уверен, что моя теория верна. Я расскажу об этом здесь, надеюсь, это будет иметь для вас смысл. Имейте jQuery 1.8.2 несжатый источник рядом с этим. #
указывает номера строк.
Все фрагменты документа, сделанные с помощью jQuery.buildFragment
(определенные @# 6122), пройдут через jQuery.clean
(# 6151) (даже если это кешированный фрагмент, он уже прошел через jQuery.clean
, когда он был создан), и, как следует из приведенного выше цитированного текста, jQuery.clean
(определенный @# 6275) создает свежий div
внутри безопасного фрагмента, который служит контейнером для проанализированных данных - div
, созданный на # 6301-6303, childNodes
, извлеченный на # 6344, div удален на # 6347 для очистки (плюС# 6359-6361 как исправление ошибок), childNodes
, объединенный в возвращаемый массив на # 6351- 6355 и вернулся на # 6406.
Следовательно, все методы, которые вызывают jQuery.buildFragment
, которые включают jQuery.parseHTML
и jQuery.fn.domManip
, среди них: .append()
, .after()
, .before()
, которые вызывают метод объекта domManip
jQuery, а $(html)
, который обрабатывается в jQuery.fn.init
(определенный @# 97, обработка сложного [более одного тега] html строк @# 125, вызывает jQuery.parseHTML
@# 131).
Имеет смысл, что практически все синтаксические строки jQuery HTML (помимо одиночных строк HTML-тегов) выполняются с использованием элемента div
в качестве контейнера, а теги html
/body
являются недопустимыми потомками элемента div
поэтому они лишены.
Добавление: Новые версии jQuery (1.9+) реорганизовали логику синтаксического анализа HTML (например, внутренний метод jQuery.clean
больше не существует), но общая логика синтаксического анализа остается той же.
Ответ 3
Я думаю, что у меня есть еще лучший способ:
скажем, у вас есть html:
var htmlText = '<html><body><div class="class0"><h4>data1</h4><p class="class1">data2</p><div id="mydivid"><p>data3</p></div></div></body></html>'
Вот то, что вы надеялись сделать:
var dataHtml = $($.parseXML(htmlText)).children('html');
dataHtml
теперь работает точно так же, как обычные объекты jquery, с которыми вы знакомы!!
Замечательная вещь в этом решении заключается в том, что он не будет разделять теги тела, головы или script!
Ответ 4
Попробуйте это
alert($(datahtml).find(".class0 h4").text());
Причина того, что текст, на который вы ссылаетесь, находится внутри элемента h4
class0
. Поэтому ваш селектор не будет работать,
Или напрямую обращайтесь к содержимому.
alert($(".class0 h4").text());
alert($(".class1").text());
alert($("#mydivid").text());
ИЗМЕНИТЬ
var datahtml = "<html><body><div class=\"class0\"><h4>data1</h4><p class=\"class1\">data2</p><div id=\"mydivid\"><p>data3</p></div></div></body></html>";
$('body').html(datahtml);
alert($(".class0 h4").text());
alert($(".class1").text());
alert($("#mydivid").text());
ПРОВЕРИТЬ ДЕМО
Ответ 5
Я не знаю другого способа, чем размещение HTML во временном невидимом контейнере.
$(document).ready(function(){
var datahtml = $("<html><body><div class=\"class0\"><h4>data1</h4><p class=\"class1\">data2</p><div id=\"mydivid\"><p>data3</p></div></div></body></html>".replace("\\", ""));
var tempContainer = $('<div style="display:none;">'+ datahtml +'</div>');
$('body').append(tempContainer);
alert($(tempContainer).find('.class1').text());
$(tempContainer).remove();
});
Вот jsfiddle demo.
Ответ 6
Это не работает, потому что <div>
с классом class0
не имеет текстовых узлов в качестве прямых дочерних элементов. Добавьте класс в <h4>
и он будет работать
Ответ 7
Я думаю, главная проблема заключается в том, что вы не можете использовать html для jQuery. В вашем случае, что происходит с Jquery, так это то, что он пытается найти первый тег html, который в вашем случае является div с классом0.
Проверьте это, чтобы убедиться, что я прав:
if($(datahtml).hasClass('class0'))
alert('Yes you are right :-)');
Таким образом, это означает, что вы не можете добавить тег html и body в качестве части для запроса.
Если вы хотите заставить его работать, попробуйте добавить эту часть кода:
<div>
<div class="class0">
<h4>data1</h4>
<p class="class1">data2</p>
<div id="mydivid"><p>data3</p></div>
</div>
</div>
Итак, попробуйте следующее:
var datahtml = "<div><div class=\"class0\"><h4>data1</h4><p class=\"class1\">data2</p><div id=\"mydivid\"><p>data3</p></div></div></body></div>";
alert($(datahtml).find(".class0").text()); // work
alert($(datahtml).find(".class1").text()); // work
alert($(datahtml).find("#mydivid").text()); // work