Add child nodes to an XML node
addChildren.RdThis collection of functions
allow us to add, remove and replace children from an XML node
and also to and and remove attributes on an XML node.
These are generic functions that work on
both internal C-level XMLInternalElementNode objects
and regular R-level XMLNode objects.
addChildren is similar to addNode
and the two may be consolidated into a single generic
function and methods in the future.
Usage
addChildren(node, ..., kids = list(...), at = NA, cdata = FALSE, append = TRUE)
removeChildren(node, ..., kids = list(...), free = FALSE)
removeNodes(node, free = rep(FALSE, length(node)))
replaceNodes(oldNode, newNode, ...)
addAttributes(node, ..., .attrs = NULL,
suppressNamespaceWarning = getOption("suppressXMLNamespaceWarning", FALSE),
append = TRUE)
removeAttributes(node, ..., .attrs = NULL, .namespace = FALSE,
.all = (length(list(...)) + length(.attrs)) == 0)
<!-- %xmlParent(node) = value -->Arguments
- node
the XML node whose state is to be modified, i.e. to which the child nodes are to be added or whose attribute list is to be changed.
- ...
This is for use in interactive settings when specifying a collection of values individuall. In programming contexts when one obtains the collection as a vector or list from another call, use the
kidsor.attrsparameter.- kids
when adding children to a node, this is a list of children nodes which should be of the same "type" (i.e. internal or R-level nodes) as the
nodeargument. However, they can also be regular strings in which case they are converted to XML text nodes.For
removeChildren, this is again a list which identifies the child nodes to be removed using the integer identifier of the child, or the name of the XML node (but this will only remove the first such node and not necessarily do what you expect when there are multiple nodes with the same name), or theXMLInternalNodeobject itself.- at
if specified, an integer identifying the position in the original list of children at which the new children should be added. The children are added after that child. This can also be a vector of indices which is as long as the number of children being added and specifies the position for each child being added. If the vector is shorter than the number of children being added, it is padded with NAs and so the corresponding children are added at the end of the list.
This parameter is only implemented for internal nodes at present.
- cdata
a logical value which controls whether children that are specified as strings/text are enclosed within a CDATA node when converted to actual nodes. This value is passed on to the relevant function that creates the text nodes, e.g.
xmlTextNodeandnewXMLTextNode.- .attrs
a character vector identifying the names of the attributes. These strings can have name space prefixes, e.g.
r:lengthand the namespaces will be resolved relative to the list supported bynodeto ensure those namespaces are defined.- .namespace
This is currently ignored and may never be supported. The intent is to identify on which set of attributes the operation is to perform - the name space declarations or the regular node attributes. This is a logical value indicating if
TRUEthat the attributes of interested are name space declarations, i.e. of the formxmlns:prefixorxmlns. If a value ofFALSEis supplied this indicates that we are identifying regular attributes. Note that we can still identify attributes with a name space prefix as, e.g.,ns:attrwithout this value- free
a logical value indicating whether to free the C-level memory associated with the child nodes that were removed.
TRUEmeans to free that memory. This is only applicable for the internal nodes created withxmlTreeandnewXMLNodeand related functions. It is necessary as automated garbage collection is tricky in this tree-based context spanning both R and C data structures and memory managers.- .all
a logical value indicating whether to remove all of the attributes within the XML node without having to specify them by name.
- oldNode
the node which is to be replaced
- newNode
the node which is to take the place of
oldNodein the list of children of the parent ofoldNode- suppressNamespaceWarning
a logical value or a character string. This is used to control the situation when an XML node or attribute is created with a name space prefix that currently has no definition for that node. This is not necessarily an error but can lead to one. This argument controls whether a warning is issued or if a separate function is called. A value of
FALSEmeans not to suppress the warning and so it is issued. A value ofTRUEcauses the potential problem to be ignored assuming that the namespace will be added to this node or one of its ancestors at a later point. And if this value is a character string, we search for a function of that name and invoke it.- append
a logical value that indicates whether (
TRUE) the specified attributes or children should be added to the existing attributes on the XML node (if any exist), or, ifFALSEthese should replace any existing attributes.
Value
Each of these functions returns the modified node.
For an internal node, this is the same R object and
only the C-level data structures have changed.
For an R XMLNode object, this is is an entirely
separate object from the original node.
It must be inserted back into its parent "node" or context if the changes are to be
seen in that wider context.
References
libxml2 http://www.xmlsoft.org
Examples
b = newXMLNode("bob",
namespace = c(r = "http://www.r-project.org",
omg = "https://www.omegahat.net"))
cat(saveXML(b), "\n")
#> <bob xmlns:r="http://www.r-project.org" xmlns:omg="https://www.omegahat.net"/>
addAttributes(b, a = 1, b = "xyz", "r:version" = "2.4.1", "omg:len" = 3)
#> <bob xmlns:r="http://www.r-project.org" xmlns:omg="https://www.omegahat.net" a="1" b="xyz" r:version="2.4.1" omg:len="3"/>
cat(saveXML(b), "\n")
#> <bob xmlns:r="http://www.r-project.org" xmlns:omg="https://www.omegahat.net" a="1" b="xyz" r:version="2.4.1" omg:len="3"/>
removeAttributes(b, "a", "r:version")
#> <bob xmlns:r="http://www.r-project.org" xmlns:omg="https://www.omegahat.net" b="xyz" omg:len="3"/>
cat(saveXML(b), "\n")
#> <bob xmlns:r="http://www.r-project.org" xmlns:omg="https://www.omegahat.net" b="xyz" omg:len="3"/>
removeAttributes(b, .attrs = names(xmlAttrs(b)))
#> <bob xmlns:r="http://www.r-project.org" xmlns:omg="https://www.omegahat.net" omg:len="3"/>
addChildren(b, newXMLNode("el", "Red", "Blue", "Green",
attrs = c(lang ="en")))
#> <bob xmlns:r="http://www.r-project.org" xmlns:omg="https://www.omegahat.net" omg:len="3">
#> <el lang="en">RedBlueGreen</el>
#> </bob>
k = lapply(letters, newXMLNode)
addChildren(b, kids = k)
#> <bob xmlns:r="http://www.r-project.org" xmlns:omg="https://www.omegahat.net" omg:len="3">
#> <el lang="en">RedBlueGreen</el>
#> <a/>
#> <b/>
#> <c/>
#> <d/>
#> <e/>
#> <f/>
#> <g/>
#> <h/>
#> <i/>
#> <j/>
#> <k/>
#> <l/>
#> <m/>
#> <n/>
#> <o/>
#> <p/>
#> <q/>
#> <r/>
#> <s/>
#> <t/>
#> <u/>
#> <v/>
#> <w/>
#> <x/>
#> <y/>
#> <z/>
#> </bob>
cat(saveXML(b), "\n")
#> <bob xmlns:r="http://www.r-project.org" xmlns:omg="https://www.omegahat.net" omg:len="3">
#> <el lang="en">RedBlueGreen</el>
#> <a/>
#> <b/>
#> <c/>
#> <d/>
#> <e/>
#> <f/>
#> <g/>
#> <h/>
#> <i/>
#> <j/>
#> <k/>
#> <l/>
#> <m/>
#> <n/>
#> <o/>
#> <p/>
#> <q/>
#> <r/>
#> <s/>
#> <t/>
#> <u/>
#> <v/>
#> <w/>
#> <x/>
#> <y/>
#> <z/>
#> </bob>
removeChildren(b, "a", "b", "c", "z")
#> <bob xmlns:r="http://www.r-project.org" xmlns:omg="https://www.omegahat.net" omg:len="3">
#> <el lang="en">RedBlueGreen</el>
#> <d/>
#> <e/>
#> <f/>
#> <g/>
#> <h/>
#> <i/>
#> <j/>
#> <k/>
#> <l/>
#> <m/>
#> <n/>
#> <o/>
#> <p/>
#> <q/>
#> <r/>
#> <s/>
#> <t/>
#> <u/>
#> <v/>
#> <w/>
#> <x/>
#> <y/>
#> </bob>
# can mix numbers and names
removeChildren(b, 2, "e") # d and e
#> <bob xmlns:r="http://www.r-project.org" xmlns:omg="https://www.omegahat.net" omg:len="3">
#> <el lang="en">RedBlueGreen</el>
#> <f/>
#> <g/>
#> <h/>
#> <i/>
#> <j/>
#> <k/>
#> <l/>
#> <m/>
#> <n/>
#> <o/>
#> <p/>
#> <q/>
#> <r/>
#> <s/>
#> <t/>
#> <u/>
#> <v/>
#> <w/>
#> <x/>
#> <y/>
#> </bob>
cat(saveXML(b), "\n")
#> <bob xmlns:r="http://www.r-project.org" xmlns:omg="https://www.omegahat.net" omg:len="3">
#> <el lang="en">RedBlueGreen</el>
#> <f/>
#> <g/>
#> <h/>
#> <i/>
#> <j/>
#> <k/>
#> <l/>
#> <m/>
#> <n/>
#> <o/>
#> <p/>
#> <q/>
#> <r/>
#> <s/>
#> <t/>
#> <u/>
#> <v/>
#> <w/>
#> <x/>
#> <y/>
#> </bob>
i = xmlChildren(b)[[5]]
xmlName(i)
#> [1] "i"
# have the identifiers
removeChildren(b, kids = c("m", "n", "q"))
#> <bob xmlns:r="http://www.r-project.org" xmlns:omg="https://www.omegahat.net" omg:len="3">
#> <el lang="en">RedBlueGreen</el>
#> <f/>
#> <g/>
#> <h/>
#> <i/>
#> <j/>
#> <k/>
#> <l/>
#> <o/>
#> <p/>
#> <r/>
#> <s/>
#> <t/>
#> <u/>
#> <v/>
#> <w/>
#> <x/>
#> <y/>
#> </bob>
x <- xmlNode("a",
xmlNode("b", "1"),
xmlNode("c", "1"),
"some basic text")
v = removeChildren(x, "b")
# remove c and b
v = removeChildren(x, "c", "b")
# remove the text and "c" leaving just b
v = removeChildren(x, 3, "c")
if (FALSE) { # \dontrun{
# this won't work as the 10 gets coerced to a
# character vector element to be combined with 'w'
# and there is no node name 10.
removeChildren(b, kids = c(10, "w"))
} # }
# for R-level nodes (not internal)
z = xmlNode("arg", attrs = c(default="TRUE"),
xmlNode("name", "foo"), xmlNode("defaultValue","1:10"))
o = addChildren(z,
"some text",
xmlNode("a", "a link",
attrs = c(href = "https://www.omegahat.net/RSXML")))
o
#> <arg default="TRUE">
#> <name>foo</name>
#> <defaultValue>1:10</defaultValue>
#> some text
#> <a href="https://www.omegahat.net/RSXML">a link</a>
#> </arg>
# removing nodes
doc = xmlParse("<top><a/><b/><c><d/><e>bob</e></c></top>")
top = xmlRoot(doc)
top
#> <top>
#> <a/>
#> <b/>
#> <c>
#> <d/>
#> <e>bob</e>
#> </c>
#> </top>
removeNodes(list(top[[1]], top[[3]]))
#> NULL
# a and c have disappeared.
top
#> <top>
#> <b/>
#> </top>