Search code examples
rxmlapplyxml2

Add multiple children to an xml object without using a loop


My objective is to create an xml object that comprises multiple elements that each contain varying information. A simple example of what the xml object looks like is:

library(xml2)
x1 <- read_xml("<Diag><line level='3' description='a log message'/><line level='3' description='a second log message'/></Diag>")
message(x1)

Which outputs:

<Diag>
 <line level="3" description="a log message"/>
 <line level="3" description="a second log message"/>
</Diag>

At the moment, I take the information from a data frame called diag. I add the children using a for loop:

library(xml2)
diag <- data.frame(level=c(3,3),description=c('a log message','a second log message'),stringsAsFactors = F)
x2 <- xml_new_root("Diag")
for (i in 1:dim(diag)[1]) {
xml_add_child(.x=x2,.value="line",level=diag$level[i],description=diag$description[i])
}
message(x2)

The xml layout of which is identical to that of x1.

However, this loop is less elegant than I would like it to be, and, for large data frames, can be slow.

My question is: is there any way that I can create multiple children at once using the data in my data frame, by using something akin to apply?

I have tried various options but none were successful and I am not sure I was close enough to post any of these options here. Currently, I am using the xml2 package but if a solution can be found using another package then I'd be open to that also.

Much obliged for any help!


Solution

  • The following seems to be doing what you want, using sapply as requested.

    x2 <- xml_new_root("Diag")
    sapply(1:dim(diag)[1], function(i) {
      xml_add_child(.x=x2,.value="line",level=diag$level[i],description=diag$description[i])
    }
    )
    message(x2)
    <?xml version="1.0" encoding="UTF-8"?>
    <Diag>
      <line level="3" description="a log message"/>
      <line level="3" description="a second log message"/>
    </Diag>