【问题标题】:Storing XML node values with R's xmlEventParse for filtered output使用 R 的 xmlEventParse 存储 XML 节点值以进行过滤输出
【发布时间】:2013-05-16 14:54:38
【问题描述】:

我有一个巨大的 xml 文件 (260mb),其中包含大量信息,如下所示:

例子:

<mydocument>
<POSITIONS EventTime="2012-09-29T20:31:21" InternalMatchId="0000T0">
<FrameSet GameSection="1sthalf" Match="0000T0" Club="REFEREE" Object="00011D">
<Frame N="0" T="2012-09-29T18:31:21" X="-0.1158" Y="0.2347" S="1.27" />
<Frame N="1" T="2012-09-29T18:31:21" X="-0.1146" Y="0.2351" S="1.3" />
<Frame N="2" T="2012-09-29T18:31:21" X="-0.1134" Y="0.2356" S="1.33" />
</FrameSet>
<FrameSet GameSection="2ndhalf" Match="0000T0" Club="REFEREE" Object="00011D">
<Frame N="0" T="2012-09-29T18:31:21" X="-0.1158" Y="0.2347" S="1.27" />
<Frame N="1" T="2012-09-29T18:31:21.196" X="-0.1146" Y="0.2351" S="1.3" />
<Frame N="2" T="2012-09-29T18:31:21.243" X="-0.1134" Y="0.2356" S="1.33" />
</FrameSet>
</POSITIONS>
</mydocument>

大约有 40 个不同的 FrameSet 节点,每个节点都有不同的 GameSection="..."Object="..."

我很想将&lt;Frame&gt; 节点的信息提取到list 对象中,但我无法加载整个xml 文件,因为它太大了。有什么办法,我可以使用xmlEventParse 函数来过滤特定的GameSection 和特定的Object,并从相应的&lt;Frame&gt; 元素中获取所有信息?

【问题讨论】:

  • 你可以试试xpathApply。如果您需要更多帮助,您必须提供reproducible example
  • 我添加了文件的一些示例内容。要使用 xpathApply,我必须先加载 xml 文件,对吗?或者我可以在跑步时这样做吗?

标签: xml r xml-parsing


【解决方案1】:

可能是“内部”表示没有那么大

xml = xmlTreeParse("file.xml", useInternalNodes=TRUE)

然后 xpath 肯定是你最好的选择。如果这不起作用,您将需要考虑关闭。我的目标是xmlEventParsebranches 参数,它允许混合事件解析遍历文件,以及每个节点上的DOM 解析。这是一个返回函数列表的函数。

branchFactory <-
    function()
{
    env <- new.env(parent=emptyenv())   # safety

    FrameSet <- function(elt) {
        id <- paste(xmlAttrs(elt), collapse=":")
        env[[id]] <- xpathSApply(elt, "//Frame", xmlAttrs)
    }

    get <- function() env

    list(get=get, FrameSet=FrameSet)
}

在这个函数中,我们将创建一个地方来存储我们遍历文件时的结果。这可能是一个列表,但使用环境会更好。这将允许我们插入新结果,而无需复制我们已经插入的所有结果。这是我们的环境:

    env <- new.env(parent=emptyenv())

我们使用parent 参数作为安全措施,即使它与我们目前的情况无关。现在我们定义一个函数,每当遇到“FrameSet”节点时都会调用它

    FrameSet <- function(elt) {
        id <- paste(xmlAttrs(elt), collapse=":")
        env[[id]] <- xpathSApply(elt, "//Frame", xmlAttrs)
    }

事实证明,当我们使用branches 参数时,xmlEventParse 将安排将整个节点解析为我们可以通过 DOM 操作的对象,例如,使用 xlmAttrsxpathSApply .这个函数的第一行为这个框架集创建了一个唯一标识符(?也许整个数据集不是这样?你需要一个唯一标识符)。然后我们解析元素的“//Frame”部分,并将其存储在我们的环境中。存储结果比看起来要复杂——我们分配给一个名为env 的变量。 env 不存在于 FrameSet 函数的主体中,因此 R 使用其词法范围规则在 FrameSet 函数被定义的环境中搜索名为 env 的变量。瞧,它找到了我们已经创建的env。这是我们将xpathSApply 的结果添加到的地方。这就是我们的 FrameSet 节点解析器。

我们还想要一个方便的函数,可以用来检索env,如下所示:

    get <- function() env

同样,这将使用词法作用域来查找在branchFactory 顶部创建的env 变量。我们通过返回我们定义的函数列表来结束branchFactory

    list(get=get, FrameSet=FrameSet)

这也非常棘手——我们返回一个函数列表。这些函数是在我们调用branchFactory 时创建的环境中定义的,并且为了使词法范围起作用,环境必须保持不变。所以实际上我们不仅返回函数列表,而且隐含地返回变量env。简而言之

我们现在可以解析我们的文件了。通过创建分支解析器的实例来做到这一点,它具有自己独特的getFrameSet 函数版本以及为存储结果而创建的env 变量。然后解析文件

b <- branchFactory()
xx <- xmlEventParse("file.xml", handlers=list(), branches=b)

我们可以使用b$get() 检索结果,如果方便的话,可以将其转换为列表。

> as.list(b$get())
$`1sthalf:0000T0:REFEREE:00011D`
  [,1]                  [,2]                  [,3]                 
N "0"                   "1"                   "2"                  
T "2012-09-29T18:31:21" "2012-09-29T18:31:21" "2012-09-29T18:31:21"
X "-0.1158"             "-0.1146"             "-0.1134"            
Y "0.2347"              "0.2351"              "0.2356"             
S "1.27"                "1.3"                 "1.33"               

$`2ndhalf:0000T0:REFEREE:00011D`
  [,1]                  [,2]                      [,3]                     
N "0"                   "1"                       "2"                      
T "2012-09-29T18:31:21" "2012-09-29T18:31:21.196" "2012-09-29T18:31:21.243"
X "-0.1158"             "-0.1146"                 "-0.1134"                
Y "0.2347"              "0.2351"                  "0.2356"                 
S "1.27"                "1.3"                     "1.33"                   

【讨论】:

    猜你喜欢
    • 2011-11-24
    • 1970-01-01
    • 2018-02-21
    • 2013-10-07
    • 2018-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多