| querySelectorAll | R Documentation |
The purpose of these functions is to mimic the functionality of the
querySelector and querySelectorAll functions present in
Internet browsers. This is so we can succinctly query an XML tree for
nodes matching a CSS selector.
Namespaced functions querySelectorNS and
querySelectorAllNS are also provided to search relative to a
given namespace.
querySelector(doc, selector, ns = NULL, ...)
querySelectorAll(doc, selector, ns = NULL, ...)
querySelectorNS(doc, selector, ns,
prefix = "descendant-or-self::", ...)
querySelectorAllNS(doc, selector, ns,
prefix = "descendant-or-self::", ...)
doc |
The XML document, node, or set of nodes to be evaluated against. |
selector |
A selector used to query |
ns |
The namespaces that the query will be filtered to. This is a named
list or vector whose name is the prefix a selector uses (the
|
prefix |
The prefix to apply to the resulting XPath expression. The default
or |
... |
Parameters to be passed onto |
The querySelectorNS and querySelectorAllNS functions are
convenience functions for working with namespaced documents. They
filter out all content that does not belong within the given
namespaces. Note that when searching for particular elements in a
selector, they must have a namespace prefix, e.g. "svg|g".
The filter is relative to doc, so like the un-namespaced
functions these search a node's own subtree rather than the whole
document. A selector starting with :scope replaces the filter
altogether (see below); such a selector is namespaced by its own
prefixes, e.g. ":scope > svg|g".
The namespace argument, ns, is simply passed on to
getNodeSet or xml_find_all if
it is necessary to use a namespace present within the document. This
can be ignored for content lacking a namespace, which is usually the
case when using querySelector or querySelectorAll.
For querySelector and querySelectorAll, leaving
ns as NULL on an xml2 document means the
document's own namespace map is used, which xml_ns
builds by walking the whole document on every query. Passing a
zero-length ns, character(0) or list(), skips
that lookup and queries with no namespaces, which is worth doing on a
large document known to be un-namespaced. It is an error for the
namespaced functions, which have nothing to filter to without a
namespace.
A selector's bare element names match elements in no namespace,
":is(p)" and ":has(p)" exactly as "p" itself
does, so an element in a default namespace has to be reached through
a prefix. With xml2 the document's own prefixes are used when
ns is not given, and xml_ns names a
default namespace d1, making "d1|p" the selector for
those elements.
Queries may be chained: as well as a document or a single node,
doc may be a set of nodes, i.e. an xml2
xml_nodeset or an XML XMLNodeSet, as returned
by querySelectorAll. The selector is then evaluated from each
node of the set in turn, so a relative selector such as ":scope
> a" applies per node. A node that matches from more than one node
of the set is returned only once, at the position it first matched.
An xml2 xml_missing (the result of a failed
xml_find_first) is also accepted, and yields no
matches rather than an error.
Selectors are translated with the generic (XML) translator
unless a translator argument is given to be passed on to
css_to_xpath, with one exception: a
document parsed as HTML by htmlParse or
read_html is queried with the html
translator, so that element and attribute names are matched
case-insensitively and the pseudo-classes that depend on HTML
semantics (:checked, :disabled, :link,
:lang() via the lang attribute, ...) work as they do
in a browser. Passing translator explicitly overrides this
for either kind of document.
The document is recognised however the query starts, so a chain of
queries beginning at an HTML document keeps the html
translator when it continues from one of the document's nodes or
from a set of them.
A selector starting with the :scope pseudo-class is anchored
at the queried node itself: querySelectorAll(node, ":scope >
a") returns only the a children of node, where
querySelectorAll(node, "a") would return all of its a
descendants. :scope after a combinator or within a functional
pseudo-class is an error (it cannot be expressed in XPath 1.0).
When doc is a whole document rather than a node, the queried
node is taken to be the document's root element, so a bare
:scope matches that root element and ":scope > x"
matches its x children. This differs from a browser's
document.querySelectorAll(), where :scope on a
document refers to the document itself: a bare :scope matches
nothing there (the document is not an element), while ":scope
> html" matches the root element. To query starting from the root
element itself rather than the document, pass the root node (e.g.
xmlRoot or xml_root) as
doc instead of the document.
For querySelector, the result is a single node that represents
the first matched node from a selector. If no matching nodes are
found, NULL is returned.
For querySelectorAll, the result is a list of XML nodes. This
list may be empty in the case that no match is found. The list is of
the same type as the input document's package uses, so querying an
xml_nodeset gives an xml_nodeset and querying an
XMLNodeSet gives an XMLNodeSet.
The querySelectorNS and querySelectorAllNS functions
return the same type of content as their un-namespaced counterparts.
These functions propagate the same selectr_parse_error and
selectr_translation_error conditions that
css_to_xpath raises for a malformed or unsupported
selector (see ?css_to_xpath for their fields), plus
selectr_argument_error for a bad R-level argument: doc
that is not an XML or xml2 document, node, or node set;
selector that is not a single character string; or ns
that is not a named list or named character vector of non-empty
strings whose names are valid XML names (or, for
querySelectorNS and querySelectorAllNS, a missing or
zero-length ns).
Simon Potter
CSS Selectors Level 4 https://www.w3.org/TR/selectors-4/, XPath https://www.w3.org/TR/xpath/, querySelectorAll https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll and https://dom.spec.whatwg.org/#dom-parentnode-queryselectorall.
css_to_xpath, whose ‘Errors’ section documents
the condition classes' fields; selectors for the full
selector-support reference.
# All three selectr_error classes (see 'Errors' below) propagate
# from these functions; selectr_argument_error also covers a 'doc'
# that is not an XML or xml2 document, node, or node set.
tryCatch(
querySelectorAll("not a document", "a"),
selectr_argument_error = function(e) cat(conditionMessage(e), "\n")
)
# The XML and xml2 packages are both optional (Suggests), so each demo
# below is guarded with requireNamespace() and runs only when that
# package is installed.
# Demo for working with the XML package
if (requireNamespace("XML", quietly = TRUE)) {
exdoc <- XML::xmlParse('<a><b class="aclass"/><c id="anid"/></a>')
querySelector(exdoc, "#anid") # Returns the matching node
querySelector(exdoc, ".aclass") # Returns the matching node
querySelector(exdoc, "b, c") # First match from grouped selection
querySelectorAll(exdoc, "b, c") # Grouped selection
querySelectorAll(exdoc, "b") # A list of length one
querySelector(exdoc, "d") # No match
querySelectorAll(exdoc, "d") # No match
# Queries can be chained, the second search running from each node
# matched by the first
querySelectorAll(querySelectorAll(exdoc, "a"), "c")
# Read in a document where two namespaces are being set:
# SVG and MathML
svgdoc <- XML::xmlParse(system.file("demos/svg-mathml.svg",
package = "selectr"))
# Search for <script/> elements in the SVG namespace
querySelectorNS(svgdoc, "svg|script",
c(svg = "http://www.w3.org/2000/svg"))
querySelectorAllNS(svgdoc, "svg|script",
c(svg = "http://www.w3.org/2000/svg"))
# MathML content is *within* SVG content,
# search for <mtext> elements within the MathML namespace
querySelectorNS(svgdoc, "math|mtext",
c(math = "http://www.w3.org/1998/Math/MathML"))
querySelectorAllNS(svgdoc, "math|mtext",
c(math = "http://www.w3.org/1998/Math/MathML"))
# Search for *both* SVG and MathML content
querySelectorAllNS(svgdoc, "svg|script, math|mo",
c(svg = "http://www.w3.org/2000/svg",
math = "http://www.w3.org/1998/Math/MathML"))
}
# Demo for working with the xml2 package
if (requireNamespace("xml2", quietly = TRUE)) {
exdoc <- xml2::read_xml('<a><b class="aclass"/><c id="anid"/></a>')
querySelector(exdoc, "#anid") # Returns the matching node
querySelector(exdoc, ".aclass") # Returns the matching node
querySelector(exdoc, "b, c") # First match from grouped selection
querySelectorAll(exdoc, "b, c") # Grouped selection
querySelectorAll(exdoc, "b") # A nodeset of length one
querySelector(exdoc, "d") # No match
querySelectorAll(exdoc, "d") # No match
# Queries can be chained, the second search running from each node
# matched by the first
querySelectorAll(querySelectorAll(exdoc, "a"), "c")
# Read in a document where two namespaces are being set:
# SVG and MathML
svgdoc <- xml2::read_xml(system.file("demos/svg-mathml.svg",
package = "selectr"))
# Search for <script/> elements in the SVG namespace
querySelectorNS(svgdoc, "svg|script",
c(svg = "http://www.w3.org/2000/svg"))
querySelectorAllNS(svgdoc, "svg|script",
c(svg = "http://www.w3.org/2000/svg"))
# MathML content is *within* SVG content,
# search for <mtext> elements within the MathML namespace
querySelectorNS(svgdoc, "math|mtext",
c(math = "http://www.w3.org/1998/Math/MathML"))
querySelectorAllNS(svgdoc, "math|mtext",
c(math = "http://www.w3.org/1998/Math/MathML"))
# Search for *both* SVG and MathML content
querySelectorAllNS(svgdoc, "svg|script, math|mo",
c(svg = "http://www.w3.org/2000/svg",
math = "http://www.w3.org/1998/Math/MathML"))
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.