微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

具有显式默认命名空间的XML文档的XPath和命名空间规范

我正在努力获得XPath表达式和命名空间规范的正确组合,如 XML(参数名称空间)所需,对于在顶部元素上定义了显式xmlns名称间的XML文档.

UPDATE

感谢har07,我能够把它放在一起:

查询名称空间后,ns的第一个条目还没有名称,这就是问题所在:

nsDefs <- xmlNamespaceDeFinitions(doc)
ns <- structure(sapply(nsDefs,function(x) x$uri),names = names(nsDefs))

> ns
                                             omegahat                          r 
    "http://something.org"  "http://www.omegahat.org" "http://www.r-project.org"

所以我们只需指定一个充当前缀的名称(这可以是任何有效的R名称):

names(ns)[1] <- "xmlns"

现在,我们所要做的就是在XPath表达式中的任何地方使用名称空间前缀:

getNodeSet(doc,"/xmlns:doc//xmlns:b[@omegahat:status='foo']",ns)

对于那些对基于name()和namespace-uri()(以及其他)的替代解决方案感兴趣的人可能会发现this post很有帮助.

仅仅是为了参考:在我们找到解决方案之前,这是试错代码

考虑一下?xmlParse中的示例:

require("XML")

doc <- xmlParse(system.file("exampleData","tagnames.xml",package = "XML"))

> doc
<?xml version="1.0"?>
<doc>
  <!-- A comment -->
  <a xmlns:omegahat="http://www.omegahat.org" xmlns:r="http://www.r-project.org">
    <b>
      <c>
        <b/>
      </c>
    </b>
    <b omegahat:status="foo">
      <r:d>
        <a status="xyz"/>
        <a/>
        <a status="1"/>
      </r:d>
    </b>
  </a>
</doc>
nsDefs <- xmlNamespaceDeFinitions(getNodeSet(doc,"/doc/a")[[1]])
ns <- structure(sapply(nsDefs,names = names(nsDefs))
getNodeSet(doc,"/doc//b[@omegahat:status='foo']",ns)[[1]]

但是,在我的文档中,名称空间已在< doc>中定义.标签,所以我相应地调整了示例XML代码

xml_source <- c(
  "<?xml version=\"1.0\"?>","<doc xmlns:omegahat=\"http://www.omegahat.org\" xmlns:r=\"http://www.r-project.org\">","<!-- A comment -->","<a>","<b>","<c>","<b/>","</c>","</b>","<b omegahat:status=\"foo\">","<r:d>","<a status=\"xyz\"/>","<a/>","<a status=\"1\"/>","</r:d>","</a>","</doc>"
)
write(xml_source,file="exampleData_2.xml")  
doc <- xmlParse("exampleData_2.xml")
nsDefs <- xmlNamespaceDeFinitions(doc)
ns <- structure(sapply(nsDefs,names = names(nsDefs))    
getNodeSet(doc,"/doc",namespaces = ns)
getNodeSet(doc,namespaces = ns)[[1]]

一切都还行.但更重要的是,我的XML代码还具有认命名空间(xmlns)的显式定义:

xml_source <- c(
  "<?xml version=\"1.0\"?>","<doc xmlns=\"http://something.org\" xmlns:omegahat=\"http://www.omegahat.org\" xmlns:r=\"http://www.r-project.org\">","</doc>"  
)
write(xml_source,file="exampleData_3.xml")  
doc <- xmlParse("exampleData_3.xml")
nsDefs <- xmlNamespaceDeFinitions(doc)
ns <- structure(sapply(nsDefs,names = names(nsDefs))

过去的工作现在失败了:

> getNodeSet(doc,namespaces = ns)
list()
attr(,"class")
[1] "XMLNodeSet"
Warning message:
using http://something.org as prefix for default namespace http://something.org 

> getNodeSet(doc,"/xmlns:doc",namespaces = ns)
XPath error : Undefined namespace prefix
XPath error : Invalid expression
Error in xpathApply.XMLInternalDocument(doc,path,fun,...,namespaces = namespaces,: 
  error evaluating xpath expression /xmlns:doc
In addition: Warning message:
using http://something.org as prefix for default namespace http://something.org 
getNodeSet(doc,namespaces = matchNamespaces(doc,namespaces="xmlns",nsDefs = nsDefs)
)

这似乎让我更接近:

> getNodeSet(doc,+ namespaces = matchNamespaces(doc,nsDefs = nsDefs)
+ )[[1]]
<doc xmlns="http://something.org" xmlns:omegahat="http://www.omegahat.org" xmlns:r="http://www.r-project.org">
  <!-- A comment -->
  <a>
    <b>
      <c>
        <b/>
      </c>
    </b>
    <b omegahat:status="foo">
      <r:d>
        <a status="xyz"/>
        <a/>
        <a status="1"/>
      </r:d>
    </b>
  </a>
</doc> 

attr(,"class")
[1] "XMLNodeSet"

然而,现在我不知道如何进入子节点:

> getNodeSet(doc,"/xmlns:doc//b[@omegahat:status='foo']",ns)[[1]]
XPath error : Undefined namespace prefix
XPath error : Invalid expression
Error in xpathApply.XMLInternalDocument(doc,: 
  error evaluating xpath expression /xmlns:doc//b[@omegahat:status='foo']
In addition: Warning message:
using http://something.org as prefix for default namespace http://something.org 

> getNodeSet(doc,+ namespaces = c(
+ matchNamespaces(doc,nsDefs = nsDefs),+ matchNamespaces(doc,namespaces="omegahat",nsDefs = nsDefs)
+ )
+ )
list()
attr(,"class")
[1] "XMLNodeSet"
没有前缀的命名空间定义(xmlns =“…”)是认命名空间.在XML文档具有认命名空间的情况下,认命名空间声明的元素和所有它的后代没有前缀且没有不同的认命名空间声明在上述认命名空间中被考虑.

因此,在您的情况下,您需要在XPath中的所有元素的开头使用为认命名空间注册的前缀,例如:

/xmlns:doc//xmlns:b[@omegahat:status='foo']

更新:

实际上我不是r的用户,但是在网上看一些像这样的引用可能有用:

getNodeSet(doc,"/ns:doc//ns:b[@omegahat:status='foo']",c(ns="http://something.org"))

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。