使用xml2

问题描述

假设我具有以下XML:

library(xml2)

x = xml_children(read_xml('<?xml version="1.0" encoding="UTF-8"?>
  <items>
    <item type="greeting" id="9273938">
      <link type="1" id="139" value="Hi"/>
      <link type="1" id="142" value="Hello"/>
      <link type="1" id="130" value="Ahoy"/>
    </item>
    <item type="greeting" id="9225694">
      <link type="1" id="138" value="Bye"/>
      <link type="1" id="131" value="Adios"/>
    </item>
  </items>'))

我可以遍历它以访问各个<link>节点中的<item>个节点。

lapply(x,xml_find_all,xpath = "link")

这将产生一个单独的节点集的列表,这使我可以知道“链接”的哪个集合属于哪个“项目”。但是,在冗长的节点集(例如数千个<item>节点)上循环会很慢。

相比之下,以下内容几乎是即时的(我认为更接近应如何使用xml2的精神),但我不再知道链接来自哪个项目。他们似乎都是兄弟姐妹:

xml_find_all(x,xpath = "link")

问题:如何提取<link>个节点而不会丢失有关它们来自的<item>的信息,从而避免上述不受欢迎的解决方案?

解决方法

对于每个link节点,您可以通过/parent::item获取有关父项的信息:​​

library(xml2)

x <- read_xml('<?xml version="1.0" encoding="UTF-8"?>
  <items>
    <item type="greeting" id="9273938">
      <link type="1" id="139" value="Hi"/>
      <link type="1" id="142" value="Hello"/>
      <link type="1" id="130" value="Ahoy"/>
    </item>
    <item type="greeting" id="9225694">
      <link type="1" id="138" value="Bye"/>
      <link type="1" id="131" value="Adios"/>
    </item>
  </items>')
links <- x %>% xml_find_all("//link")
data.frame(
  item_id = links %>% xml_find_first("./parent::item") %>% xml_attr("id"),# notice the dot refers to the current link node
  link_id = links %>% xml_attr("id"),value = links %>% xml_attr("value")
)