Skip to content

Commit 66195e2

Browse files
New xml_find_int() to get integers from an XPath (#412)
1 parent e4a54ae commit 66195e2

File tree

6 files changed

+73
-0
lines changed

6 files changed

+73
-0
lines changed

NAMESPACE

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ S3method(xml_find_chr,xml_nodeset)
8080
S3method(xml_find_first,xml_missing)
8181
S3method(xml_find_first,xml_node)
8282
S3method(xml_find_first,xml_nodeset)
83+
S3method(xml_find_int,xml_missing)
84+
S3method(xml_find_int,xml_node)
85+
S3method(xml_find_int,xml_nodeset)
8386
S3method(xml_find_lgl,xml_missing)
8487
S3method(xml_find_lgl,xml_node)
8588
S3method(xml_find_lgl,xml_nodeset)
@@ -149,6 +152,7 @@ export(xml_dtd)
149152
export(xml_find_all)
150153
export(xml_find_chr)
151154
export(xml_find_first)
155+
export(xml_find_int)
152156
export(xml_find_lgl)
153157
export(xml_find_num)
154158
export(xml_find_one)

NEWS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# xml2 (development version)
22

3+
* `xml_find_int()` analogous to `xml_find_num()` for returning integers
4+
matched by an XPath (#365, @michaelchirico).
5+
36
* Now compatible with limxml2 2.12.0 and later (@KNnut).
47

58
* Fix format string issues detected in R-devel.

R/xml_find.R

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,33 @@ xml_find_num.xml_missing <- function(x, xpath, ns = xml_ns(x)) {
178178
numeric(0)
179179
}
180180

181+
#' @export
182+
#' @rdname xml_find_all
183+
xml_find_int <- function(x, xpath, ns = xml_ns(x)) {
184+
UseMethod("xml_find_int")
185+
}
186+
187+
#' @export
188+
xml_find_int.xml_node <- function(x, xpath, ns = xml_ns(x)) {
189+
res <- .Call(xpath_search, x$node, x$doc, xpath, ns, Inf)
190+
check_number_whole(res, arg = I(paste0("Element at path `", xpath, "`")))
191+
as.integer(res)
192+
}
193+
194+
#' @export
195+
xml_find_int.xml_nodeset <- function(x, xpath, ns = xml_ns(x)) {
196+
if (length(x) == 0) {
197+
return(integer())
198+
}
199+
200+
vapply(x, function(x) xml_find_int(x, xpath = xpath, ns = ns), integer(1))
201+
}
202+
203+
#' @export
204+
xml_find_int.xml_missing <- function(x, xpath, ns = xml_ns(x)) {
205+
integer(0)
206+
}
207+
181208
#' @export
182209
#' @rdname xml_find_all
183210
xml_find_chr <- function(x, xpath, ns = xml_ns(x)) {

man/xml_find_all.Rd

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/_snaps/xml_find.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,24 @@
22

33
Element at path `//z` must be a number, not a <xml_missing> object.
44

5+
# xml_find_int errors with non integer results
6+
7+
Code
8+
xml_find_int(x, "//z")
9+
Condition
10+
Error in `xml_find_int()`:
11+
! Element at path `//z` must be a whole number, not a <xml_missing> object.
12+
Code
13+
xml_find_int(x, "//y")
14+
Condition
15+
Error in `xml_find_int()`:
16+
! Element at path `//y` must be a whole number, not a list.
17+
Code
18+
xml_find_int(x, "number(1.1)")
19+
Condition
20+
Error in `xml_find_int()`:
21+
! Element at path `number(1.1)` must be a whole number, not the number 1.1.
22+
523
# xml_find_chr errors with non character results
624

725
Element at path `//z` must be a single string, not a <xml_missing> object.

tests/testthat/test-xml_find.R

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,24 @@ test_that("xml_find_num returns a numeric result", {
8585
expect_equal(xml_find_num(x, "1 div floor(-0)"), -Inf)
8686
})
8787

88+
# Find int ---------------------------------------------------------------------
89+
test_that("xml_find_int errors with non integer results", {
90+
x <- read_xml("<x><y/><y/></x>")
91+
expect_snapshot(error = TRUE, {
92+
xml_find_int(x, "//z")
93+
xml_find_int(x, "//y")
94+
xml_find_int(x, "number(1.1)")
95+
})
96+
})
97+
98+
test_that("xml_find_int returns a integer result", {
99+
x <- read_xml("<x><y>1</y><y/></x>")
100+
101+
expect_identical(xml_find_int(x, "1 div floor(-0.1)"), -1L)
102+
expect_identical(xml_find_int(x, "number(//y)"), 1L)
103+
expect_identical(xml_find_int(x, "string-length(string('abcd'))"), 4L)
104+
})
105+
88106
# Find chr ---------------------------------------------------------------------
89107
test_that("xml_find_chr errors with non character results", {
90108
x <- read_xml("<x><y/><y/></x>")

0 commit comments

Comments
 (0)