【发布时间】:2015-11-07 02:03:06
【问题描述】:
我对使用 R 相当陌生,对使用 XML 包和 xpath 也很陌生。我需要从一个看起来像这样的 xml 文件中提取四个元素(除了我已经修剪掉了很多其他 xmlnodes 来简化它):
<?xml version="1.0" encoding="utf-8"?>
<iati-activities version="1.03" generated-datetime="2015-07-07T16:49:09+00:00">
<iati-activity last-updated-datetime="2014-08-11T14:36:59+00:00" xml:lang="en" default-currency="EUR">
<iati-identifier>NL-KVK-41160054-100530</iati-identifier>
<title>Improvement of basic health care</title>
<reporting-org ref="NL-KVK-41160054" type="21">Stichting Cordaid</reporting-org>
<participating-org role="Accountable" ref="NL-KVK-41160054" type="21">Cordaid</participating-org>
<participating-org role="Funding" ref="EU" type="15">EU</participating-org>
<participating-org role="Funding" type="21">Cordaid Memisa</participating-org>
<participating-org role="Funding" ref="NL-1" type="10">Dutch Ministry of Foreign Affairs</participating-org>
<participating-org role="Implementing" type="21">CORDAID RCA</participating-org>
<recipient-country percentage="100" code="CF">CENTRAL AFRICAN REPUBLIC</recipient-country>
<budget type="1">
<period-start iso-date="2010-01-01"></period-start>
<period-end iso-date="2013-02-28"></period-end>
</budget>
</iati-activity>
<iati-activity last-updated-datetime="2013-07-19T14:12:14+00:00" xml:lang="en" default-currency="EUR">
<iati-identifier>NL-KVK-41160054-100625</iati-identifier>
<title>Pigs for Pencils</title>
<reporting-org ref="NL-KVK-41160054" type="21">Stichting Cordaid</reporting-org>
<participating-org role="Funding" ref="NL-1" type="10">Dutch Ministry of Foreign Affairs</participating-org>
<participating-org role="Funding" type="60">Stichting Kapatiran</participating-org>
<participating-org role="Implementing" type="22">PREDA Foundation Inc.</participating-org>
<participating-org role="Accountable" ref="NL-KVK-41160054" type="21">Cordaid</participating-org>
<budget type="2">
<period-start iso-date="2010-04-20"></period-start>
<period-end iso-date="2012-10-02"></period-end>
<value value-date="2010-04-20">12500</value>
</budget>
</iati-activity>
<iati-activity last-updated-datetime="2015-04-08T03:01:58+00:00" xml:lang="en" default-currency="EUR">
<iati-identifier>NL-KVK-41160054-100815</iati-identifier>
<title>Job and housing opportunities for women </title>
<reporting-org ref="NL-KVK-41160054" type="21">Stichting Cordaid</reporting-org>
<participating-org role="Funding" ref="NL-1" type="10">Dutch Ministry of Foreign Affairs</participating-org>
<participating-org role="Implementing" type="22">WISE</participating-org>
<participating-org role="Accountable" ref="NL-KVK-41160054" type="21">Cordaid</participating-org>
<budget type="2">
<period-start iso-date="2010-10-01"></period-start>
<period-end iso-date="2011-12-31"></period-end>
<value value-date="2010-10-01">227000</value>
</budget>
</iati-activity>
</iati-activities>
这也是我在 StackOverflow 上的第一个问题,所以如果我做得不对(并且 xml 没有完全对齐),请道歉。 我需要的元素,以及我分配给它们的元素是:
UniqueID <- "//iati-activity/iati-identifier"
GrantTitle <- "//iati-activity/title"
GrantAmount <- "//iati-activity/budget/value"
Recipient <- "//iati-activity/participatingorg[@role='Implementing']"
到目前为止(经过多次试验和磨难)我已经想出了这段代码,它通过当前节点(x),拉出 4 个变量,并将它们绑定成一行,然后使用 xpathApply 循环通过 iati-活动节点调用函数并将结果行绑定在一起。
当所有四个元素都存在于每个活动中时,此代码有效。但是,请注意 xml 示例中没有预算/价值节点。这是因为我删除它是为了解决缺少节点的问题,对于我需要的几乎所有元素,它在完整文件中经常出现。
还要注意我的 xpath 表达式末尾的 [1] - 我已经包含这些是因为还有多个标题、所有类型的多个参与组织等。
鉴于某些元素的倍数而其他元素不存在,因此不可能简单地将所有相同的元素拉入一个向量并将其弹出到数据框中。因此需要循环通过每个活动来拉动元素。我的代码目前无法解决缺少的元素(第一个 iati 活动中缺少的预算/值),因为 cbinding(和 rbinding)忽略了空向量。
xmltestNA = xmlInternalTreeParse("XMLtoDF_TestNA.xml", useInternalNodes=TRUE)
bodyToDF <- function(x){
UniqueID <- xpathSApply(x, "./iati-identifier", xmlValue)
GrantTitle <- xpathSApply(x, "./title[1]", xmlValue)
GrantAmount <- xpathSApply(x, "./budget/value[1]", xmlValue)
Recipient <- xpathSApply(x, "./participating-org[@role='Implementing'][1]", xmlValue)
cbind(UniqueID=UniqueID, GrantTitle=GrantTitle, GrantAmount=GrantAmount, Recipient=Recipient)
}
res <-xpathApply(xmltestNA, '//iati-activity', fun=bodyToDF)
IatiNA <-do.call(rbind, res)
IatiNA
如何保留空值/缺失节点,以便将其转换为如下所示的矩阵或数据框:
UniqueID GrantTitle GrantAmount Recipient
1 NL-KVK-41160054-100530 Improvement of basic health care NA CORDAID RCA
2 NL-KVK-41160054-100625 Pigs for Pencils 12500 PREDA Foundation Inc.
3 NL-KVK-41160054-100815 Job and housing opportunities for women 227000 WISE
因为我还是新手,代码越简单越好。提前致谢!
【问题讨论】:
标签: xml r xpath xml-parsing