How to create xml document using xml2 and furrr?

How to convert the following code using furrr

library(xml2)

# 1. Create a new, empty XML document with a root node
xml_doc <- xml_new_document()
root_node <- xml_add_child(xml_doc, "items") # Add the root element

# 2. Define the data you want to loop through
item_names <- c("apple", "banana", "cherry", "date")
item_ids <- 101:104

# 3. Loop through the data to create and add nodes
for (i in seq_along(item_names)) {
  # Create a new <item> node as a child of the root_node
  item_node <- xml_add_child(root_node, "item")
  
  # Add child elements (e.g., <name> and <id>) to the new item node
  xml_add_child(item_node, "name", item_names[i])
  xml_add_child(item_node, "id", item_ids[i])
}

# 4. Print or save the resulting XML document
print(xml_doc)

  1. Why do you want to rewrite the code using these specific packages?
    I am asking this, because without context this sounds a lot like an XY problem (where you ask for help with your solution to a problem, instead of the underlying problem).
    Also, furrr is being replaced as a parallel backend. If you've freedom of choice, it might be worth seeing if you want to move on to the more modern solution.
  2. Can you share what you've tried? Did you get stuck somewhere? Did you struggle with reading some of the documentation, or finding it?

For that particular structure you could build items as lists and in the main process convert nested list into XML doc with as_xml_document(). I'd start with plain {purrr} first and then parallelize, either with {furrr}, purrr::in_parallel() or mirai::mirai_map().

Test with {purrr}:

library(xml2)
library(purrr)
library(furrr)
#> Loading required package: future

item_names <- c("apple", "banana", "cherry", "date")
item_ids <- 101:104

map2(item_ids, item_names, \(id, nm) list(name = list(nm), id = list(id))) |>
  set_names("item") |>
  list(items = _) |>
  as_xml_document()
#> {xml_document}
#> <items>
#> [1] <item>\n  <name>apple</name>\n  <id>101</id>\n</item>
#> [2] <item>\n  <name>banana</name>\n  <id>102</id>\n</item>
#> [3] <item>\n  <name>cherry</name>\n  <id>103</id>\n</item>
#> [4] <item>\n  <name>date</name>\n  <id>104</id>\n</item>

Same with {furrr}:

plan(multisession, workers = 2)
# or plan(future.mirai::mirai_multisession, workers = 2) or whatever backend you are going to use
future_map2(item_ids, item_names, \(id, nm) list(name = list(nm), id = list(id))) |>
  set_names("item") |>
  list(items = _) |>
  as_xml_document()
#> {xml_document}
#> <items>
#> [1] <item>\n  <name>apple</name>\n  <id>101</id>\n</item>
#> [2] <item>\n  <name>banana</name>\n  <id>102</id>\n</item>
#> [3] <item>\n  <name>cherry</name>\n  <id>103</id>\n</item>
#> [4] <item>\n  <name>date</name>\n  <id>104</id>\n</item>

# close multisession workers
plan(sequential)

Or use {mirai} backend through purrr::in_parallel() :

# start mirai daemons
mirai::daemons(2)
map2(item_ids, item_names, in_parallel(\(id, nm) list(name = list(nm), id = list(id)))) |>
  set_names("item") |>
  list(items = _) |>
  as_xml_document()
#> {xml_document}
#> <items>
#> [1] <item>\n  <name>apple</name>\n  <id>101</id>\n</item>
#> [2] <item>\n  <name>banana</name>\n  <id>102</id>\n</item>
#> [3] <item>\n  <name>cherry</name>\n  <id>103</id>\n</item>
#> [4] <item>\n  <name>date</name>\n  <id>104</id>\n</item>

Or skip {purrr} and use mirai::mirai_map():

data.frame(id = item_ids, nm = item_names) |> 
  mirai::mirai_map(\(id, nm) list(name = list(nm), id = list(id))) |>
  _[] |> 
  set_names("item") |>
  list(items = _) |>
  as_xml_document()
#> {xml_document}
#> <items>
#> [1] <item>\n  <name>apple</name>\n  <id>101</id>\n</item>
#> [2] <item>\n  <name>banana</name>\n  <id>102</id>\n</item>
#> [3] <item>\n  <name>cherry</name>\n  <id>103</id>\n</item>
#> [4] <item>\n  <name>date</name>\n  <id>104</id>\n</item>

# stop daemons
mirai::daemons(0)

Created on 2025-12-15 with reprex v2.1.1