【问题标题】:Extracting specific internal nodes from an xml file and construct a dataframe in r从 xml 文件中提取特定的内部节点并在 r 中构造数据框
【发布时间】:2016-05-12 00:14:39
【问题描述】:

我有一个 xml 文件,我想使用 xmlToDataFrame 包中的 xmlToDataFrame 从 R 中提取特定节点。我可以获得从各个节点提取数据的功能。例如:

xml <- xmlParse("file.xml")

df <- xmlToDataFrame(getNodeSet(xml, "//lat"))

但是我想知道是否可以同时提取多个节点?具体来说,我希望从 xml 中创建一个从节点中提取数据的五列数据框://nucleotides,//lat,//lon,//bin_uri,//record_id

xml文件的结构如下(record_id只有一个,但文件中有很多我需要提取):

    <record>
      <record_id>634750</record_id>
      <processid>CCSMA054-07</processid>
      <bin_uri>AAG2098</bin_uri>
      <collection_event>
        <collectors>Arctic Ecology</collectors>
          <coordinates>
            <lat>58.805</lat>
            <lon>-94.214</lon>
          </coordinates>
        <country>Canada</country>
        <province>Manitoba</province>
      </collection_event>
      <sequences>
       <sequence>
         <sequenceID>3336699</sequenceID>
         <markercode>COI-5P</markercode>
         <genbank_accession>HQ938393</genbank_accession>
         <nucleotides>CTCAGAGTTCTCACCTGGC</nucleotides>
       </sequence>
      </sequences>
    </record>

【问题讨论】:

  • 我收到一个错误:xmlToDataFrame 中的错误(getNodeSet(xml, ii)):在为函数 'xmlToDataFrame' 选择方法时评估参数 'doc' 时出错:UseMethod 中的错误("xpathApply ") : 没有适用于“函数”类对象的“xpathApply”方法
  • 感谢您的帮助,我收到另一个错误:UseMethod("xpathApply") 中的错误:没有适用于“函数”类对象的“xpathApply”方法
  • 我将发布我正在使用的 xml 数据文件的示例boldsystems.org/index.php/API_Public/…

标签: r xml-parsing


【解决方案1】:

考虑使用xpathSApply() 简单地运行各种xpath 表达式,然后将它们绑定到一个数据框中:

library(XML)

doc<-xmlParse("D:/Freelance Work/Scripts/BoldXML.xml")

record_id <- xpathSApply(doc, "//record/record_id", xmlValue)
bin_uri <- xpathSApply(doc, "//record/bin_uri", xmlValue)
lat <- xpathSApply(doc, "//record/collection_event/coordinates/lat", xmlValue)
lon <- xpathSApply(doc, "//record/collection_event/coordinates/lon", xmlValue)
nucleotides <- xpathSApply(doc, "//record/sequences/sequence/nucleotides", xmlValue)

df <- data.frame(record_id = unlist(record_id), 
                 bin_uri = unlist(bin_uri),                  
                 lat = unlist(lat),
                 lng = unlist(lon),
                 nucleotides = unlist(nucleotides))

或者,您可以使用XSLT 简化原始 XML,这是一种重组/重新设计 XML 文件的专用语言。虽然 R 没有通用 XSLT 包,但几乎所有通用语言(C#、Java、PHP、Perl、Python、VB)都维护 XSLT 库,您甚至可以使用 system() 从 R 调用脚本。更重要的是,Windows 的 PowerShell 和 Linux 的 Bash 等命令行程序可以运行 XSLT。

XSLT 脚本(另存为 .xsl 或 .xslt)

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>

  <xsl:template match="/">
    <root>
      <xsl:apply-templates select="*"/>
    </root>
  </xsl:template>  

  <xsl:template match="record">
    <xsl:copy>
      <xsl:copy-of select="record_id"/>
      <xsl:copy-of select="bin_uri"/>     
      <xsl:copy-of select="collection_event/coordinates/lat"/>
      <xsl:copy-of select="collection_event/coordinates/lon"/>
      <xsl:copy-of select="sequences/sequence/nucleotides"/>
    </xsl:copy>
  </xsl:template>

</xsl:transform>

XML (转换后)

<?xml version="1.0" encoding="utf-8"?>
<root>
  <record>
    <record_id>634750</record_id>
    <bin_uri>AAG2098</bin_uri>
    <lat>58.805</lat>
    <lon>-94.214</lon>
    <nucleotides>CTCAGAGTTCTCACCTGGC</nucleotides>
  </record>
</root>

R 脚本:

result <- system('..some command line call to an external script that 
                  parses original xml and above xslt script and transforms
                  former with the latter..', intern = TRUE)

doc <- xmlParse("C:/Path/To/Transformed/XML.xml")
df <- xmlToDataFrame(getNodeSet(doc, "//record"))

【讨论】:

  • 谢谢!我能够使用 xpathSApply() 的第一个选项使其工作。
  • 太棒了!请接受以确认解决方案。但要小心丢失 XML 值,因为列表长度可能不同并且无法与数据框列对齐。
  • xslt 解决方案对我也很有效。
【解决方案2】:

与上一个答案一样,带有 xpath 的getNodeSet 是另一种快速获取所需值的方法。如果每个 xpath 都有一个节点,您可以使用:

library(XML)

doc <- xmlParse("D:/Freelance Work/Scripts/BoldXML.xml")

record_id <- xmlValue(getNodeSet(doc, "//record/record_id"))
bin_uri   <- xmlValue(getNodeSet(doc, "//record/bin_uri"))
lat       <- xmlValue(getNodeSet(doc, "//record/collection_event/coordinates/lat"))
lon       <- xmlValue(getNodeSet(doc, "//record/collection_event/coordinates/lon"))
ntides    <- xmlValue(getNodeSet(doc, "//record/sequences/sequence/nucleotides"))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 2014-08-06
    • 2018-07-30
    • 2014-02-02
    • 1970-01-01
    • 2018-01-08
    相关资源
    最近更新 更多