当我使用 XML 包在 R 中解析此 XML 时,为什么“//*”是唯一有效的 xPath 查询?
Why is "//*" the only xPath query that works when I'm parsing this XML in R using the XML-package?
我正在使用 R 和 XML 包解析瑞典图书馆目录。使用库的 API,我从包含我的查询的 url 中得到 XML。
我想使用 xPath 查询来解析每条记录,但是我使用 XML-包 returns 空白列表的 xPath 所做的一切,除了“//*”之外的所有内容。我不是 xml-parsing 和 xPath 方面的专家,但我怀疑它与我的 API returns 对我的 xml 有关。
这是目录中单曲 post 的简单示例:
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 returns 数据似乎在初始标记中定义了命名空间,我可以使用它,但这对我没有帮助:
# 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"
(此处为 non-default)。这看起来相当混乱。现在,<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 包解析瑞典图书馆目录。使用库的 API,我从包含我的查询的 url 中得到 XML。
我想使用 xPath 查询来解析每条记录,但是我使用 XML-包 returns 空白列表的 xPath 所做的一切,除了“//*”之外的所有内容。我不是 xml-parsing 和 xPath 方面的专家,但我怀疑它与我的 API returns 对我的 xml 有关。
这是目录中单曲 post 的简单示例:
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 returns 数据似乎在初始标记中定义了命名空间,我可以使用它,但这对我没有帮助:
# 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"
(此处为 non-default)。这看起来相当混乱。现在,<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 查询中显式使用默认命名空间名称。