R/xbrl.R

#' Convert xbrl to 
#' @param xml xbrl document to read
#' @export
#' @importFrom magrittr "%>%"
xbrl <- function(xml){
  
  ns <- xml2::xml_ns(xml)
  
  for(i in 1:length(ns)){
    if (ns[[i]] == "http://www.xbrl.org/2003/instance"){
      param <- list(old = ns)
      param[[names(ns[i])]] <- "xbrli"
      ns <- do.call(xml2::xml_ns_rename, param) 
    }
  }
  
  c_i <- 1
  u_i <- 1
  f_i <- 1
  
  contexts <- c()
  units <- c()
  facts <- c()
  
  for(x in xml2::xml_children(xml)){
    
    if (xml2::xml_name(x) == "unit"){
      
      unit <- list(
        id = xml2::xml_attr(x, attr = 'id'),
        measure = xml2::xml_text(
          xml2::xml_child(x, 'measure')
        )
      )
      
      units[[u_i]] <- unit
      u_i <- u_i + 1
      
    } else if(xml2::xml_name(x) == "context"){
      
      context <- list(
        id = xml2::xml_attr(x, attr = 'id', ns = ns),
        
        entity = xml2::xml_text(
          xml2::xml_find_first(x, ".//xbrli:entity//xbrli:identifier", ns = ns)
        ),
          
          # xml2::xml_child(x, 'xbrli:entity', ns = ns) %>%
          # xml2::xml_child("xbrli:identifier", ns = ns) %>%
          # xml2::xml_text(),
        
        start_date = xml2::xml_text(
          xml2::xml_find_first(x, ".//xbrli:period//xbrli:startDate", ns = ns)
        ),
          
          # xml2::xml_child(x, 'xbrli:period', ns = ns) %>%
          # xml2::xml_child('xbrli:startDate', ns = ns) %>%
          # xml2::xml_text(),
        
        end_date = xml2::xml_text(
          xml2::xml_find_first(x, ".//xbrli:period//xbrli:endDate", ns = ns)
        ),
          
          # xml2::xml_child(x, 'xbrli:period', ns = ns) %>%
          # xml2::xml_child('xbrli:endDate',  ns = ns) %>%
          # xml2::xml_text(),
        
        instant = xml2::xml_text(
          xml2::xml_find_first(x, ".//xbrli:period//xbrli:instant", ns = ns)
        ),
          
          # xml2::xml_child(x, 'xbrli:period',  ns = ns) %>%
          # xml2::xml_child('xbrli:instant',  ns = ns) %>%
          # xml2::xml_text(),
        
        explicitMember = xml2::xml_text(
          xml2::xml_find_first(x, ".//xbrli:scenario//xbrldi:explicitMember", ns = ns)
        ),
          
          # xml2::xml_child(x, 'xbrli:scenario') %>%
          # xml2::xml_child('xbrldi:explicitMember', ns = ns) %>%
          # xml2::xml_text(),
        
        explicitMember_dimension = xml2::xml_attr(
          xml2::xml_find_first(x, ".//xbrli:scenario//xbrldi:explicitMember", ns = ns)
          , attr = 'dimension', ns = ns),
          
          # xml2::xml_child(x, 'xbrli:scenario', ns = ns) %>%
          # xml2::xml_child('xbrldi:explicitMember', ns = ns) %>%
          # xml2::xml_attr('dimension', ns = ns),
        
        typedMember_dimension = xml2::xml_attr(
          xml2::xml_find_first(x, ".//xbrli:scenario//xbrldi:typedMember", ns = ns)
          , attr = 'dimension', ns = ns),
          
          # xml2::xml_child(x, 'xbrli:scenario', ns = ns) %>%
          # xml2::xml_child('xbrldi:typedMember', ns = ns) %>%
          # xml2::xml_attr('dimension', ns = ns),
        
        typedMember_identifier =  xml2::xml_text(
          xml2::xml_find_first(x, ".//xbrli:scenario//xbrldi:typedMember", ns = ns)
        ),
          
          # xml2::xml_child(x, 'xbrli:scenario', ns = ns) %>%
          # xml2::xml_child('xbrldi:typedMember', ns = ns) %>%
          # xml2::xml_text(),
        
        scheme = xml2::xml_attr(
          xml2::xml_find_first(x, ".//xbrli:entity//xbrli:identifier", ns = ns)
          , attr = 'scheme')
          
          # xml2::xml_child(x, 'xbrli:entity', ns = ns) %>%
          # xml2::xml_child("xbrli:identifier", ns = ns) %>%
          # xml2::xml_attr('scheme')
        
      )
      contexts[[c_i]] <- context
      c_i <- c_i + 1
      
    } else if(xml2::xml_name(x) == "footnote"){
      # no handling of footnotes for now
      NULL
    } else {
      
      x_namespace_tag <- stringi::stri_split_fixed(
        xml2::xml_name(x, ns = ns)
        , pattern = (":")
      )[[1]][[1]]
        
        # (xml2::xml_name(x, ns = ns) %>%
        #   stringi::stri_split_fixed(":") 
        #   %>% unlist())[1]
            
      fact <- list(
        fact = xml2::xml_name(x),
        context_ref = xml2::xml_attr(x, attr = "contextRef"),
        decimals = xml2::xml_attr(x, attr = "decimals"),
        unit_ref = xml2::xml_attr(x, attr = "unitRef"),
        value = xml2::xml_text(x),
        lang = xml2::xml_attr(x, attr = "lang"),
        ns = ns[x_namespace_tag]
      )
      
      
      facts[[f_i]] <- fact
      f_i <- f_i + 1
    }
  }
  
  xbrl <- c()
  xbrl$contexts <- data.table::rbindlist(contexts)
  xbrl$units <- data.table::rbindlist(units) 
  xbrl$facts <-  data.table::rbindlist(facts) 
  
  return(xbrl)

}
soetang/xbrlr documentation built on May 26, 2019, 7:01 p.m.