Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
19b65cd
Very basic modification of single nodes
jimhester Feb 17, 2016
08468fb
Add functions to create new nodes / documents
jimhester Feb 18, 2016
c508fb6
Use actual maps for NsMap
jimhester Feb 19, 2016
45e696c
Fix tests
jimhester Feb 19, 2016
76142c6
Use indexes into vectors rather than pointers.
jimhester Feb 20, 2016
4d7b4ed
Use proper size_type rather than assuming it will be size_t
jimhester Feb 20, 2016
4c28ae4
Preserve input order.
jimhester Feb 22, 2016
7dd28c6
Use boost unordered map
jimhester Feb 22, 2016
bb4411c
Remove BOOST_AUTO
jimhester Feb 22, 2016
2770288
Current state
jimhester Feb 24, 2016
06d02ea
node content assignment
jimhester Apr 25, 2016
7709e66
Attribute assignment
jimhester Apr 25, 2016
d5d2557
Support unsetting attributes
jimhester Apr 26, 2016
567d698
Support writing xml_attrs from a named vector
jimhester Apr 26, 2016
c84b4dc
Mode location of node_attrs
jimhester Apr 26, 2016
6c090b5
Support xml_nodesets for xml_attrs modification
jimhester Apr 26, 2016
56c6cb9
Add assignment method for xml_name
jimhester Apr 26, 2016
8f6802e
xml_nodeset method
jimhester Apr 26, 2016
f840beb
Tests for xml_attr<- and xml_attrs<-
jimhester Apr 27, 2016
5dd55b8
Errors found by tests
jimhester Apr 27, 2016
a8690f9
Tests for xml_contents
jimhester Apr 27, 2016
8f05bb6
Tests for xml_name
jimhester Apr 27, 2016
fd31586
Rename xml_contents<- to xml_text<-
jimhester Apr 27, 2016
2692009
Re-oxygenate
jimhester Apr 27, 2016
08140e3
Simple modification vignette
jimhester Apr 27, 2016
298d62b
Mode xml_name replacement function to the xml_name file
jimhester Apr 28, 2016
ad491b7
Add sibling nodes
jimhester Apr 28, 2016
543aa77
Fix xml_name test
jimhester Apr 28, 2016
0b104ed
Add xml_add_child
jimhester Apr 28, 2016
7e4a566
Add missing test files
jimhester Apr 28, 2016
ad143cd
Have to load the library first
jimhester Apr 29, 2016
7bc4384
Update documentation to fix WARNINGS
jimhester Apr 29, 2016
9fc5130
Additional tests for the modification code
jimhester Apr 29, 2016
7d2131b
Remove unused functions
jimhester May 2, 2016
1dd3356
Both ns and value should be lists for xml_attrs<-.xml_nodeset
jimhester May 2, 2016
361561c
ns should be a list for xml_name<-.xml_nodeset
jimhester May 2, 2016
58e5bdd
Explain behavior of xml_attrs
jimhester May 2, 2016
3fbeb6c
Move questions to the bottom
jimhester May 2, 2016
a657c0c
Use braces around UseMethod
jimhester May 2, 2016
f86e2f1
Use has_names
jimhester May 2, 2016
6cb2d4c
Make xml_replace just a normal function
jimhester May 2, 2016
f9b7b0f
Document modification methods together
jimhester May 2, 2016
6965191
Re-oxygenate
jimhester May 2, 2016
cbb8986
Adding a new node/document
jimhester May 3, 2016
59b2ae7
Node and document creation functions
jimhester May 3, 2016
dcfbe1e
Include document pointer in xml_namespace object
jimhester May 4, 2016
903e978
Tweaks to node creating plus simple example in vignette
jimhester May 4, 2016
4eaf6e1
Free unlinked nodes
jimhester May 5, 2016
c2936d9
Draft of creating new namespaces and setting an existing namespace
jimhester May 6, 2016
e673249
Return invisibly
jimhester May 6, 2016
526ba00
Use named character vector for xml_new_namespace
jimhester May 6, 2016
93a4ce3
Export xml_new_node
jimhester May 6, 2016
ced5c4b
Export xml_new_document
jimhester May 6, 2016
f7db761
Creating nodes in a namespace
jimhester May 9, 2016
391844b
Create new namespaces using xml_attr
jimhester May 9, 2016
8019a56
Some cleanup
jimhester May 9, 2016
1a3c368
Allow using xml_add_child on xml_document without a root node
jimhester May 9, 2016
855b74e
Support adding text to a new node
jimhester May 10, 2016
f1d4cdf
Update tests
jimhester May 10, 2016
179dc4f
Update vignette for new API
jimhester May 10, 2016
e2a8c68
xml_root to get the document from an xml_node
jimhester May 10, 2016
cef3f91
Only print node names if the document has a node
jimhester May 10, 2016
cf9a6f5
Re-oxygenate
jimhester May 10, 2016
c1a4c64
Rename modify.R
jimhester May 10, 2016
6aca780
Remove xml_new_node and xml_new_namespace and fix documentation issues.
jimhester May 11, 2016
5435f2a
Throw error if namespace is not found
jimhester May 11, 2016
379d808
Move namespace lookup functions to namespace file
jimhester May 11, 2016
b4f46bb
Rename arguments to avoid namespace clashes
jimhester May 11, 2016
f7a0d49
Add magrittr in Suggests, as it is used in the vignette
jimhester May 11, 2016
8e0a0e8
Only modify text nodes with xml_text<-
jimhester May 11, 2016
52183af
Text for text creation
jimhester May 11, 2016
29718a1
Tweaks to adding a new node to a document
jimhester May 12, 2016
e632d3c
Add a format option to write_xml
jimhester May 13, 2016
cd61f0f
Add an explicit free argument to xml_remove_node
jimhester May 18, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ src/*.so
src/*.dll
src/*.a
src/Makevars
inst/doc
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
language: R
cache: packages

github_packages: jimhester/covr

addons:
apt:
packages:
Expand Down
6 changes: 5 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ LinkingTo: Rcpp (>= 0.11.4.6),
Suggests:
testthat,
curl,
covr
covr,
knitr,
rmarkdown,
magrittr
SystemRequirements: libxml2: libxml2-dev (deb), libxml2-devel (rpm)
License: GPL (>= 2)
RoxygenNote: 5.0.1
VignetteBuilder: knitr
28 changes: 28 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
# Generated by roxygen2: do not edit by hand

S3method("[",xml_nodeset)
S3method("xml_attr<-",xml_node)
S3method("xml_attr<-",xml_nodeset)
S3method("xml_attrs<-",xml_node)
S3method("xml_attrs<-",xml_nodeset)
S3method("xml_name<-",xml_node)
S3method("xml_name<-",xml_nodeset)
S3method("xml_text<-",xml_node)
S3method("xml_text<-",xml_nodeset)
S3method(as.character,xml_document)
S3method(as.character,xml_missing)
S3method(as.character,xml_node)
Expand All @@ -26,6 +34,11 @@ S3method(write_xml,xml_document)
S3method(write_xml,xml_missing)
S3method(write_xml,xml_node)
S3method(write_xml,xml_nodeset)
S3method(xml_add_child,xml_document)
S3method(xml_add_child,xml_node)
S3method(xml_add_child,xml_nodeset)
S3method(xml_add_sibling,xml_node)
S3method(xml_add_sibling,xml_nodeset)
S3method(xml_attr,xml_missing)
S3method(xml_attr,xml_node)
S3method(xml_attr,xml_nodeset)
Expand Down Expand Up @@ -57,6 +70,10 @@ S3method(xml_parent,xml_node)
S3method(xml_parent,xml_nodeset)
S3method(xml_path,xml_node)
S3method(xml_path,xml_nodeset)
S3method(xml_remove_node,xml_node)
S3method(xml_remove_node,xml_nodeset)
S3method(xml_replace,xml_node)
S3method(xml_replace,xml_nodeset)
S3method(xml_text,xml_missing)
S3method(xml_text,xml_node)
S3method(xml_text,xml_nodeset)
Expand All @@ -65,6 +82,10 @@ S3method(xml_type,xml_node)
S3method(xml_type,xml_nodeset)
S3method(xml_url,xml_missing)
S3method(xml_url,xml_node)
export("xml_attr<-")
export("xml_attrs<-")
export("xml_name<-")
export("xml_text<-")
export(as_list)
export(html_structure)
export(read_html)
Expand All @@ -75,6 +96,8 @@ export(url_parse)
export(url_relative)
export(url_unescape)
export(write_xml)
export(xml_add_child)
export(xml_add_sibling)
export(xml_attr)
export(xml_attrs)
export(xml_children)
Expand All @@ -87,11 +110,16 @@ export(xml_find_one)
export(xml_has_attr)
export(xml_length)
export(xml_name)
export(xml_new_document)
export(xml_ns)
export(xml_ns_rename)
export(xml_parent)
export(xml_parents)
export(xml_path)
export(xml_remove_node)
export(xml_replace)
export(xml_root)
export(xml_set_namespace)
export(xml_siblings)
export(xml_structure)
export(xml_text)
Expand Down
84 changes: 82 additions & 2 deletions R/RcppExports.R
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,30 @@ doc_format <- function(x) {
.Call('xml2_doc_format', PACKAGE = 'xml2', x)
}

doc_write <- function(x, path) {
invisible(.Call('xml2_doc_write', PACKAGE = 'xml2', x, path))
doc_write <- function(x, path, format) {
invisible(.Call('xml2_doc_write', PACKAGE = 'xml2', x, path, format))
}

doc_root <- function(x) {
.Call('xml2_doc_root', PACKAGE = 'xml2', x)
}

doc_has_root <- function(x) {
.Call('xml2_doc_has_root', PACKAGE = 'xml2', x)
}

doc_url <- function(x) {
.Call('xml2_doc_url', PACKAGE = 'xml2', x)
}

doc_new <- function(version) {
.Call('xml2_doc_new', PACKAGE = 'xml2', version)
}

doc_set_root <- function(doc, root) {
.Call('xml2_doc_set_root', PACKAGE = 'xml2', doc, root)
}

libxml2_version <- function() {
.Call('xml2_libxml2_version', PACKAGE = 'xml2')
}
Expand All @@ -41,10 +53,22 @@ doc_namespaces <- function(doc) {
.Call('xml2_doc_namespaces', PACKAGE = 'xml2', doc)
}

ns_lookup_uri <- function(doc, node, uri) {
.Call('xml2_ns_lookup_uri', PACKAGE = 'xml2', doc, node, uri)
}

ns_lookup <- function(doc, node, prefix) {
.Call('xml2_ns_lookup', PACKAGE = 'xml2', doc, node, prefix)
}

node_name <- function(node, nsMap) {
.Call('xml2_node_name', PACKAGE = 'xml2', node, nsMap)
}

node_set_name <- function(node, value) {
invisible(.Call('xml2_node_set_name', PACKAGE = 'xml2', node, value))
}

node_text <- function(node, trim) {
.Call('xml2_node_text', PACKAGE = 'xml2', node, trim)
}
Expand All @@ -57,6 +81,14 @@ node_attrs <- function(node, nsMap) {
.Call('xml2_node_attrs', PACKAGE = 'xml2', node, nsMap)
}

node_set_attr <- function(node, name, value, nsMap) {
invisible(.Call('xml2_node_set_attr', PACKAGE = 'xml2', node, name, value, nsMap))
}

node_remove_attr <- function(node, name, nsMap) {
invisible(.Call('xml2_node_remove_attr', PACKAGE = 'xml2', node, name, nsMap))
}

node_format <- function(doc, node, format = TRUE, indent = 0L) {
.Call('xml2_node_format', PACKAGE = 'xml2', doc, node, format, indent)
}
Expand Down Expand Up @@ -97,6 +129,54 @@ node_type <- function(node) {
.Call('xml2_node_type', PACKAGE = 'xml2', node)
}

node_set_content <- function(node, content) {
invisible(.Call('xml2_node_set_content', PACKAGE = 'xml2', node, content))
}

node_append_content <- function(node, content) {
invisible(.Call('xml2_node_append_content', PACKAGE = 'xml2', node, content))
}

node_add_child <- function(parent, cur, copy) {
.Call('xml2_node_add_child', PACKAGE = 'xml2', parent, cur, copy)
}

node_prepend_sibling <- function(cur, elem, copy) {
.Call('xml2_node_prepend_sibling', PACKAGE = 'xml2', cur, elem, copy)
}

node_append_sibling <- function(cur, elem, copy) {
.Call('xml2_node_append_sibling', PACKAGE = 'xml2', cur, elem, copy)
}

node_replace <- function(old, cur, copy) {
.Call('xml2_node_replace', PACKAGE = 'xml2', old, cur, copy)
}

node_remove <- function(cur, free) {
invisible(.Call('xml2_node_remove', PACKAGE = 'xml2', cur, free))
}

node_new <- function(name) {
.Call('xml2_node_new', PACKAGE = 'xml2', name)
}

node_new_ns <- function(name, ns) {
.Call('xml2_node_new_ns', PACKAGE = 'xml2', name, ns)
}

node_null <- function() {
.Call('xml2_node_null', PACKAGE = 'xml2')
}

node_set_namespace_uri <- function(doc, node, uri) {
invisible(.Call('xml2_node_set_namespace_uri', PACKAGE = 'xml2', doc, node, uri))
}

node_set_namespace_prefix <- function(doc, node, prefix) {
invisible(.Call('xml2_node_set_namespace_prefix', PACKAGE = 'xml2', doc, node, prefix))
}

#' Convert between relative and absolute urls.
#'
#' @param x A character vector of urls relative to that base
Expand Down
7 changes: 5 additions & 2 deletions R/classes.R
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@ xml_document <- function(doc) {
#' @export
print.xml_document <- function(x, width = getOption("width"), max_n = 20, ...) {
cat("{xml_document}\n")
cat("<", xml_name(x), ">\n", sep = "")
show_nodes(xml_children(x), width = width, max_n = max_n)
if (inherits(x, "xml_node")) {
cat("<", xml_name(x), ">\n", sep = "")
show_nodes(xml_children(x), width = width, max_n = max_n)
}
}

#' @export
Expand Down Expand Up @@ -117,6 +119,7 @@ show_nodes <- function(x, width = getOption("width"), max_n = 20) {
if (trunc) {
cat("...\n")
}
invisible()
}


Expand Down
12 changes: 12 additions & 0 deletions R/utils.R
Original file line number Diff line number Diff line change
@@ -1 +1,13 @@
`%||%` <- function(a, b) if (is.null(a)) b else a

is_named <- function(x) {
all(has_names(x))
}
has_names <- function(x) {
nms <- names(x)
if (is.null(nms)) {
rep(FALSE, length(x))
} else {
!(is.na(nms) | nms == "")
}
}
87 changes: 83 additions & 4 deletions R/xml_attr.R
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#' Retrieve an attribute.
#'
#' \code{xml_attrs()} retrieves all attributes values as a named character
#' vector. \code{xml_attr()} retrieves the value of single attribute. If the
#' attribute doesn't exist, it will return \code{default}, which defaults to
#' \code{NA}. \code{xml_has_attr()} tests if an attribute is present.
#' vector, \code{xml_attrs() <-} sets all attribute values. \code{xml_attr()}
#' retrieves the value of single attribute and \code{xml_attr() <-} modifies
#' its value. If the attribute doesn't exist, it will return \code{default},
#' which defaults to \code{NA}. \code{xml_has_attr()} tests if an attribute is
#' present.
#'
#' @inheritParams xml_name
#' @param attr Name of attribute to extract.
Expand Down Expand Up @@ -79,7 +81,9 @@ xml_has_attr <- function(x, attr, ns = character()) {

#' @export
#' @rdname xml_attr
xml_attrs <- function(x, ns = character()) UseMethod("xml_attrs")
xml_attrs <- function(x, ns = character()) {
UseMethod("xml_attrs")
}

#' @export
xml_attrs.xml_missing <- function(x, ns = character()) {
Expand All @@ -95,3 +99,78 @@ xml_attrs.xml_node <- function(x, ns = character()) {
xml_attrs.xml_nodeset <- function(x, ns = character()) {
lapply(x, xml_attrs, ns = ns)
}

#' @param value character vector of new value.
#' @rdname xml_attr
#' @export
`xml_attr<-` <- function(x, attr, ns = character(), value) {
UseMethod("xml_attr<-")
}

#' @export
`xml_attr<-.xml_node` <- function(x, attr, ns = character(), value) {
if (is.null(value)) {
node_remove_attr(x$node, name = attr, nsMap = ns)
} else {
node_set_attr(x$node, name = attr, nsMap = ns, value)
}
x
}

#' @export
`xml_attr<-.xml_nodeset` <- function(x, attr, ns = character(), value) {
lapply(x, `xml_attr<-`, attr = attr, ns = ns, value = value)
x
}

#' @rdname xml_attr
#' @export
`xml_attrs<-` <- function(x, ns = character(), value) {
UseMethod("xml_attrs<-")
}

#' @export
`xml_attrs<-.xml_node` <- function(x, ns = character(), value) {
if (!is_named(value)) {
stop("`value` must be a named character vector or `NULL`", call. = FALSE)
}

attrs <- names(value)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to check this is not NULL, and elements not "" or NA? (You can just throw an error if not)

has_names <- function(x) {
  nms <- names(x)
  if (is.null(nms)) {
    rep_along(x, FALSE)
  } else {
    !(is.na(nms) | nms == "")
  }
}


current_attrs <- names(xml_attrs(x, ns = ns))

existing <- intersect(current_attrs, attrs)
new <- setdiff(attrs, current_attrs)
removed <- setdiff(current_attrs, attrs)

# replace existing attributes and add new ones
Map(function(attr, val) {
xml_attr(x, attr, ns) <- val
}, attr = c(existing, new), value[c(existing, new)])


# Remove attributes which no longer exist
Map(function(attr) {
xml_attr(x, attr, ns) <- NULL
}, attr = removed)

x
}

#' @export
`xml_attrs<-.xml_nodeset` <- function(x, ns = character(), value) {
if (!is.list(ns)) {
ns <- list(ns)
}
if (!is.list(value)) {
value <- list(value)
}
if (!all(vapply(value, is_named, logical(1)))) {
stop("`value` must be a list of named character vectors")
}

Map(`xml_attrs<-`, x, ns, value)

x
}

8 changes: 8 additions & 0 deletions R/xml_children.R
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,11 @@ xml_length.xml_nodeset <- function(x, only_elements = TRUE) {

vapply(x, node_length, onlyNode = only_elements, FUN.VALUE = integer(1))
}

#' @export
#' @rdname xml_children
xml_root <- function(x) {
stopifnot(inherits(x, "xml_node") || inherits(x, "xml_document"))

xml_document(x$doc)
}
Loading