R: разобрать большой неструктурированный XML-файл - PullRequest
0 голосов
/ 02 мая 2018

У меня очень сложный xml-файл, который нужно проанализировать и представить в формате фрейма данных в R. Структура может быть похожа на следующий пример. Узлы не параллельны.

<Root>
  <A>
   <info1>a</info1>
     <child>
       <info2>b</info2>
       <info3>c</info3>
       <info4>d</info4>
     </child>
   <info5>e</info5>
  </A>
  <B>
   <info6>f</info6>
   <info7>g</info7>
  </B>
</Root>

Придумываю код для разбора файла:

doc <- xmlParse(file="sample.xml", useInternal = TRUE)
rootnode <- xmlRoot(doc)
df1<-xmlToDataFrame(nodes=getNodeSet(rootnode, "//Root/A"))
df2<-xmlToDataFrame(nodes=getNodeSet(rootnode, "//Root/B"))
Final<-cbind.data.frame(df1,df2, all=TRUE)

Результат, возвращаемый как: (все узлы формы значений были сжаты вместе)

info1 child info5 info6 info7
  a    bcd    e     f     g

Тем не менее, идеальный результат, который я хочу получить:

info1 info2 info3 info4 info5 info6 info7
  a     b     c     d     e     f     g

Поскольку в xml-файле имеется большое количество узлов, аналогичное описанному выше, нецелесообразно вручную манипулировать кадром данных.
Я также пытаюсь изменить инструкцию пути на "// Root / A / child", тогда все значения в узле A и узле B будут пропущены. Кто-нибудь может предложить решение этой проблемы. Заранее спасибо.

Ответы [ 3 ]

0 голосов
/ 02 мая 2018

Можно попробовать xmlToList и unlist, чтобы уменьшить xml данные в названном векторном формате. Имена могут быть изменены с помощью gsub, чтобы соответствовать ожиданиям OP как:

library(XML)
result <- unlist(xmlToList(xmlParse(xml)))
#Change the name to refer only child 
names(result) <- gsub(".*\\.(\\w+)$","\\1", names(result))
result 
# info1 info2 info3 info4 info5 info6 info7 
# "a"   "b"   "c"   "d"   "e"   "f"   "g"

Данные:

xml <- "<Root>
  <A>
  <info1>a</info1>
  <child>
  <info2>b</info2>
  <info3>c</info3>
  <info4>d</info4>
  </child>
  <info5>e</info5>
  </A>
  <B>
  <info6>f</info6>
  <info7>g</info7>
  </B>
  </Root>"
0 голосов
/ 03 мая 2018

Сопоставьте узлы, используя starts-with()

> doc = xmlParse(xml)
> xpathSApply(doc, "//*[starts-with(name(), 'info')]", xmlValue)
[1] "a" "b" "c" "d" "e" "f" "g"
> xpathSApply(doc, "//*[starts-with(name(), 'info')]", xmlName)
[1] "info1" "info2" "info3" "info4" "info5" "info6" "info7"

так

query <- "//*[starts-with(name(), 'info')]"
setNames(
    xpathSApply(doc, query, xmlValue),
    xpathSApply(doc, query, xmlName)
)
0 голосов
/ 02 мая 2018

В менее структурированном XML лучше сделать следующее:

library(XML)
Final <- data.frame(xmlToList(rootnode), recursive = T, use.names = T)

Если вам не нравятся автоматически задаваемые имена столбцов, вы можете просто сделать use.names = F и установить свои собственные имена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...