我正在使用R和XML包解析瑞典图书馆目录。使用库的API,我从包含查询的URL中获取了XML。
我想使用xPath查询来解析每条记录,但是我对XML包的xPath所做的所有操作都返回空白列表,除了“ // *”之外的所有内容。我既不是xml解析也不是xPath方面的专家,但是我怀疑这与我的API返回给我的xml有关。
这是目录中单个帖子的一个简单示例:
library(XML)
example.url <- "http://libris.kb.se/sru/swepub?version=1.1&operation=searchRetrieve&query=mat:dok&maximumRecords=1&recordSchema=mods"
doc = xmlParse(example.url)
# Title
works <- xmlRoot(doc)[[4]][["record"]][["recordData"]][["mods"]][["titleInfo"]][["title"]][[1]]
doesntwork <- getNodeSet(doc, "//title")
# The only xPath that returns anything
onlythisworks <- getNodeSet(doc, "//*")
如果这与名称空间(as these answers sugests)有关,那么我要了解的是,API返回的数据似乎在初始标记中定义了名称空间,我可以使用它,但这无济于事:
# Namespaces are confusing:
title <- getNodeSet(xmlRoot(doc), "//xsi:title", namespaces = c(xsi = "http://www.w3.org/2001/XMLSchema-instance"))
(再次)这是我要解析的the example return data。
最佳答案
您必须使用正确的名称空间。
尝试以下
doesntwork <- getNodeSet(doc, "//mods:title")
#[[1]]
#<title>Horizontal Slot Waveguides for Silicon Photonics Back-End Integration [Elektronisk resurs]</title>
#
#[[2]]
#<title>TRITA-ICT/MAP AVH, 2014:17 \
# </title>
#
#attr(,"class")
#[1] "XMLNodeSet"
顺便说一句:我通常通过以下方式获取名称空间
nsDefs=xmlNamespaceDefinitions(doc,simplify = TRUE,recursive=TRUE)
但这在您的情况下会引发错误。它抱怨有
different URIs for the same name space prefix
。根据this site这似乎不是良好的编码风格。
根据OP的评论进行更新
我自己不是
xml
专家,但是我的看法是:您可以通过<tag xmlns=URI>
定义默认名称空间。非默认名称空间的格式为<tag xmlns:a=URI>
,其中a
是各自的名称空间名称。您的文档的问题是有两个不同的默认名称空间。第一个在
<searchRetrieveResponse xmlns="http://www.loc.gov/zing/srw/" ... >
中。第二个在<mods xmlns="http://www.loc.gov/mods/v3" ... >
中。此外,您将在第一个标签中找到第二个默认名称空间URI,即xmlns:mods="http://www.loc.gov/mods/v3"
(非默认)。这似乎很混乱。现在,<title>
标记在<mods>
标记内。我认为<mods>
中定义的默认名称空间被searchRetrieveResponse
的非默认名称空间覆盖(因为它们具有相同的URI)。因此,尽管<mods>
和所有后续标记(例如<title>
)似乎具有默认名称空间,但它们实际上具有xmlns:mods
名称空间。但这不适用于标签<numberOfRecords>
(因为它在<mods>
之外)。您可以通过访问此节点getNodeSet(doc, "//ns:numberOfRecords",
namespaces = c(ns="http://www.loc.gov/zing/srw/"))
在这里,您提取
<searchRetrieveResponse>
中定义的默认名称空间并为其命名(在本例中为ns
)。然后,您可以在xPath查询中显式使用默认名称空间名称。关于r - 当我使用XML包在R中解析此XML时,为什么“//*”是唯一可用的xPath查询?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34749655/