Skip to content

Commit

Permalink
Implement xml_path() in C
Browse files Browse the repository at this point in the history
  • Loading branch information
mgirlich committed Aug 29, 2023
1 parent 3e2049e commit 08ba881
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 22 deletions.
3 changes: 0 additions & 3 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,6 @@ S3method(xml_ns,xml_nodeset)
S3method(xml_parent,xml_missing)
S3method(xml_parent,xml_node)
S3method(xml_parent,xml_nodeset)
S3method(xml_path,xml_missing)
S3method(xml_path,xml_node)
S3method(xml_path,xml_nodeset)
S3method(xml_remove,xml_missing)
S3method(xml_remove,xml_node)
S3method(xml_remove,xml_nodeset)
Expand Down
17 changes: 1 addition & 16 deletions R/xml_path.R
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,5 @@
#' x <- read_xml("<foo><bar><baz /></bar><baz /></foo>")
#' xml_path(xml_find_all(x, ".//baz"))
xml_path <- function(x) {
UseMethod("xml_path")
}

#' @export
xml_path.xml_missing <- function(x) {
NA_character_
}

#' @export
xml_path.xml_node <- function(x) {
.Call(node_path, x$node)
}

#' @export
xml_path.xml_nodeset <- function(x) {
vapply(x, xml_path, FUN.VALUE = character(1))
.Call(node_path, x)
}
49 changes: 46 additions & 3 deletions src/xml2_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -749,12 +749,55 @@ extern "C" SEXP node_parent(SEXP node_sxp) {
END_CPP
}

SEXP node_path_impl(SEXP x) {
NodeType type = getNodeType(x);

SEXP out;

switch(type) {
case NodeType::missing:
out = NA_STRING;
break;
case NodeType::node: {
SEXP node_sxp = VECTOR_ELT(x, 0);
XPtrNode node(node_sxp);

out = Xml2String(xmlGetNodePath(node.checked_get())).asRString();
break;
}
default: Rf_error("Unexpected node type");
}

return(out);
}

// [[export]]
extern "C" SEXP node_path(SEXP node_sxp) {
extern "C" SEXP node_path(SEXP x) {
BEGIN_CPP
XPtrNode node(node_sxp);
NodeType type = getNodeType(x);

switch(type)
{
case NodeType::missing:
case NodeType::node :
return(Rf_ScalarString(node_path_impl(x)));
break;
case NodeType::nodeset: {
int n = Rf_xlength(x);

SEXP out = PROTECT(Rf_allocVector(STRSXP, n));

for (int i = 0; i < n; ++i) {
SEXP x_i = VECTOR_ELT(x, i);
SEXP name_i = node_path_impl(x_i);
SET_STRING_ELT(out, i, name_i);
}

UNPROTECT(1);
return(out);
};
}

return Rf_ScalarString(Xml2String(xmlGetNodePath(node.checked_get())).asRString());
END_CPP
}

Expand Down

0 comments on commit 08ba881

Please sign in to comment.