2015-03-03 3 views
0

У меня есть XML-файл (TEI-кодированный проигрыватель), который я хочу обработать в data.frame в R, где каждая строка файла data.frame содержит одну строку воспроизведение, номер строки, динамик этой линии, номер сцены и тип сцены. Тело файла XML выглядит следующим образом (но больше):Загрузите XML в DataFrame в R с атрибутами родительского узла

<text> 
<body> 
<div1 type="scene" n="1"> 
    <sp who="fau"> 
     <l n="30">Settle thy studies, Faustus, and begin</l> 
     <l n="31">To sound the depth of that thou wilt profess;</l> 
     <l n="32">Having commenced, be a divine in show,</l> 
    </sp> 
    <sp who="eang"> 
     <l n="105">Go forward, Faustus, in that famous art,</l> 
    </sp> 
</div1> 
<div1 type="scene" n="2"> 
    <sp who="sch1"> 
     <l n="NA">I wonder what's become of Faustus, that was wont to make our schools ring with sic probo.</l> 
    </sp> 
    <sp who="sch2"> 
     <l n="NA">That shall we know, for see here comes his boy.</l> 
    </sp> 
    <sp who="sch1"> 
     <l n="NA">How now sirrah, where's thy master?</l> 
    </sp> 
    <sp who="wag"> 
     <l n="NA">God in heaven knows.</l> 
    </sp> 
</div1> 
</body> 
</text> 

проблема кажется похожа на поставленные вопросы here и here, но мой файл XML структурирован немного по-другому, так что ни один не дал мне рабочий раствор. Я сумел сделать это:

library(XML) 
doc <- xmlTreeParse("data/faustus_sample.xml", useInternalNodes=TRUE) 

bodyToDF <- function(x){ 
    scenenum <- xmlGetAttr(x, "n") 
    scenetype <- xmlGetAttr(x, "type") 
    attributes <- sapply(xmlChildren(x, omitNodeTypes = "XMLInternalTextNode"), xmlAttrs) 
    linecontent <- sapply(xmlChildren(x), xmlValue) 
    data.frame(scenenum = scenenum, scenetype = scenetype, attributes = attributes, linecontent = linecontent, stringsAsFactors = FALSE) 
} 

res <- xpathApply(doc, '//div1', bodyToDF) 
temp.df <- do.call(rbind, res) 

Это возвращает data.frame с «номером сцены», «тип сцены» и «динамик» неповрежденной, но я не могу работать, как разбить его к каждой строке (и получить номер соответствующей линии).

Я попытался импортировать файл в виде списка (через xmlToList), но это дало мне невероятно грязный список списков списков, а также привело к множеству разных ошибок, если я попытался использовать для циклов для доступа к разные элементы (ужасная идея, я знаю!).

В идеале, я ищу решение, которое будет работать с полным файлом во всей его беспорядочности, а также работать с другими, аналогично структурированными XML-файлами.

Я только что начал использовать R, и я полностью в недоумении. Любая помощь, которую вы можете предоставить, будет чрезвычайно оценена.

Благодарим за помощь!

EDIT: имеется копия полного файла xml here.

ответ

1

Добавлены дополнительные xpathApply для зр элементов:

bodyToDF <- function(x){ 
    scenenum <- xmlGetAttr(x, "n") 
    scenetype <- xmlGetAttr(x, "type") 
    sp <- xpathApply(x, 'sp', function(sp) { 
    who <- xmlGetAttr(sp, "who") 
    if(is.null(who)) 
     who <- NA 
    line_num <- xpathSApply(sp, 'l', function(l) { xmlGetAttr(l,"n")}) 
    linecontent = xpathSApply(sp, 'l', function(l) { xmlValue(l,"n")}) 
    data.frame(scenenum, scenetype, who, line_num, linecontent) 
    }) 
    do.call(rbind, sp) 
} 

res <- xpathApply(doc, '//div1', bodyToDF) 
temp.df <- do.call(rbind, res) 

Первые 4 колонки:

# > temp.df[,1:4] 
# scenenum scenetype who line_num 
# 1  1  scene fau  30 
# 2  1  scene fau  31 
# 3  1  scene fau  32 
# 4  1  scene eang  105 
# 5  2  scene sch1  NA 
# 6  2  scene sch2  NA 
# 7  2  scene sch1  NA 
# 8  2  scene wag  NA 
+0

Оказывается, это решение отлично работает для образца XML, но изломы на полном документе. Насколько я могу судить, они форматируются одинаково. При запуске строки 'res <- xpathApply (doc, '// div1', bodyToDF)' Я получаю ошибку '' Ошибка в data.frame (scenenum = xmlGetAttr (x, "n"), scenetype = xmlGetAttr (x, : аргументы подразумевают различное количество строк: 1, 0 "'. – galenc

+0

В полном документе есть строка без атрибута 'who'. Я обновил обработку ответов только в этом случае (' is.null (who) '). – bergant

+0

Yep , просто поймал его. Еще такой R noob, но я получу это. Большое спасибо за вашу помощь! – galenc

Смежные вопросы