【问题标题】:How can I use xpath querying using R's XML library?如何使用 R 的 XML 库使用 xpath 查询?
【发布时间】:2010-10-06 20:25:25
【问题描述】:

xml文件有这个sn-p:

<?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>

我尝试使用 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()

xpath 不应该匹配:

<PC-XRefData_pmid>17959251</PC-XRefData_pmid>

【问题讨论】:

  • 对 R 一无所知,我假设 ns="xs"ns= c(xs... 部分声明了表达式中使用的命名空间。这可能是问题所在,因为元素PC-XRefData_pmid 不是http://www.w3.org/2001/XMLSchema-instance 命名空间的成员,而是http://www.ncbi.nlm.nih.gov,这是源文档中的默认命名空间。搜索xs:PC-XRefData_pmid 是错误的。
  • 我假设我不需要命名空间,因为默认的是 xmlns="ncbi.nlm.nih.gov"? xpath 查询“//PC-XRefData_pmid”不应该工作吗?

标签: xml r xpath xquery


【解决方案1】:

由于默认命名空间是 NIH(其 URI 为“http://www.ncbi.nlm.nih.gov”),&lt;PC-XRefData_pmid&gt;(以及 XML 文档中没有命名空间前缀的所有其他元素)在那个 NIH 命名空间中。

因此,要将它们与 XPath 匹配,您需要告诉 XPath 处理器您将为 NIH 命名空间使用什么前缀,并且您需要在 XPath 中使用该前缀。

所以,在不知道 R 的情况下,我会尝试

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

否则

getNodeSet(doc, "//*[local-name() = 'PC-XRefData_pmid']")

因为后者绕过了命名空间。

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

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

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

所以如果“doc”是文档类的一个实例,那么正确的解决方案是:

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

【讨论】:

  • 这太棒了,我一直想知道如何绕过命名空间,因为它们总是让我头疼。
  • @WarrenFaith:很高兴你提出了这些我不知道的额外警告。不过,我想知道它们是否更适合单独的答案。事实上,听起来(尤其是最后几句话)就像是我说的。
  • @LarsH 我没有,但我将它修改为最后一个(删除了一些不重要的东西)。
  • WF:哦,我明白了,你刚刚查看了 Jim 的编辑 - 并删除了他的自我署名?我想我会编辑它以明确他添加的内容。 @JimPivarski:我认为您的警告很有价值,但下次请将它们放在评论或单独的答案中。这次,我会将它们纳入我的答案中,并注明出处。
【解决方案2】:

这是常见问题解答。

这个://PC-XRefData_pmid

意思是:任何PC-XRefData_pmid在没有命名空间或空命名空间下的文档中

这并不意味着默认命名空间下的文档中有任何PC-XRefData_pmid

另外,您的文档示例尚未完成,但您的 PC-XRefData_pmid 元素似乎位于 http://www.ncbi.nlm.nih.gov 命名空间下

【讨论】:

  • @Alejandro,您能否为粗体部分提供参考?我相信你,但想确定这不仅适用于 XSLT 中的 XPath,而且适用于一般的 XPath,即使将默认命名空间声明传递给 XPath 处理器也是如此。
  • @Alejandro:没关系,我在w3.org/TR/xpath/#node-tests 看到它。您会说这适用于 XPath 1.0,但不适用于 2.0?因为 XSLT 2.0 允许您为 XPath 表达式声明默认 ns。
  • 谢谢,我不知道有关 // 用于 xpath 查询的信息。
  • @Alejandro:再次回答我自己。 :-) 根据w3.org/TR/xpath20/#node-tests,在 XPath 2.0 中,“一个 无前缀的 QName,当用作主节点类型为元素的轴上的名称测试时,具有 的命名空间 URI表达式上下文中的默认元素/类型命名空间;否则,它没有命名空间URI。”但我们假设@tommy 使用的是 XPath 1.0。
  • @LarsH:我认为这是specs 的正确部分:Two expanded-names are equal if they have the same local part, and either both have a null namespace URI or both have non-null namespace URIs that are equal. 另外,看起来正确的术语应该是 null namespace URI
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-19
相关资源
最近更新 更多