在 R 中解析 XML:命名空间不正确
Parsing XML in R: Incorrect namespaces
我有一堆 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
如果我从第二个文件中删除命名空间 link,我会得到正确的结果:
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 声明?
我认为没有简单的方法可以忽略命名空间。最好的方法是学会和他们一起生活。这个答案将使用更新的 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"
我有一堆 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
如果我从第二个文件中删除命名空间 link,我会得到正确的结果:
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 声明?
我认为没有简单的方法可以忽略命名空间。最好的方法是学会和他们一起生活。这个答案将使用更新的 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"