r – xpathApply en XMLNodeSet (con paquete XML)

Estoy tratando de usar la función xpathApply en el paquete XML en R para extraer ciertos datos de un archivo html. Sin embargo, después de usar xpathApply en algunos nodos primarios del documento html, la clase del objeto resultante se convierte en XMLNodeSet, y no puedo usar más xpathApply en dicho objeto, ya que aparece este mensaje de error: “Error en UseMethod (” xpathApply “): no se aplica ningún método para ‘xpathApply’ a un objeto de la clase “XMLNodeSet” ”

Aquí está el script R que estoy tratando de replicar mi problema (este ejemplo es solo una tabla simple, sé que puedo usar la función readHTMLtable, pero necesito usar una función de nivel más bajo para funcionar porque mi html real es más complicado que este simple mesa):

library(XML) y <- htmlParse(htmlfile) x <- xpathApply(y, "//table/tr") z <- xpathApply(x, "/td") 

Aquí está el “htmlfile”:

 
Test1.1 Test1.2
Test1.3 Test1.4

¿Hay algún método para seguir trabajando en los nodos después de usar xpathApply? ¿O hay otras buenas alternativas para jugar con los datos en los nodos?

Una vez que tenga una lista de nodos, puede aplicar una función en ella para extraer el nodo. Funciona como xmlValue o xmlGetAttr …. Por ejemplo:

 x <- xpathApply(y, "//table/tr") sapply(x,xmlValue) ## it a list of nodes.. " Test1.1 Test1.2 " " Test1.3 Test1.4 " 

Lo que equivale a hacer:

 xpathSApply(y,"//table/tr",xmlValue) " Test1.1 Test1.2 " " Test1.3 Test1.4 " 

EDITAR

Estoy seguro de que tu pregunta puede ser resuelta por el xpath correcto. Debe aprender a trabajar con archivos xml mientras trabaja con una base de datos. xpath es simplemente análogo a una consulta de SQL. es rápido y muchos navegadores pueden ayudarlo a obtener la xpath correcta.

Por ejemplo :

  xpathSApply(y,"//table/tr[2]/td[1]",xmlValue) # second tr and first td [1] " Test1.3 " xpathSApply(y,"//table/tr[2]/td[3]",xmlValue) # second tr and third td 

EDITAR

El OP parece como si quisiera replicar la estructura XML (obtener tr y td en el mismo orden)

Aquí está el camino, no creo que sea el modo más eficiente ...

 nn.trs <- length(xpathSApply(y,"//table/tr",I)) lapply(seq(nn.trs),function(i){ xpathSApply(y,paste("//table/tr[",i,"]/td",sep=''),xmlValue) }) [[1]] [1] " Test1.1 " " Test1.2 " [[2]] [1] " Test1.3 " " Test1.4 " 

Si si el número de td son todos iguales en cada tr, puede reemplazar lapply por sapply y obtendrá:

  [,1] [,2] [1,] " Test1.1 " " Test1.3 " [2,] " Test1.2 " " Test1.4 " 

Pero creo que en este caso readHtmlTable es mejor ..

Aunque la solución para definir la xPath correcta parece ser mejor, puedes hacer esto:

 library(XML) y <- htmlParse(htmlfile) x <- getNodeSet(y, "//table/tr") z <- lapply(x, function(x){ subDoc <- xmlDoc(x) r <- xpathApply(x, "/td") free(subDoc) # not sure if necessary return(r) }) 

Lo siguiente parece estar funcionando. Esencialmente tienes que buscar los elementos de la lista devuelta por xpathApply

 > y <- htmlParse(htmlfile) > x <- xpathApply(y, "//table/tr") > x [[1]]  Test1.1   Test1.2   [[2]]  Test1.3   Test1.4   attr(,"class") [1] "XMLNodeSet" > z <- xpathApply(x[[1]], "//td") > z [[1]]  Test1.1  [[2]]  Test1.2  [[3]]  Test1.3  [[4]]  Test1.4  attr(,"class") [1] "XMLNodeSet" 

PD: No estoy seguro de por qué busca todos los elementos de la lista x lugar de solo x[[1]] . Parece un error.