get XML 1.1 from Api with R

109 views Asked by At

http://www.librarything.com/services/rest/1.1/?method=librarything.ck.getwork&isbn=9788426379696&apikey=d231aa37c9b4f5d304a60a3d0ad1dad4

http://www.librarything.com/services/rest/1.1/?method=librarything.ck.getwork&isbn=9788426348593&apikey=d231aa37c9b4f5d304a60a3d0ad1dad4

I'm trying to get the description from that XML using R but I'm having a hard time doing that.

As not all XML have all their parameters, I can not "wire" the position of the description, no just because there could be no description, but also because tha lack of another parameter may change the index of the description .

I need a way to "search" for that xml that have the word description on its attributes.

require(stringr)
library("rjson")
require(XML)
cat("\014")  
gc()

isbn <- 9788426379696
key <- 'd231aa37c9b4f5d304a60a3d0ad1dad4'

descripcion_librarything <- function( isbn_num ,APIKey ){

  url  <- "http://www.librarything.com/services/rest/1.1/?method=librarything.ck.getwork&isbn="
  url<- paste(url,isbn_num, "&apikey=", APIKey, sep = "") 
  data <- xmlParse(url)
  xml_data <- xmlToList(data)
  class(xml_data)

  #<field type="14" name="description" displayName="Description">

  xml_data$ltml$item$author$text
  xml_data$ltml$item$commonknowledge$fieldList[17]$field$versionList$version$factList$fact

  doc = xmlInternalTreeParse(url)
  hasSentence = xpathApply(doc, "description")
  xpathApply(doc, "description")

  doc = xmlTreeParse(url)
  xmlAttrs(xmlRoot(doc)[[1]][[1]][[5]][[1]][[17]])

  str <- null 
  return(str)
}

descripcion_librarything (isbn, key)

thanks in advance !

2

There are 2 answers

0
Israel Rodriguez On

Loop through the xml data<- xmlToList(data), like this:

 for (i in 1:length(xml_data$ltml$item$commonknowledge$fieldList) ){
        if(xml_data$ltml$item$commonknowledge$fieldList[i]$field$.attrs['name'] == "description" ){
          print(paste('index ',i))
        }
     }
0
hrbrmstr On
library(httr)
library(xml2)

get_description <- function(ISBN) {

  httr::GET("http://www.librarything.com/services/rest/1.1/",
            query=list(method = "librarything.ck.getwork",
                       isbn = ISBN,
                       apikey = Sys.getenv("LIBRARYTHING_API_KEY"))) -> res

  stop_for_status(res)

  res <- content(res, as="text")
  doc <- read_xml(res)

  desc <- xml_find_all(doc, ".//*[@name='description']")

  if (length(desc) > 0) {
    xml_text(desc) # or whatever you need
  } else {
    "" # or whatever you want to return if not found
  }

}

isbns <- c("9788426379696", "9788426348593")

purrr::map_chr(isbns, get_description)

That:

  • makes it a wrapped API
  • keeps the API key out of scripts and StackOverflow posts (DELETE & INVALIDATE THE KEY)
  • provides a way to target & process descriptions & return what you eed
  • provides a way to return something useful on not found condition