R -XML数据提取,并非所有父节点都包含子节点



我有一个XML数据文件,在该文件中用户打开了一个帐户,在某些情况下,该帐户已终止。当未终止帐户时,数据不会列出该值,这使得很难提取信息。

这是可重复的示例(其中只有用户1和3才终止帐户):

library(XML)
my_xml <- xmlParse('<accounts>
                    <user>
                      <id>1</id>
                      <start>2015-01-01</start>
                      <termination>2015-01-21</termination>
                    </user>
                    <user>
                      <id>2</id>
                      <start>2015-01-01</start>
                    </user>
                    <user>
                      <id>3</id>
                      <start>2015-02-01</start>
                      <termination>2015-04-21</termination>
                    </user>
                    <user>
                      <id>4</id>
                      <start>2015-03-01</start>
                    </user>
                    <user>
                      <id>5</id>
                      <start>2015-04-01</start>
                    </user>
                    </accounts>')

要创建一个data.frame,我尝试使用sapply,但是由于用户没有终止值,该代码不会返回NA,因此代码会产生error: arguments imply differing number of rows: 5, 2

accounts <- data.frame(id=sapply(my_xml["//user//id"], xmlValue),
                       start=sapply(my_xml["//user//start"], xmlValue),
                       termination=sapply(my_xml["//user//termination"], xmlValue)
                       )

关于如何解决此问题的任何建议?

我更喜欢在XML软件包上使用XML2软件包,我发现语法易于使用。
这是一个直接的问题。查找所有用户节点,然后解析ID和终止节点。使用XML2,即使找不到节点,xml_find_first函数也会返回Na。

library(xml2)
my_xml <- read_xml('<accounts>
                   <user>
                   <id>1</id>
                   <start>2015-01-01</start>
                   <termination>2015-01-21</termination>
                   </user>
                   <user>
                   <id>2</id>
                   <start>2015-01-01</start>
                   </user>
                   <user>
                   <id>3</id>
                   <start>2015-02-01</start>
                   <termination>2015-04-21</termination>
                   </user>
                   <user>
                   <id>4</id>
                   <start>2015-03-01</start>
                   </user>
                   <user>
                   <id>5</id>
                   <start>2015-04-01</start>
                   </user>
                   </accounts>')
usernodes<-xml_find_all(my_xml, ".//user")
  ids<-xml_text(xml_find_first(usernodes, ".//id") )
  terms<-xml_text(xml_find_first(usernodes, ".//termination"))
answer<-data.frame(ids, terms)

我设法找到了xpath中的xpath:返回na的解决方案,如果na缺少

accounts <- data.frame(id=sapply(my_xml["//user//id"], xmlValue),
                       start=sapply(my_xml["//user//start"], xmlValue),
                       termination=sapply(xpathApply(my_xml, "//user",
                                                     function(x){
                                                     if("termination" %in% names(x))
                                                     xmlValue(x[["termination"]])
                                                     else NA}), function(x) x))

最新更新