How to update xml attributes without using a loop with the xml2 R package -
i have xml object update using r's xml2 package. there 2 things need do:
- update text inside nodes
<c>{text}</c> - update attributes of nodes
<c name={text}/>
i'd avoid looping on xml structure because slower identifying node set , assigning entire vector of values @ once.
xml <- read_xml("<root> <c name='test' db_name='test'><d>this column desc</d></c> <c name='test2' db_name='test2'><d>this column desc</d></c> <c name='test3' db_name='test3'><d>this column desc</d></c> </root>") df <- data.frame( db_name = c("test2", "test", "test3"), desc = c("new desc!", "you want desc", "good vector"), disp_name = c("okay", "now", "happy"), stringsasfactors = f) we on #1
c_nodes <- xml %>% xml_find_all("//c") c_db_names <- c_nodes %>% xml_find_all("@db_name") %>% xml_text xml_text(c_nodes) <- df$desc[match(c_db_names, df$db_name)] bad on #2
disp_names <- df$disp_name[match(c_db_names, df$db_name)] (i in seq_along(c_nodes)) { xml_attr(c_nodes[i], "name") <- disp_names[i] } when try xml_attr(c_nodes, "name") <- df$disp_name[match(c_db_names, df$db_name)], following error:
error in node_set_attr(x$node, name = attr, nsmap = ns, value) : expecting single value
if provide single value updates entire node set 1 value, need make different updates each node attribute. thus, i'm using loop, want replace vectorized equivalent produce this:
{xml_document} <root> [1] <c name="now" db_name="test">\n <d>you want desc</d>\n</c> [2] <c name="okay" db_name="test2">\n <d>new desc!</d>\n</c> [3] <c name="happy" db_name="test3">\n <d>good vector</d>\n</c>
xml_set_attrs correct function use, must pass in list of named character vectors value parameter. can create list using apply function, , pass function follows:
new_attrs<-lapply(df$disp_name[match(c_db_names, df$db_name)], function(x) { names(x)<- "name" x }) xml_set_attrs(c_nodes, new_attrs)
Comments
Post a Comment