R Cran - 嵌套不规则 xml,其中 xml 的属性作为数据框的列名称

问题描述 投票:0回答:1

我有一个由 Windows 日志生成的大 xml 文件,我需要将其导入 R 中以分析记录的事件之间的一些相关性。 我遇到的问题是事件的详细信息 (EventData) 保留为 xml 的属性,并且属性的数量根据事件的类型而变化。

要导入的简化 xml 是:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Events>
    <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
        <System>
            <EventID>259</EventID>
            <Version>0</Version>
            <Level>2</Level>
            <TimeCreated SystemTime="2024-07-10T15:02:35.203376200Z"/>
        </System>
        <EventData>
            <Data Name="TCP">0</Data>
            <Data Name="InterfaceIP">0.0.0.0</Data>
            <Data Name="Source">192.168.109.4</Data>
            <Data Name="QNAME"/>
        </EventData>
    </Event>
    <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
        <System>
            <EventID>256</EventID>
            <Version>0</Version>
            <Level>4</Level>
            <TimeCreated SystemTime="2024-07-10T15:02:35.203362300Z"/>
        </System>
        <EventData>
            <Data Name="TCP">0</Data>
            <Data Name="InterfaceIP">0.0.0.0</Data>
            <Data Name="Source">192.168.109.4</Data>
            <Data Name="QNAME">microsoft.com.</Data>
            <Data Name="QTYPE">0</Data>
            <Data Name="XID">22342</Data>
            <Data Name="Port">65220</Data>
            <Data Name="Flags">16979</Data>
            <Data Name="BufferSize">108</Data>
         </EventData>
    </Event>
</Events>

预期结果

这正是我所期望的。

我写的代码是:

library(xml2)
library(tibble)
library(dplyr)


file_dns <- c("./test_ridotto_2.xml")
read_xml(file_dns) -> dns


dns_items <- tibble(
   event_id =  xml_find_all(x = dns, xpath = "/Events/Event/System/EventID") |> xml_text(),
   time_created = xml_find_all(x = dns, xpath = "/Events/Event/System/TimeCreated") |> xml_attr(attr = "SystemTime"),
   info4 = xml_find_all(x = dns, xpath = "/Events/Event/EventData") |> as_list()
)

我遇到的问题是,我不明白如何继续拆分列并为它们指定属性的名称,因为属性的数量和列的数量逐行变化,并取决于属性的类型已记录事件。 我尝试了 unnest_wider 命令,但它丢失了属性,并且在我的简化测试文件上看起来很慢。 制作文件为1Gb。

怎样才能得到预期的结果?

谢谢 多梅尼科

r xml
1个回答
0
投票

此脚本从每个事件中提取 eventID 和创建时间,然后循环访问事件并提取数据元素和节点 ID 来为最终答案创建数据帧。

请参阅下面的评论了解步骤。

library(xml2)
library(dplyr)

#read page and strip namespace
page <- read_xml(text)
xml_ns(page)

#find the events nodes
events <- xml_find_all(page, ".//Event")

#get the eventID and Created time
eventID <- xml_find_first(events, ".//EventID") %>% xml_text()
CreatedTime <-xml_find_first(events, ".//TimeCreated") %>% xml_attr("SystemTime")

#loop through the events and extract the data
#make a data frame and create the proper column headings
dfs <- lapply(events, function(node){
   data <- xml_find_all(node, ".//Data") %>% xml_text()
   tag <- xml_find_all(node, ".//Data") %>% xml_attrs() %>% unlist()
   names(tag)<-NULL
   df<-as.data.frame(t(data))
   names(df) <- tag
   df
})

#make a data frame for the answer
answer <- bind_rows(dfs)

#add the event ID and timecreated
answer <-bind_cols(EventID=eventID, CreatedTime=CreatedTime, answer)

  EventID                    CreatedTime TCP InterfaceIP        Source          QNAME QTYPE   XID  Port Flags BufferSize
1     259 2024-07-10T15:02:35.203376200Z   0     0.0.0.0 192.168.109.4                 <NA>  <NA>  <NA>  <NA>       <NA>
2     256 2024-07-10T15:02:35.203362300Z   0     0.0.0.0 192.168.109.4 microsoft.com.     0 22342 65220 16979        108
© www.soinside.com 2019 - 2024. All rights reserved.