【问题标题】:R XML Get Ancestor Attribute for Each Occurrence of a Descendant AttributeR XML为后代属性的每次出现获取祖先属性
【发布时间】:2016-10-13 18:16:36
【问题描述】:

我正在尝试通过从 XML 文件中提取中断数据并将每次中断与特定仪表相关联来构建数据框。数据的简化示例如下所示:

  <MeterReadings Irn="311" Source="Remote">
       <Meter MeterIrn="311" IsActive="true" /> 
       <ConsumptionData>
       </ConsumptionData>
       <IntervalData>
           <Reading TimeStamp="2016-10-13" />
       </IntervalData>
       <EventData>
           <EventSpec Type="Outage Detected from Interval Data" Category="Full Power Outage / Restoration" />
           <Event TimeStamp="2014-10-31 14:17:40" DiscoveredAt="2014-11-01 12:05:28" Source="Event Log" EventInfo="Outage detected from Interval Data.">
           </Event>
           <Event TimeStamp="2014-10-31 14:16:20" DiscoveredAt="2014-11-01 12:05:28" Source="Event Log" EventInfo="Outage detected from Interval Data.">
           </Event>
           <Event TimeStamp="2014-10-31 14:16:16" DiscoveredAt="2014-11-01 12:05:28" Source="Event Log" EventInfo="Outage detected from Interval Data.">
           </Event>
           <Event TimeStamp="2014-10-31 14:15:12" DiscoveredAt="2014-11-01 12:05:28" Source="Event Log" EventInfo="Outage detected from Interval Data.">
           </Event>
           <Event TimeStamp="2014-10-31 14:12:00" DiscoveredAt="2014-11-01 12:05:28" Source="Event Log" EventInfo="Outage detected from Interval Data">
           </Event>
       </EventData>
  </MeterReadings>

我想要的是设置一个数据框,该数据框将在第一列中包含电表编号,在第二列中包含每次中断的时间。

我尝试过使用以下表达式:

    outage.inv <- data.frame(xpathSApply(doc, '//Event[contains(@EventInfo, "Outage detected from Interval Data")]/ancestor::MeterReadings', xmlGetAttr, "Irn"))
    outage.df <- data.frame(xpathSApply(doc, '//MeterReadings/EventData/EventSpec[@Type="Outage Detected from Interval Data"]/following-sibling::Event', xmlGetAttr, "TimeStamp"))
    outage.inv <- cbind(outage.inv, outage.df)

但是第一个表达式只拉一次米数,所以变量总数不匹配。在这种情况下,1 米数和 5 次停电时间。有没有办法为每个出现的带有后代的属性提取祖先属性?

我已经检查了以下答案,但无法弄清楚。

XPath to select element based on childs child value

R: How to get parent attributes and node values at the site time?

任何帮助将不胜感激。

【问题讨论】:

    标签: r xml attributes


    【解决方案1】:

    另一种方法。

    这是数据:

    txt <- '  <MeterReadings Irn="311" Source="Remote">
           <Meter MeterIrn="311" IsActive="true" />
           <ConsumptionData>
           </ConsumptionData>
           <IntervalData>
               <Reading TimeStamp="2016-10-13" />
           </IntervalData>
           <EventData>
               <EventSpec Type="Outage Detected from Interval Data" Category="Full Power Outage / Restoration" />
               <Event TimeStamp="2014-10-31 14:17:40" DiscoveredAt="2014-11-01 12:05:28" Source="Event Log" EventInfo="Outage detected from Interval Data.">
               </Event>
               <Event TimeStamp="2014-10-31 14:16:20" DiscoveredAt="2014-11-01 12:05:28" Source="Event Log" EventInfo="Outage detected from Interval Data.">
               </Event>
               <Event TimeStamp="2014-10-31 14:16:16" DiscoveredAt="2014-11-01 12:05:28" Source="Event Log" EventInfo="Outage detected from Interval Data.">
               </Event>
               <Event TimeStamp="2014-10-31 14:15:12" DiscoveredAt="2014-11-01 12:05:28" Source="Event Log" EventInfo="Outage detected from Interval Data.">
               </Event>
               <Event TimeStamp="2014-10-31 14:12:00" DiscoveredAt="2014-11-01 12:05:28" Source="Event Log" EventInfo="Outage detected from Interval Data">
               </Event>
           </EventData>
      </MeterReadings>'
    

    我们可以用不同的方式处理记录:

    library(xml2)
    library(purrr)
    library(dplyr)
    
    doc <- read_xml(txt)
    
    xml_find_all(doc, "//MeterReadings") %>%
      map_df(function(x) {
        meter <- xml_attr(x, "Irn")
        xml_find_all(x, "//Event[contains(@EventInfo, 'Outage')]") %>% 
          map_df(function(y) {
            data_frame(
              meter=meter,
              timestamp=xml_attr(y, "TimeStamp"),
              discovered_at=xml_attr(y, "DiscoveredAt")
            )
          })
      })
    

    生成:

    ## # A tibble: 5 × 3
    ##   meter           timestamp       discovered_at
    ##   <chr>               <chr>               <chr>
    ## 1   311 2014-10-31 14:17:40 2014-11-01 12:05:28
    ## 2   311 2014-10-31 14:16:20 2014-11-01 12:05:28
    ## 3   311 2014-10-31 14:16:16 2014-11-01 12:05:28
    ## 4   311 2014-10-31 14:15:12 2014-11-01 12:05:28
    ## 5   311 2014-10-31 14:12:00 2014-11-01 12:05:28
    

    【讨论】:

    • 太棒了!我做了一些调整,因为它正在拉动所有仪表并包括每个仪表的所有时间戳。修改方案如下:
    【解决方案2】:

    修改后的答案以过滤计量器和时间戳,使其不会重复所有计量器的所有时间戳:

    outage.df <- xml_find_all(doc, "//MeterReadings[EventData/Event[contains(@EventInfo, 'Outage')]]") %>%
    map_df(function(x) {
      meter <- xml_attr(x, "Irn")
      xml_find_all(x, paste("//MeterReadings[@Irn=",meter,"]/EventData/Event[contains(@EventInfo, 'Outage')]")) %>% 
        map_df(function(y) {
          data_frame(
            meter=meter,
            timestamp=xml_attr(y, "TimeStamp"),
            discovered_at=xml_attr(y, "DiscoveredAt")
          )
        })
    })
    

    【讨论】:

      猜你喜欢
      • 2022-11-23
      • 1970-01-01
      • 1970-01-01
      • 2015-11-02
      • 2020-06-10
      • 1970-01-01
      • 2015-01-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多