2015-01-19 9 views
0

R에서 XML 처리가 필요한 여러 프로젝트가 있었지만 항상 어려움을 겪었습니다. 문제는 항상 동일합니다. 다른 사람의 복잡한 XML 구조를 파싱하여 실행 가능한 데이터 프레임으로 만듭니다.R에서 복잡한 XML 구조를 평탄하게 만드는 재귀 함수

아래의 예는 내 일반적인 문제입니다. 필자가 작업 한 데이터를 사용하면 노드 이름이 파일간에 반드시 일치하지는 않습니다. 보통 가장 깊은 수준의 수준에서 각 데이터 프레임 행을 병합 한 다음 성인 노드 이름 또는 특성으로 열을 채 웁니다.

이에서 얻을 싶이로

library(XML) 
# Small example extract 
# Most data points removed 

xml_extract <- xmlParse(" 
<COMPARISON ID=\"CMP-001\" NO=\"1\"> 
    <NAME>Incomplete resection (HGG)</NAME> 
    <DICH_SUBGROUP CHI2=\"0.0\" CI_END=\"0.0\" CI_START=\"0.0\"> 
     <NAME>iMRI</NAME> 
     <DICH_DATA CI_END=\"0.9640231041199472\" CI_START=\"0.017586933339032232\"/> 
    </DICH_SUBGROUP> 
    <DICH_SUBGROUP CHI2=\"0.0\" CI_END=\"0.0\" CI_START=\"0.0\"> 
     <NAME>5-ALA</NAME> 
     <DICH_DATA CI_END=\"0.7124078544369572\" CI_START=\"0.4242461206130219\"/> 
    </DICH_SUBGROUP> 
    <DICH_SUBGROUP CHI2=\"0.0\" CI_END=\"0.0\" CI_START=\"0.0\"> 
     <NAME>DTI-neuronavigation</NAME> 
     <DICH_DATA CI_END=\"0.6302184844574396\" CI_START=\"0.19776580326143214\"/> 
    </DICH_SUBGROUP> 
</COMPARISON> 
") 

:

dataframe

(나는이 열이이 같은 NAME, 문제의 일부 알고하지 내 XML.) .

나는 XML을 사용하며 XML2R을 살펴 보았습니다. 나는 친숙하다 - 녀석은 XPath이다. 표준 xmlToDataFrame 유형 명령이 작동하지 않습니다. 목록에 대해 표준 Apply 접근법 (예 : xmlSApply 또는 plyr)은 일반적으로 완전히 표준화 된 노드 이름을 필요로합니다.

내가 찾고 있는게 가능한거야? XML 구조를 실행하고 평평하게 만드는 재귀 함수입니다. 나는 테이블에서 XML 추출물에서 원하지 않는 비트를 편리하게 생략했다. :) 미리 감사드립니다!


편집은 좀 더 복잡하고 일반적인 예를 제공합니다.

감사합니다. 특히 hrbmstr과 관련하여 도움을 주셔서 대단히 감사합니다. 귀하의 솔루션은 과거 내 접근 방식이었습니다. 필자는 예제에 중대한 변형이있는 8000 개의 문서를 가지고 있으므로 변수 이름이 함수가 아닌 XML 내용에 의해 정의 된 솔루션을 찾고있었습니다. 여기

복잡하지만 전형적인 예 :

library(httr) 
library(XML) 
url = "http://onlinelibrary.wiley.com/doi/10.1002/14651858.CD007635.pub2/downloadstats" 
response = POST(url, body = list("tAndCs" = TRUE)) 

xml_record = content(response, "parsed", type="text/xml") 
path = "//ANALYSES_AND_DATA" 
xml_extract = xml_record[[path]] 

내가 가진 경험이없는 R interface for XSLT 있습니다. XSLT도 아닙니다.

+0

이와 같은 작업은 항상 저에게 XSLT 솔루션에 적합한 것처럼 보입니다. R에 대해 XSLT를 지원하는 패키지가없는 것 같습니다. – MrFlick

+1

@MrFlick 이제 https://cran.r-project.org/web/packages/xslt/index.html이 있습니다. 나 자신을 시도하지 않았습니다. –

답변

2

그것은 단지 XML 체계적으로 "공격"(필요하지 XSLT)를 필요로하지 않는다 :이 요구 사항을 충족하지 않는 경우

data.frame(comparison=xpathSApply(xml_extract, "//COMPARISON", xmlGetAttr, "ID"), 
      name=xpathSApply(xml_extract, "//COMPARISON/NAME", xmlValue), 
      dich_name=xpathSApply(xml_extract, "//COMPARISON/DICH_SUBGROUP/NAME", xmlValue), 
      ci_end=xpathSApply(xml_extract, "//COMPARISON/DICH_SUBGROUP/DICH_DATA", xmlGetAttr, "CI_END"), 
      ci_end=xpathSApply(xml_extract, "//COMPARISON/DICH_SUBGROUP/DICH_DATA", xmlGetAttr, "CI_START") 
) 

## comparison      name   dich_name    ci_end    ci_end.1 
## 1 CMP-001 Incomplete resection (HGG)    iMRI 0.9640231041199472 0.017586933339032232 
## 2 CMP-001 Incomplete resection (HGG)    5-ALA 0.7124078544369572 0.4242461206130219 
## 3 CMP-001 Incomplete resection (HGG) DTI-neuronavigation 0.6302184844574396 0.19776580326143214 

더 복잡한 XML 샘플을 게시하시기 바랍니다.

+0

의심스러운 경우 무차별 한 힘을 적용하십시오. Nice –

+0

일반화 된 예제는 더 추한 것입니다. (OP가 필요하지는 않길 바래요 :-) – hrbrmstr

+0

일찍이 알려 줬습니다. 어리석은 당신은 내 삭제 된 대답을 볼 수 없습니다. 나는 단지'lapply (xmlRoot (doc) [- 1], function (x) c (NAME = xmlValue (x), xmlAttrs (x [[2]]))) –

관련 문제