如何使用R的XML库使用xpath查询?

tom*_*eng 8 xml xpath xquery r

xml文件包含以下代码段:

<?xml version="1.0"?>
<PC-AssayContainer
    xmlns="http://www.ncbi.nlm.nih.gov"
    xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
    xs:schemaLocation="http://www.ncbi.nlm.nih.gov ftp://ftp.ncbi.nlm.nih.gov/pubchem/specifications/pubchem.xsd"
>
....
    <PC-AnnotatedXRef>
      <PC-AnnotatedXRef_xref>
        <PC-XRefData>
          <PC-XRefData_pmid>17959251</PC-XRefData_pmid>
        </PC-XRefData>
      </PC-AnnotatedXRef_xref>
    </PC-AnnotatedXRef>
Run Code Online (Sandbox Code Playgroud)

我尝试使用xpath的全局搜索解析它,并尝试使用一些命名空间:

library('XML')
doc = xmlInternalTreeParse('http://s3.amazonaws.com/tommy_chheng/pubmed/485270.descr.xml')
>xpathApply(doc, "//PC-XRefData_pmid")
list()
attr(,"class")
[1] "XMLNodeSet"
> getNodeSet(doc, "//PC-XRefData_pmid")
list()
attr(,"class")
[1] "XMLNodeSet"
> xpathApply(doc, "//xs:PC-XRefData_pmid", ns="xs")
list()
> xpathApply(doc, "//xs:PC-XRefData_pmid", ns= c(xs = "http://www.w3.org/2001/XMLSchema-instance"))
list()
Run Code Online (Sandbox Code Playgroud)

xpath不应该匹配:

<PC-XRefData_pmid>17959251</PC-XRefData_pmid>
Run Code Online (Sandbox Code Playgroud)

Lar*_*rsH 9

由于默认命名空间是NIH(其URI是"http://www.ncbi.nlm.nih.gov"),<PC-XRefData_pmid>(并且XML文档中没有名称空间前缀的所有其他元素)都在NIH名称空间中.

因此,要将它们与XPath匹配,您需要告诉您的XPath处理器您将使用哪个前缀用于NIH命名空间,并且您需要在XPath中使用该前缀.

所以,不知道R,我会尝试

xpathApply(doc, "//nih:PC-XRefData_pmid",
   ns= c(nih = "http://www.ncbi.nlm.nih.gov"))
Run Code Online (Sandbox Code Playgroud)

要不然

getNodeSet(doc, "//*[local-name() = 'PC-XRefData_pmid']")
Run Code Online (Sandbox Code Playgroud)

因为后者绕过名称空间.

仅仅因为XML文档将NIH命名空间声明为默认命名空间并不意味着XPath处理器会知道这一点.在XML信息模型中,名称空间前缀并不重要.因此,当我解析XML文档时,NIH命名空间是否绑定到"nih:"前缀或"snizzlefritz:"前缀或""(默认)前缀并不重要.XML解析器或XPath处理器不应该知道什么前缀绑定到XML文档中的哪个命名空间.特别是因为在同一文档中的不同位置可能有几个不同的前缀绑定到同一名称空间...反之亦然.因此,如果您希望XPath表达式与命名空间中的元素匹配,

编辑:有一些警告,由@Jim Pivarski提供:

  • "doc"必须是xml节点,而不是文档(类"XMLNode"或"XMLInternalElementNode",而不是"XMLDocument"或"XMLInternalDocument").
  • 至少在Jim的版本(XML_3.93-0)中,命名参数是"名称空间",而不是"ns".

因此,如果"doc"是文档类的实例,那么正确的解决方案是:

xpathApply(xmlRoot(doc), "//nih:PC-XRefData_pmid",
   namespaces = c(nih = "http://www.ncbi.nlm.nih.gov"))
Run Code Online (Sandbox Code Playgroud)