在R中读取数据-XML

因为要读取一个XML格式的数据,学习整理XML包。

1.XML包

1.1. 载入XML文件

有两种方法:

    1. 通过函数xmlTreeParse(“file.xml”)载入xml文件,如果不加入参数,将获得关于这个xml文件的所有信息。所以,这个函数通常配合xmlRoot()使用,比如xmlRoot(xmlTreeParse(“file.xml”))以得到xml主体文件。
    1. 通过函数xmlTreeParse(“file.xml”, useInternalNodes = TRUE)来得到加入首行的xml文件主体
library(RCurl)
library(XML)
url<-"http://www.w3school.com.cn/example/xdom/books.xml"  #注,也可以为url复制本地文件的路径
doc<-xmlTreeParse(getURL(url),useInternal = TRUE)
d <- xmlRoot(doc)

1.2. 获取特定的节点

详细XPath语言见XPath 语法

使用函数getNodeSet(doc, XPath)

XPath的常见用法:

  1. 获取第一个son元素

/root/son[1]

getNodeSet(d, "/bookstore/book[1]")
  1. 获取最后一个son元素

/root/son[last()]

getNodeSet(d, "/bookstore/book[last()]")
  1. 获取前两个son元素

/root/son[position() < 3]

getNodeSet(d, "/bookstore/book[position() < 3]")
  1. 获取任意son2元素

//son2

getNodeSet(d, "/bookstore/book")
getNodeSet(d, "/bookstore/book/title")
  1. 获取任意son2的age属性

//son2[@age]

getNodeSet(d, "//book[@category]")
  1. 获取任意son2的age属性等于18的元素

//son2[@age=18]

getNodeSet(d, "//book[@category='web']")
  1. 获取root下所有元素

/root/*

getNodeSet(d, "/bookstore/*")
  1. 获取所有带属性的son元素

//son[@*]

getNodeSet(d, "//book[@*]")

节点相关函数

  • class(xmltop) #查看类
  • xmlName(node):查看根目录名。 node[[1]]:查看第一个子目录 node[[1]][[2]]:查看第一个子目录的第二个节点
  • xmlSize(node):该节点下字节点数量。
  • xmlAttrs(node):该节点属性。
  • xmlGetAttr(node, attr):该节点某一属性。
  • xmlValue(node):该节点值。
  • xmlChildren(node):该节点下的子节点。
class(d)
xmlName(d)
xmlSize(d)
xmlAttrs(d)
xmlAttrs(d[[1]])
xmlAttrs(d[[1]][[1]])
xmlGetAttr(d[[1]][[1]], "lang")
xmlChildren(d[[1]])

#通过以下方式获得的节点类型不同,建议使用getNodeSet
d[[1]][[1]]
getNodeSet(d, "//book/title")[[1]]
getNodeSet(d, "//book[1]/title")

1.3 xmlSApply和xmlApply

  1. 读取节点的值
#读取第一本书的"title"的值
d[[1]][[1]][[1]]
xmlValue(d[[1]][[1]])
xpathSApply(d, "/bookstore/book[1]/title", xmlValue)
xpathSApply(d, "//book[1]/title", xmlValue)

xpathSApply(d, "//book/title", xmlValue)

xpathSApply(d, "//book[1]/title", xmlName)
xpathSApply(d, "//book[1]/title", xmlSize)
xpathSApply(d, "//book[1]/title", xmlAttrs)

#xpathSApply和xpathApply的区别:
#xpathSApply是xpathApply读取值的一个因子
xpathApply(d, "//book[1]/title", xmlName)
xpathApply(d, "//book[1]/title", xmlSize)
xpathApply(d, "//book[1]/title", xmlAttrs)
  1. 读取节点的属性值
xmlGetAttr(d[[1]][[1]], "lang")

title<-getNodeSet(d, "//book[1]/title")
title_lang<-sapply(title, xmlGetAttr, "lang")
sapply(xmlChildren(d), xmlGetAttr, "category")

#也可以通过该方法读取节点的值
title_value<-sapply(title, xmlValue)
sapply(xmlChildren(d[["book"]]), xmlValue)

1.4 xml格式转dataframe

book <- getNodeSet(d, "//book")
mybook <- sapply(book,xmlValue)

#第一种方式,直接用xmlToDataFrame()函数
xmlToDataFrame(d)
#由于book[4]不规范,导致转化失败
xmlToDataFrame(xmlChildren(d)[["book"]])
xmlToDataFrame(getNodeSet(d, "//book[1]"))
xmlToDataFrame(nodes = getNodeSet(d, "//book/title"))

#第二种方式,数据格式处理专用包plyr
library("plyr")
#先转成list,再转dataframe
MyBooks <- ldply(xmlToList(d), data.frame)
MyBooks <- ldply(xmlToList(getNodeSet(d, "//book")), data.frame)

#第三种方式,读取单个值后组合为dataframe
author <- xpathSApply(d, "//book/author", xmlValue)
#对第四个book的author值做特殊处理
author4 <- xpathSApply(d, "//book[4]/author", xmlValue)
author4 <- paste(author4, collapse = ", ")
author <- c(author[1:3],author4)
MyBooks <- data.frame(
    category=sapply(xmlChildren(d), xmlGetAttr, "category"),
    title=xpathSApply(d, "//book/title", xmlValue),
    author,
    year=xpathSApply(d, "//book/year", xmlValue),
    price=xpathSApply(d, "//book/price", xmlValue))
Avatar
Jeevan Yue
Data Analyst

Related