You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R中解析XML文件的datetime属性并存入数据框?

问题描述

我在用R语言解析XML文件时,已经成功提取到了<CumulativeOperatingHours>节点下的<Hour>值(比如1059.60),但一直没法获取该节点的datetime属性值(比如"2016-12-15T22:45:40.000Z")。希望能把这个datetime属性解析出来并存入数据框,我的相关代码和XML示例如下:

我的R代码:

xmldataframe <- xmlToDataFrame("xamal.xml")
xmlfile <- xmlParse("xamal.xml")
rootnode <- xmlRoot(xmlfile)
rootsize <- xmlSize(rootnode)
print(rootsize)
# [1] 103
print(rootnode[[11]][[5]])
# <CumulativeOperatingHours datetime="2016-12-15T22:45:40.000Z">
#   <Hour>1059.60</Hour>
# </CumulativeOperatingHours>

XML文件示例:

<?xml version="1.0" encoding="UTF-8"?>
<Group xmlns="http://standards.is.com/is/151/-1" version="2" Time="2018-05-30T19:33:44.352Z">
  <Links>
    <rel>self</rel>
    <href>https://cloud.com/1</href>
  </Links>
  <Links>
    <rel>last</rel>
    <href>https://cloud.com/2</href>
  </Links>
  <Links>
    <rel>next</rel>
    <href>https://cloud.com/3</href>
  </Links>
  <Equip>
    <EquipHead>
      <Name>CAST</Name>
      <Model>1100</Model>
      <EquipmentID>Desk</EquipmentID>
      <SerialNumber>12312312</SerialNumber>
      <PIN>123123</PIN>
    </EquipHead>
    <Location datetime="2012-06-25T11:14:54.000Z">
      <Latitude>44.57</Latitude>
      <Longitude>-95.51</Longitude>
    </Location>
    <OperatingHours datetime="2012-03-01T17:42:37.000Z">
      <Hour>198.80</Hour>
    </OperatingHours>
  </Equip>
  <Equip>
    <EquipHead>
      <Name>Yuza</Name>
      <Model>L208</Model>
      <EquipmentID>4DW772GP</EquipmentID>
      <SerialNumber>4DW772GP</SerialNumber>
      <PIN>1DW772GPVJF</PIN>
    </EquipHead>
    <Location datetime="2018-05-30T19:22:46.000Z">
      <Latitude>47.518556</Latitude>
      <Longitude>-70.422444</Longitude>
    </Location>
    <IdleHours datetime="2018-05-30T19:02:46.000Z">
      <Hour>33.74</Hour>
    </IdleHours>
    <OperatingHours datetime="2018-05-30T19:22:48.000Z">
      <Hour>72.35</Hour>
    </OperatingHours>
    <Distance datetime="2018-05-30T19:02:46.000Z">
      <Odometer>kilometre</Odometer>
      <OdometerV>30.9</OdometerV>
    </Distance>
    <FuelUsed datetime="2018-05-30T19:02:46.000Z">
      <FuelUnits>litre</FuelUnits>
      <Consumed>395</Consumed>
    </FuelUsed>
  </Equip>
  <Equip>
    <EquipHead>
      <OEMName>CALL</OEMName>
      <Model>562A</Model>
      <EquipmentID>1W2772G</EquipmentID>
      <SerialNumber>1TT772GPTE</SerialNumber>
      <PIN>1MM772GPTE</PIN>
    </EquipHead>
    <Location datetime="2018-05-30T07:00:17.000Z">
      <Latitude>22.809278</Latitude>
      <Longitude>-45.316417</Longitude>
    </Location>
    <IdleHours datetime="2018-05-24T20:37:03.000Z">
      <Hour>457.10</Hour>
    </IdleHours>
    <OperatingHours datetime="2018-05-30T18:25:18.000Z">
      <Hour>26.35</Hour>
    </OperatingHours>
    <Distance datetime="2018-05-23T13:26:37.000Z">
      <Units>kilometre</Units>
      <OdometerV>5075.6997</OdometerV>
    </Distance>
    <FuelUsed datetime="2018-05-24T20:37:03.000Z">
      <FuelUnits>litre</FuelUnits>
      <FuelConsumed>2548</FuelConsumed>
    </FuelUsed>
  </Equip>
</Group>
解决方案

首先要说明:xmlToDataFrame()默认只会提取节点的文本内容,不会处理节点的属性,所以你没法直接用它拿到datetime属性。我们可以用xmlParse()结合节点遍历或者XPath查询来解决这个问题,下面给你两种实用的方法:

方法一:遍历节点提取(适合复杂结构)

这种方法适合XML结构多变的情况,可以灵活处理每个节点的属性和子节点:

library(XML)

# 解析XML文件
xmlfile <- xmlParse("xamal.xml")
rootnode <- xmlRoot(xmlfile)

# 创建空数据框存储结果
result_df <- data.frame(
  EquipmentID = character(),
  DateTime = character(),
  Hour = numeric(),
  NodeType = character(),
  stringsAsFactors = FALSE
)

# 遍历所有Equip节点
for (i in 1:xmlSize(rootnode)) {
  current_node <- rootnode[[i]]
  # 只处理<Equip>节点
  if (xmlName(current_node) == "Equip") {
    # 获取设备ID
    equip_id <- xmlValue(current_node[["EquipHead"]][["EquipmentID"]])
    
    # 遍历Equip下的子节点,找带datetime属性的节点
    for (j in 1:xmlSize(current_node)) {
      child_node <- current_node[[j]]
      datetime_attr <- xmlAttrs(child_node)["datetime"]
      
      if (!is.null(datetime_attr)) {
        # 提取Hour值(如果节点下有<Hour>子节点)
        hour_val <- if (!is.null(child_node[["Hour"]])) {
          as.numeric(xmlValue(child_node[["Hour"]]))
        } else {
          NA  # 没有Hour节点就填NA
        }
        
        # 把数据添加到数据框
        result_df <- rbind(result_df, data.frame(
          EquipmentID = equip_id,
          DateTime = datetime_attr,
          Hour = hour_val,
          NodeType = xmlName(child_node),
          stringsAsFactors = FALSE
        ))
      }
    }
  }
}

# 查看结果
head(result_df)

方法二:XPath快速提取(适合目标明确)

如果你的目标只是提取<CumulativeOperatingHours>节点的datetime和<Hour>值,用XPath会更简洁高效。注意你的XML有命名空间(xmlns="http://standards.is.com/is/151/-1"),所以需要指定命名空间才能正确找到节点:

library(XML)

xmlfile <- xmlParse("xamal.xml")

# 定义XML的命名空间
ns <- c(is = "http://standards.is.com/is/151/-1")

# 提取所有CumulativeOperatingHours节点的datetime属性
datetime_vals <- xpathSApply(xmlfile, "//is:CumulativeOperatingHours", xmlAttrs, namespaces = ns)[1,]
# 提取对应的Hour值
hour_vals <- xpathSApply(xmlfile, "//is:CumulativeOperatingHours/is:Hour", xmlValue, namespaces = ns)
hour_vals <- as.numeric(hour_vals)

# 组合成数据框
cumulative_hours_df <- data.frame(
  DateTime = datetime_vals,
  Hour = hour_vals,
  stringsAsFactors = FALSE
)

# 查看结果
print(cumulative_hours_df)

关键说明

  • 命名空间处理:你的XML根节点带有xmlns属性,这意味着所有子节点都属于这个命名空间,所以用XPath查询时必须通过namespaces参数指定,否则会找不到目标节点。
  • 属性提取:xmlAttrs()函数可以获取节点的所有属性,通过下标["datetime"]就能拿到指定属性的值。

内容的提问来源于stack exchange,提问作者Alli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:49:47