Análisis de cadena html usando jquery

Estoy tratando de analizar este html a través de jQuery para obtener data1, data2, data3. Si bien obtengo data2 y data3, no puedo obtener data3 con mi enfoque. Soy bastante nuevo en jQuery así que disculpen mi ignorancia.

  

data1

data2

data3

Así es como estoy llamando esto en mi jquery.

 var datahtml = "

data1

data2

data3

"; alert($(datahtml).find(".class0").text()); // Doesn't Work alert($(datahtml).find(".class1").text()); // work alert($(datahtml).find("#mydivid").text()); // work

Solo alert($(datahtml).find(".class0").text()); no funciona, el rest funciona como se esperaba Me pregunto si puede ser porque class0 tiene varias tags dentro o ¿qué? ¿Cómo obtener data1 en tal escenario?

Su comportamiento es extraño ya que igorona la etiqueta html y body y comienza desde la primera div con class = “class0”. El html se analiza como elementos DOM pero no se agrega a DOM. Para los elementos añadidos a DOM, el selector no ignora la etiqueta de cuerpo y aplica selectores en el documento. Debe agregar el html a DOM como se indica a continuación.

Demo en vivo

 $('#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 

Si envolvemos su html dentro de algún elemento html para convertirlo en el punto de partida en lugar de su primer div con class = “class0”, su selector funcionará como se esperaba.

Demo en vivo

 var datahtml = "

data1

data2

data3

"; alert($(datahtml).find(".class0").text()); // Now it Works too alert($(datahtml).find(".class1").text()); // work alert($(datahtml).find("#mydivid").text()); // work

Qué dice jQuery sobre la función de análisis jQuery jQuery () ie $ ()

Al pasar HTML complejo, algunos navegadores no pueden generar un DOM que replique exactamente la fuente HTML proporcionada. Como se mencionó, jQuery usa la propiedad .innerHTML del navegador para analizar el HTML pasado e insertarlo en el documento actual. Durante este proceso, algunos navegadores filtran ciertos elementos como , o elements Como resultado, los elementos insertados pueden no ser representativos de la secuencia original pasada.

Ninguna de las respuestas actuales aborda el problema real, así que lo probaré.

 var datahtml = "

data1

data2

data3

"; console.log($(datahtml));

$(datahtml) es un objeto jQuery que solo contiene el elemento div.class0 , por lo tanto, cuando llamas a .find en él, en realidad estás buscando descendientes de div.class0 lugar de todo el documento HTML que esperas.

Una solución rápida es envolver los datos analizados en un elemento para que el .find funcione como se .find :

 var parsed = $('
').append(datahtml); console.log(parsed.find(".class0").text());

Violín


La razón de esto no es muy simple, pero asumo que cuando jQuery “analiza” cadenas de html más complejas simplemente colocando su cadena de HTML en un fragmento de DOM creado al vuelo y luego recupera los elementos analizados, es muy probable que esta operación haga que el analizador DOM ignore las tags html y body ya que serían ilegales en este caso.

Aquí hay un conjunto de pruebas muy pequeño que demuestra que este comportamiento es consistente a través de jQuery 1.8.2 hasta llegar a 1.6.4.

Editar: citando esta publicación :

El problema es que jQuery crea un DIV y establece innerHTML y luego toma DIV hijos, pero dado que los elementos BODY y HEAD no son hijos DIV válidos, entonces esos no son creados por el navegador.

Me hace confiar más en que mi teoría es correcta. Lo compartiré aquí, espero que tenga sentido para ti. Ten la fuente no comprimida de jQuery 1.8.2 al lado de esto. El # indica los números de línea.

Todos los fragmentos de documentos realizados a través de jQuery.buildFragment (definido @ # 6122) pasarán por jQuery.clean (# 6151) (incluso si se trata de un fragmento en caché, ya pasó por jQuery.clean cuando se creó), y como el el texto citado arriba implica, jQuery.clean (definido @ # 6275) crea un nuevo div dentro del fragmento seguro para servir como contenedor para los datos analizados – elemento div creado en # 6301-6303, childNodes recuperados en # 6344, div eliminado en # 6347 para limpiar (más # 6359-6361 como solución de errores), childNodes fusionó en la matriz de devolución en # 6351-6355 y se devolvió en # 6406.

Por lo tanto, todos los métodos que invocan jQuery.buildFragment , que incluyen jQuery.parseHTML y jQuery.fn.domManip , entre los que se encuentran .append() , .after() , .before() que invocan el método de objeto domManip jQuery y $(html) que se maneja en jQuery.fn.init (define @ # 97, manejo de cadenas [html] complejas más de una sola etiqueta @ # 125, invoca jQuery.parseHTML @ # 131).

Tiene sentido que prácticamente todos los análisis de cadenas jQuery HTML (además de cadenas html de etiqueta única) se realicen utilizando un elemento div como contenedor, y body tags html / body no son descendientes válidos de un elemento div para que se eliminen.


Adición: las versiones más recientes de jQuery (1.9+) han modificado la lógica de análisis de HTML (por ejemplo, el método jQuery.clean interno ya no existe), pero la lógica de análisis general sigue siendo la misma.

Creo que tengo una forma aún mejor:

digamos que tienes tu html:

 var htmlText = '

data1

data2

data3

'

Esto es lo que has estado esperando hacer:

 var dataHtml = $($.parseXML(htmlText)).children('html'); 

dataHtml ahora funciona exactamente como los objetos jquery comunes con los que está familiarizado.

¡Lo maravilloso de esta solución es que no va a despojar a las tags de cuerpo, cabeza o guiones!

Prueba esto

 alert($(datahtml).find(".class0 h4").text()); 

El motivo por el cual el texto al que se refiere es dentro del elemento h4 de class0 … Por lo tanto, su selector no funcionará, o accederá a los contenidos directamente.

 alert($(".class0 h4").text()); alert($(".class1").text()); alert($("#mydivid").text()); 

EDITAR

 var datahtml = "

data1

data2

data3

"; $('body').html(datahtml); alert($(".class0 h4").text()); alert($(".class1").text()); alert($("#mydivid").text());

CHECK DEMO

No conozco otra manera que colocar el HTML en un contenedor invisible temporal.

 $(document).ready(function(){ var datahtml = $("

data1

data2

data3

".replace("\\", "")); var tempContainer = $('
'+ datahtml +'
'); $('body').append(tempContainer); alert($(tempContainer).find('.class1').text()); $(tempContainer).remove(); });​

Aquí hay una demostración jsfiddle .

No funciona porque el

con la clase class0 no tiene ningún nodo de texto como hijos directos. Agregue la clase a la

y funcionará

Creo que el problema principal es que no puedes tener un html para tu jquery. En tu caso, lo que le sucede a Jquery es que trata de encontrar la primera etiqueta html, que en tu caso es div con class0.

Prueba esto para ver si estoy en lo correcto:

 if($(datahtml).hasClass('class0')) alert('Yes you are right :-)'); 

Esto significa que no puede agregar el html y / o la etiqueta de cuerpo como parte para tener una consulta dentro.

Si quiere que funcione, intente agregar esta parte del código:

 

data1

data2

data3

Entonces intente esto:

 var datahtml = "

data1

data2

data3

"; alert($(datahtml).find(".class0").text()); // work alert($(datahtml).find(".class1").text()); // work alert($(datahtml).find("#mydivid").text()); // work