【问题标题】:Parsing XML in R: Incorrect namespaces在 R 中解析 XML:不正确的命名空间
【发布时间】:2015-03-20 15:27:50
【问题描述】:

我有一堆 XML 文件和一个将它们的内容读入数据框的 R 脚本。然而,我现在得到了我想像往常一样解析的文件,但是它们的命名空间定义中有一些东西不允许我使用 XPath 表达式正常选择它们的值。

XML 文件是这样的:

xml_nons.xml

<?xml version="1.0" encoding="UTF-8"?>
<XML>
   <Node>
      <Name>Name 1</Name>
      <Title>Title 1</Title>
      <Date>2015</Date>
   </Node>
</XML>

还有一个:

xml_ns.xml

<?xml version="1.0" encoding="UTF-8"?>
<XML xmlns="http://www.nonexistingsite.com">
   <Node>
      <Name>Name 2</Name>
      <Title>Title 2</Title>
      <Date>2014</Date>
   </Node>
</XML>

xmlns 指向的 URL 不存在。

我使用的R代码是这样的:

library(XML)

xmlfiles <- list.files(path = ".", 
                       pattern="*.xml$", 
                       full.names = TRUE, 
                       recursive = TRUE)

n <- length(xmlfiles)
dat <- vector("list", n)

for(i in 1:n){
       doc <- xmlTreeParse(xmlfiles[i], useInternalNodes = TRUE)
       nodes <- getNodeSet(doc, "//XML")
       x <- lapply(nodes, function(x){ data.frame(
              Filename = xmlfiles[i],
              Name = xpathSApply(x, ".//Node/Name" , xmlValue),
              Title = xpathSApply(x, ".//Node/Title" , xmlValue),
              Date = xpathSApply(x, ".//Node/Date" , xmlValue)
            )})
            dat[[i]] <- do.call("rbind", x)
    }

    xml <- do.call("rbind", dat)
    xml

但是,我得到的结果是:

Filename            Name    Title    Date
./xml_nons.xml      Name 1  Title 1  2015

如果我从第二个文件中删除命名空间链接,我会得到正确的:

Filename            Name    Title    Date
./xml_nons_1.xml    Name 1  Title 1  2015
./xml_ns_1.xml      Name 2  Title 2  2014

当然,我可以有一个 XSL 来从原始 XML 文件中删除这些命名空间,但我希望有一些在 R 中工作的解决方案。有什么方法可以告诉 R 忽略 XML 声明中的所有内容吗?

【问题讨论】:

    标签: r xml xml-namespaces xml2


    【解决方案1】:

    我认为没有简单的方法可以忽略命名空间。最好的方法是学会和他们一起生活。这个答案将使用较新的 XML2 包。但同样适用于 XML 包解决方案。

    使用

    library(XML2)
    fname='myfile.xml'
    doc <- read_xml(fname)
    #peak at the namespaces
    xml_ns(doc)
    

    第一个命名空间分配给 d1。如果 XPath 没有找到您想要的,最可能的原因是命名空间问题。

    xpath <-  "//d1:FormDef"
    ns <- xml_find_all(doc,xpath, xml_ns(doc))
    ns
    

    此外,您必须对路径中的每个元素执行此操作 所以为了节省打字,你可以这样做

    library(stringr)
    > xpath <-  "/ODM/Study"
    > (xpath<-str_replace_all(xpath,'/','/d1:'))
    [1] "/d1:ODM/d1:Study"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-17
      • 2017-02-03
      • 2021-05-03
      相关资源
      最近更新 更多