Преобразование вложенного XML-документа во фрейм данных, когда информация находится как в атрибуте, так и в текстовом узле. - PullRequest
1 голос
/ 11 марта 2019

Справочная информация:

У меня есть документ XML со следующей структурой:

<records>
 <record id="512" size="1">
  <user id="8412" origin="ab"/>
  <category id="105">Certificates</category>
  <rating>80</rating>
  <text>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
  </text>
 </record>
 <record id="452" size="2">
  <user id="7623" origin="bb"/>
  <category id="105">Certificates</category>
  <rating>70</rating>
  <text>
  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
  </text>
 </record>
</records>

Что я пытаюсь сделать:

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

Вот как должен выглядеть окончательный результат:

Record ID | Size | User ID | ... | Text           |
       452|     2|     7623| ... | Lorem ipsum... | 

Кроме того, поскольку существует около 1 000 000 записей, а файл, содержащий их, составляет ~ 500 МБ, я пытаюсь найти относительно эффективный способ сделать это.

Что я пробовал до сих пор:

Я рассмотрел ряд связанных вопросов по этой теме, но ни один из них не предложил решения, которое применимо в этом случае.

Сначала я попытался использовать функцию 'xmlToDataFrame' в пакете XML, используя следующий код, но он только извлекает текстовые данные, а не атрибуты:

library(XML)
doc = xmlParse("My_document.xml")
xmldf = xmlToDataFrame(doc, nodes = "//record")
xmldf = xmlToDataFrame(nodes = getNodeSet(doc, "//record"))

То же самое происходит, когда я пытаюсь использовать пакет flatxml, несмотря на тот факт, что во время первоначального импорта XML-документа он извлекает соответствующие данные атрибута:

library(flatxml)
doc = fxml_importXMLFlat("My_document.xml")
xmldf = fxml_toDataFrame(xml_original, siblings.of = 2)

Я также попробовал немного другой подход с использованием пакета xml2:

library(xml2)
doc <- read_xml('My_document.xml')
rows <- xml_children(doc)
data.frame(
  Record_ID = as.numeric(xml_attr(rows,"id")),
  Size = as.numeric(xml_attr(rows,"size")),
  User_ID = as.numeric(xml_attr(rows,"id")),
  Origin = as.character(xml_attr(rows,"origin")),
  Category = as.character(xml_text(rows,"category")),
  Category_ID = as.numeric(xml_attr(rows,"id")),
  Rating = as.numeric(xml_text(rows,"rating")),
  Text = as.character(xml_text(rows,"text"))
) -> xmldf

Здесь у меня был другой набор проблем: я могу извлечь данные атрибутов, но только из узла «запись». Это означает, что он копирует данные «id» из записи для «User_ID» и не может получить доступ к соответствующим данным для таких вещей, как атрибут «origin». Кроме того, этот процесс также извлекает всю текстовую информацию из всех узлов одновременно каждый раз, когда я пытаюсь извлечь ее.

1 Ответ

1 голос
/ 11 марта 2019

Рассмотрим атрибуты связывания с внутренним методом xmlAttrsToDataFrame и элементы с xmlToDataFrame, предполагая, что только один набор пользователь и родственные теги на запись .

library(XML)
...

# BIND ATTRIBUTES AND ELEMENTS
record_df <- cbind(XML:::xmlAttrsToDataFrame(getNodeSet(doc, path='//record')),
                   XML:::xmlAttrsToDataFrame(getNodeSet(doc, path='//user')),
                   xmlToDataFrame(doc, nodes = getNodeSet(doc, "//record"))
             )    

# RENAME COLUMNS
record_df <- setNames(record_df, c("record_id", "record_size", "user_id", "user_origin",
                                   "record_user", "record_category", "record_rating", "record_text"))

record_df
#   record_id record_size user_id user_origin record_user record_category record_rating              record_text
# 1       512           1    8412          ab                Certificates            80  \nLorem ipsum dolor ...
# 2       452           2    7623          bb                Certificates            70   \nUt enim ad minim ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...