【问题标题】:In R how do I pair XML node values from common parent nodes?在 R 中,如何配对来自公共父节点的 XML 节点值?
【发布时间】:2017-01-18 21:57:20
【问题描述】:

我有以下示例 XML:

<body>
  <div class="row">
    <div class="column">
      <span class="title">Color</span>
    </div>
    <div class="column property">Blue</div>
  </div> 
  <div class="row">
    <div class="column">
      <span class="title">Shape</span>
    </div>
    <div class="column property">Square</div>
  </div> 
</body>

如何使用 R 将每个标题与其属性和输出配对:

Color = Blue
Shape = Square

我尝试了以下脚本,但标题周围有 XML 标记并且缺少属性:

library(XML)

getDetails <- function(id) {
  html <- htmlTreeParse( "exampleXML.html" ,useInternal = TRUE)
  xpathSApply( html , "//div[@class='row']" , function(row) { 
    print( xmlElementsByTagName(row, "span", recursive = TRUE) )
  })
}

getDetails()

也没有运气:

library(XML)      #to install use: install.packages("XML")
library(xml2)     #to install use: install.packages("xml2")
library(magrittr) #to install use: install.packages("magrittr")

extract_info <- function(x){
   title <- x %>% xml_find_first(".//span[@class='title']") %>% xml_text
   property <- x %>% xml_find_first(".//div[@class='column property']") %>% xml_text
   setNames(property, title)
 }

html <- htmlTreeParse( "exampleXML.html" ,useInternal = TRUE)
html %>% xml_find_all("//div[@class='row']") %>% extract_info

UseMethod("xml_find_all") 中的错误: 'xml_find_all' 没有适用于类“c('HTMLInternalDocument', 'HTMLInternalDocument', 'XMLInternalDocument', 'XMLAbstractDocument')”的对象的适用方法

【问题讨论】:

    标签: r xml xml-parsing


    【解决方案1】:

    考虑使用嵌套的xpathSApply(),其中外循环遍历rows 以解析每行的titleproperty 的对应值: p>

    library(XML)
    
    example_html <- paste0('<body>',
                       '  <div class="row">',
                       '    <div class="column">',
                       '       <span class="title">Color</span>',
                       '    </div>',
                       '    <div class="column property">Blue</div>',
                       '  </div>',
                       '  <div class="row">',
                       '    <div class="column">',
                       '       <span class="title">Shape</span>',
                       '    </div>',
                       '    <div class="column property">Square</div>',
                       '  </div>', 
                       '</body>')
    
    doc <- htmlTreeParse(example_html, useInternal = TRUE)
    
    columns <- xpathSApply(doc, "//div[@class='row']", function(row){
       title <- xpathSApply(row, "div[@class='column']/span", xmlValue)
       property <- xpathSApply(row, "div[@class='column property']", xmlValue)
       setNames(gsub(" ", "", property), gsub(" ", "", title))    # GSUB TO STRIP WHITESPACE
    })
    
    columns <- setNames(property, title)
    columns
    #  Color    Shape 
    #  "Blue" "Square" 
    

    或者,假设 rows 中的严格一致性而没有丢失子元素或 titleproperty 值的多个相同命名元素,请考虑几个xpathSApply() 来电:

    title <- xpathSApply(doc, "//div[@class='column']/span", xmlValue)
    property <- xpathSApply(doc, "//div[@class='column property']", xmlValue)
    
    columns <- setNames(property, title)
    columns
    #   Color    Shape 
    #  "Blue" "Square" 
    

    【讨论】:

      【解决方案2】:

      使用xml2,您可以执行以下操作:

      library(xml2)     #to install use: install.packages("xml2")
      library(magrittr) #to install use: install.packages("magrittr")
      
      extract_info <- function(x){
        title <- x %>% xml_find_first(".//span[@class='title']") %>% xml_text
        property <- x %>% xml_find_first(".//div[@class='column property']") %>% xml_text
        setNames(property, title)
      }
      
      html <- read_xml( "exampleXML.html" )
      html %>% xml_find_all("//div[@class='row']") %>% extract_info
      

      它为您提供以下命名向量:

         Color    Shape 
        "Blue" "Square"
      

      【讨论】:

      • 我收到了Error: could not find function "%&gt;%"。我尝试从 RStudio > 工具 > 安装包... > xml2 安装包。还在脚本的开头添加了library(xml2)。没有运气。
      • 我在我的问题中添加了“也没有运气:”部分。你能看看它并可能更新你的答案吗?
      • 你自己想通了。对不起,半完整的答案。诀窍是通过read_xml 读取文件,并且(与rvest 不同,xml2 的包装更方便)xml2 默认不导入magrittr::%&gt;%
      【解决方案3】:

      如果您的 XML 格式正确(即元素的顺序没有改变),那么您可以这样做:

      library(xml2)
      library(purrr)
      
      doc <- read_xml(txt)
      
      vals <- xml_text(xml_find_all(doc, ".//*[@class='title' or @class='column property']"))
      map_chr(seq(1, length(vals), by=2), ~sprintf("%s = %s", vals[.], vals[.+1])) %>% 
        cat(sep="\n")
      

      也是。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多