2015-06-23 35 views
1

源自this問題,我對R(和其他)文檔的研究表明SAX方法將是解析XML數據的一種更快的方法。可悲的是,我找不到很多有用的例子來了解如何到達那裏。解析R中的XML SAX方式

這是一個包含我想分析信息的虛擬文件。真正的事情將有更多的<ITEM>節點和我想排除的樹周圍的其他節點。另一個特點是<META>部分有兩個<DESC>元素,我需要其中的任何一個(不是兩個)。

<FILE> 
    <HEADER> 
    <FILEID>12347</FILEID> 
    </HEADER> 
    <META> 
    <DESC> 
     <TYPE>A</TYPE> 
     <CODE>ABC</CODE> 
     <VALUE>100000</VALUE> 
    </DESC> 
    <DESC> 
     <TYPE>B</TYPE> 
     <CODE>ABC</CODE> 
     <VALUE>100000</VALUE> 
    </DESC> 
    </META> 
    <BODY> 
    <ITEM> 
     <IVALUE>1000</IVALUE> 
     <ICODE>CDF</ICODE> 
     <ITYPE>R</ITYPE> 
    </ITEM> 
    <ITEM> 
     <IVALUE>1500</IVALUE> 
     <ICODE>EGK</ICODE> 
     <ITYPE>R</ITYPE> 
    </ITEM> 
    <ITEM> 
     <IVALUE>300</IVALUE> 
     <ICODE>TSR</ICODE> 
     <ITYPE>R</ITYPE> 
    </ITEM> 
    </BODY> 
</FILE> 

對於例如XML在上面,我希望得到

> data.table(fileid=12347, code="ABC", value=10000, ivalue=c(1000,1500,300), icode=c("CDF","EGK","TSR"), itype="R") 
# fileid code value ivalue icode itype 
# 1: 12347 ABC 10000 1000 CDF  R 
# 2: 12347 ABC 10000 1500 EGK  R 
# 3: 12347 ABC 10000 300 TSR  R  

誰能與SAX經驗指導我建立一個解析器適合我的需要與xmlEventParse()

回答

1

可能是這樣的嗎?

library(rvest) 
library(data.table) 


test<-read_html("test.html") 
    data.table(do.call(cbind,lapply(c("fileid","code","value","ivalue","icode","itype"),function(i){ 
     test %>% 
     html_nodes(i)%>% 
     html_text() 


    }))) 

     V1 V2  V3 V4 V5 V6 
    1: 12347 ABC 100000 1000 CDF R 
    2: 12347 ABC 100000 1500 EGK R 
    3: 12347 ABC 100000 300 TSR R 
1

用於XML可能提高速度在解析XML數據與另一種方法,但一般使用SAX不會給你比XPath的更好的結果,例如在簡單的API。相反,對於更大的文件,它將允許不加載R中的完整樹,從而避免潛在的內存泄漏。

對於使用SAX,您可以使用下面的代碼示例,它是基於xmlEventParse分支(每個數據的一個分支要檢索):

#a file to read with xmlEventParse 
xmlDoc <- "example.xml" 

desc <- NULL 
items <- NULL 

#function to use with xmlEventParse 
row.sax = function() { 

    #SAX function for Meta 'DESC' 
    DESC = function(node){ 
     children <- xmlChildren(node) 
     children[which(names(children) == "text")] <- NULL 
     desc <<- rbind(desc, sapply(children,xmlValue)) 
    } 

    #SAX function for Body 'ITEM' 
    ITEM = function(node){ 
     children <- xmlChildren(node) 
     children[which(names(children) == "text")] <- NULL 
     items <<- rbind(items, sapply(children,xmlValue)) 
    } 

    branches <- list(DESC = DESC, ITEM = ITEM) 
    return(branches) 
} 

#call the xmlEventParse 
xmlEventParse(xmlDoc, handlers = list(), branches = row.sax(), 
       saxVersion = 2, trim = FALSE) 

#processing the result as data.frame 
desc <- as.data.frame(desc, stringsAsFactors = F) 
desc <- desc[rep(row.names(desc[1,]), nrow(items)),] 

items <- as.data.frame(items, stringsAsFactors = F) 

result <- cbind(desc, items) 
row.names(result) <- 1:nrow(result) 

讓我知道它是否適合你