xml到R数据帧,多层子节点

时间:2017-07-11 16:59:01

标签: r xml xml-parsing

我试图使用XML包将xml转换为r df。能够成功获得一个df,但每当有一个孩子的孙子孙女时,孙子孙女的价值就被合并成一列。

以下是xml的外观:

<user>
    <created-at type="datetime">2012-12-20T18:32:20+00:00</created-at>
    <details></details>
    <is-active type="boolean">true</is-active>
    <last-login type="datetime">2017-06-22T16:52:11+01:00</last-login>
    <time-zone>Pacific Time (US &amp; Canada)</time-zone>
    <updated-at type="datetime">2017-06-22T21:00:47+01:00</updated-at>
    <is-verified type="boolean">true</is-verified>
    <groups type="array">
        <group>
            <created-at type="datetime">2015-02-09T09:34:41+00:00</created-at>
            <id type="integer">23215935</id>
            <is-active type="boolean">true</is-active>
            <name>Product Managers</name>
            <updated-at type="datetime">2015-02-09T09:34:41+00:00</updated-at>
        </group>
    </groups>
</user>

我使用的代码是:

users_xml = xmlTreeParse("users.xml")

top_users = xmlRoot(users_xml)

users = xmlSApply(top_users, function(x) xmlSApply(x, xmlValue))

我得到的结果除了将“组”下的所有内容组合成一列之外,其他所有元素都很好。无论如何,我可以将“group”下的每个元素作为最终数据框中的单独列吗?

我也试过

nodes=getNodeSet(top_users, "//groups[@group]")

nodes=getNodeSet(top_users, "//groups/group[@group]")

nodes=getNodeSet(top_users, "//.groups/group[@group]")

并将“top_users”切换为“user_xml”,但每次都收到错误消息:

Error: 1: Input is not proper UTF-8, indicate encoding !
Bytes: 0xC2 0x3C 0x2F 0x6E

然后尝试了

data.frame(t(xpathSApply(xmlRoot(xmlTreeParse("users.xml", useInternalNodes = T)),
                    "//user", function(y) xmlSApply(y, xmlValue))))

这给了我与第一个解决方案完全相同的东西。

最后,我尝试了

data.frame(t(xpathSApply(xmlRoot(xmlTreeParse("users.xml", useInternalNodes = T)),
                    "//user/groups/group", function(y) xmlSApply(y, xmlValue))))

哪个确实给了我一个数据帧但只包含“group”中的元素,并且我无法将它映射回我得到的第一个包含“user”中所有元素的表。

1 个答案:

答案 0 :(得分:0)

考虑与{em>用户子女和群组子女xmlToDataFrame()的列绑定:

userdf <- xmlToDataFrame(nodes=getNodeSet(doc, "/user"))
groupdf <- xmlToDataFrame(nodes=getNodeSet(doc, "/user/groups/group"))

df <- transform(cbind(userdf, groupdf), groups = NULL)   # REMOVE groups COL

df
#                  created.at details is.active                last.login                  time.zone
# 1 2012-12-20T18:32:20+00:00              true 2017-06-22T16:52:11+01:00 Pacific Time (US & Canada)
#                  updated.at is.verified              created.at.1       id is.active.1             name
# 1 2017-06-22T21:00:47+01:00        true 2015-02-09T09:34:41+00:00 23215935        true Product Managers
#                updated.at.1
# 1 2015-02-09T09:34:41+00:00