| Title: | Fast and Elegant XML Generation | 
| Version: | 0.1.1 | 
| Description: | Provides a fast and elegant interface for generating XML fragments and documents. It can be used in companion with R packages 'XML' or 'xml2' to generate XML documents. The fast XML generation is implemented using the 'Rcpp' package. | 
| License: | MIT + file LICENSE | 
| Encoding: | UTF-8 | 
| RoxygenNote: | 7.3.2 | 
| LinkingTo: | Rcpp | 
| Imports: | Rcpp | 
| Suggests: | xml2, tinytest | 
| URL: | https://edwindj.github.io/xmlwriter/ | 
| NeedsCompilation: | yes | 
| Packaged: | 2024-09-25 07:05:36 UTC; edwin | 
| Author: | Edwin de Jonge | 
| Maintainer: | Edwin de Jonge <edwindjonge@gmail.com> | 
| Repository: | CRAN | 
| Date/Publication: | 2024-09-25 10:20:03 UTC | 
Fast and elegant XML generation
Description
xmlwriter is an R package that provides a simple interface for creating XML documents
and fragments from R. It provides a simple elegant syntax for creating xml_fragments and furthermore
contains a feed-forward API that allows you to write xml.
Details
xmlwriter's xml generation from R lists is fast, implemented in C++ using Rcpp.
xmlwriter provides two different ways to create xml documents:
- a light weight R syntax using - xml_doc(),- xml_fragment()and- frag(), creating an xml fragment that can be easily translated into a xml string or- xml2::xml_documentobject
- a feed-forward API using - xmlbuilder()that allows you to create xml documents in a feed-forward manner.
It implements several xml2 methods:
-  as_xml_document.xml_fragment()
-  as_list.xml_fragment()
-  write_xml.xml_fragment()
Author(s)
Maintainer: Edwin de Jonge edwindjonge@gmail.com (ORCID)
See Also
Useful links:
Examples
doc <- xml_fragment(
  study = frag(
    .attr = c(id="1"),
    person = frag(
      .attr = c(id = "p1"),
      name = "John Doe",
      age = 30
    ),
    person = frag(
      name = "Jane Doe",
      age = 25,
      address = frag(street = "123 Main St", city = "Springfield"),
      "This is a text node"
    )
  )
)
print(doc)
if (require("xml2")){
  as_xml_document(doc)
}
# you can create a function to generate an xml fragment:
person_frag <- function(name, age, id){
  tag("person", id = id) / frag(
    name = name,
    age  = age,
    address = frag(
      street = "123 Main St",
      city = "Springfield"
    )
  )
}
# xml_doc is a xml_fragment with the restriction of having one root element
doc2 <- xml_doc("study") / (
  person_frag("John Doe", 30, "p1") +
  person_frag("Jane Doe", 25, "p2")
)
print(doc2)
if (require("xml2")){
  as_xml_document(doc2)
}
# a fragment can have multiple root elements
fgmt <- person_frag("John Doe", 30, id = "p1") +
  person_frag("Jane Doe", 25, id = "p2")
print(fgmt)
if (require("xml2")){
  # as_xml_document won't work because it expects a single root element,
  # so we retrieve a nodeset instead
  as_xml_nodeset(fgmt)
}
iris_xml <- xml_doc("fieldstudy", id = "iris", doi ="10.1111/j.1469-1809.1936.tb02137.x") /
  frag(
    source = "Fisher, R. A. (1936) The use of multiple measurements in
taxonomic problems. Annals of Eugenics, 7, Part II, 179–188.",
    data = data_frag(iris, row_tag = "obs")
  )
print(iris_xml, max_characters = 300)
if (require("xml2")){
  as_xml_document(iris_xml)
}
Add a child fragment to an existing xml_fragment
Description
Add a child fragment to an existing xml_fragment.
The child fragment can be a named frag element in which case the name
is used as the tag name, an unnamed element in which case the element
is added as a text node. This functionality is equivalent with the / operator.
Usage
add_child_fragment(x, ..., .frag = frag(...))
Arguments
| x | an  | 
| ... | nest named elements and characters to include in the fragment (see example) | 
| .frag | an xml_fragment to add as a child, overrides the ... argument | 
Value
the original xml_fragment() with the child added.
See Also
Other xml_fragment: 
as.character.xml_fragment(),
as_frag(),
as_xml_nodeset(),
data_frag(),
frag(),
xml_fragment()
Turn an xml_fragment into a character
Description
This function turns an xml_fragment into a character string, using
a performant c++ implementation.
Usage
## S3 method for class 'xml_fragment'
as.character(x, ...)
## S3 method for class 'xml_doc'
as.character(x, use_prolog = TRUE, ...)
Arguments
| x | object to be coerced or tested. | 
| ... | further arguments passed to or from other methods. | 
| use_prolog | if  | 
Value
a character with the xml representation of the fragment.
See Also
Other xml_fragment: 
add_child_fragment(),
as_frag(),
as_xml_nodeset(),
data_frag(),
frag(),
xml_fragment()
Convert a list to an xml fragment
Description
As frag is a helper function to convert a named list to an xml fragment, it
transforms all values to character, and recursively transforms nested lists.
as_frag can be used for flexible list created xml fragments, names of a
list turn into tags, and values into text nodes.
Usage
as_frag(x, ..., .attr = list(...))
Arguments
| x | named list that will be transformed into a fragment | 
| ... | optional attributes to be set on the parent of the fragment | 
| .attr | a list of attributes to add to the parent of the fragment, overrides the  | 
Value
xml_fragment() object as if specified with frag().
See Also
Other xml_fragment: 
add_child_fragment(),
as.character.xml_fragment(),
as_xml_nodeset(),
data_frag(),
frag(),
xml_fragment()
Transforms an xml_fragment into an xml_nodeset
Description
Using the xml2 package, this function transforms an xml_fragment into an xml_nodeset
Usage
as_xml_nodeset(x, ...)
Arguments
| x | an object created with  | 
| ... | reserved for future use | 
Value
an xml2::xml_nodeset object
See Also
Other xml_fragment: 
add_child_fragment(),
as.character.xml_fragment(),
as_frag(),
data_frag(),
frag(),
xml_fragment()
Other xml2: 
list_as_xml_document(),
list_as_xml_string()
Create an xml_fragment from a data.frame
Description
Create a xml_fragment() from a data.frame, in which each row is a set of xml elements (columns).
Usage
data_frag(df, row_tags = "row", .attr = NULL)
Arguments
| df | data frame that will be stored as set of xml elements | 
| row_tags | 
 | 
| .attr | optional  | 
Value
xml_fragment() object
See Also
Other xml_fragment: 
add_child_fragment(),
as.character.xml_fragment(),
as_frag(),
as_xml_nodeset(),
frag(),
xml_fragment()
Examples
persons <- data.frame(
  name = c("John Doe", "Jane Doe"),
  age = c(30, 25),
  stringsAsFactors = FALSE
)
df <- data_frag(persons, row_tag = "person")
print(df)
# setting ids on rows
persons <- data.frame(
  name = c("John Doe", "Jane Doe"),
  age = c(30, 25),
  id = c("p1", "p2"),
  stringsAsFactors = FALSE
)
df <- data_frag(
  persons[1:2],
  row_tag = "person",
  .attr = persons[3]
)
print(df)
# turning it into a document
doc <- xml_doc("study", id = "1") / frag(
  source = "homeless db",
  data = df
)
cat(as.character(doc))
add an element to an xmlbuilder object
Description
add an element to an xmlbuilder object
Usage
elem(tag, text = NULL, ...)
Arguments
| tag | name of element | 
| text | text contents of element | 
| ... | additional xml. attributes to be set | 
Value
an xmlbuilder object
Examples
xb <- elem("homeless") /
  elem("person") / (
     elem("name","John Doe") +
     elem("age",35)
  ) +
  elem("person") /(
    elem("name","Jane Doe") +
    elem("age", 30)
  ) +
  elem("person") / (
    elem("name","Jim Doe") +
    elem("age", 25) +
    elem("address") / (
      elem("street", "123 Main St") +
      elem("city", "Anytown") +
      elem("state", "CA") +
      elem("zip", 12345)
    )
  )
print(xb)
xb$end()
xb$end()
doc <- xb |> xml2::as_xml_document()
doc |> as.character() |> cat()
Create a frag xml_fragment
Description
Create a frag xml_fragment, that allows for multiple elements and nested
frags.
Usage
frag(..., .attr = NULL)
Arguments
| ... | nest named elements and characters to include in the fragment (see example) | 
| .attr | a list of attributes to add to the parent of the fragment | 
Value
an xml_fragment() object
See Also
Other xml_fragment: 
add_child_fragment(),
as.character.xml_fragment(),
as_frag(),
as_xml_nodeset(),
data_frag(),
xml_fragment()
Examples
doc <- xml_fragment(
  study = frag(
    .attr = c(id="1"),
    person = frag(
      .attr = c(id = "p1"),
      name = "John Doe",
      age = 30
    ),
    person = frag(
      name = "Jane Doe",
      age = 25,
      address = frag(street = "123 Main St", city = "Springfield"),
      "This is a text node"
    )
  )
)
print(doc)
if (require("xml2")){
  as_xml_document(doc)
}
# you can create a function to generate an xml fragment:
person_frag <- function(name, age, id){
  tag("person", id = id) / frag(
    name = name,
    age  = age,
    address = frag(
      street = "123 Main St",
      city = "Springfield"
    )
  )
}
# xml_doc is a xml_fragment with the restriction of having one root element
doc2 <- xml_doc("study") / (
  person_frag("John Doe", 30, "p1") +
  person_frag("Jane Doe", 25, "p2")
)
print(doc2)
if (require("xml2")){
  as_xml_document(doc2)
}
# a fragment can have multiple root elements
fgmt <- person_frag("John Doe", 30, id = "p1") +
  person_frag("Jane Doe", 25, id = "p2")
print(fgmt)
if (require("xml2")){
  # as_xml_document won't work because it expects a single root element,
  # so we retrieve a nodeset instead
  as_xml_nodeset(fgmt)
}
iris_xml <- xml_doc("fieldstudy", id = "iris", doi ="10.1111/j.1469-1809.1936.tb02137.x") /
  frag(
    source = "Fisher, R. A. (1936) The use of multiple measurements in
taxonomic problems. Annals of Eugenics, 7, Part II, 179–188.",
    data = data_frag(iris, row_tag = "obs")
  )
print(iris_xml, max_characters = 300)
if (require("xml2")){
  as_xml_document(iris_xml)
}
Convert a list to an xml_document
Description
list_as_xml_document is fast and efficient way to convert a list to an xml2::xml_document.
The preferred interface is to use xml_fragment() and xml_doc() to create xml fragments.
Usage
list_as_xml_document(x, ...)
Arguments
| x | a list as returned by  | 
| ... | reserved for future use | 
Details
list_to_xml_document is a much faster implementation of xml2::as_xml_document.list() method.
It writes the xml directly to a string buffer and then reads it back into an xml2::xml_document.
The function can be used in tandem with xml2::as_list() to convert R data structures.
Value
an xml2::xml_document
See Also
Other xml2: 
as_xml_nodeset(),
list_as_xml_string()
Examples
data <-
  list(
    study = list(
      person = list(
        name = "John Doe",
        age = "30"
      ),
      person = list(
        name = "Jane Doe",
        age = "25"
      )
    )
  )
list_as_xml_string(data)
if (require("xml2")){
  list_as_xml_document(data)
}
#note the xml_fragment function is more powerful to create lists
data <- xml_doc("study", id = "1") /
  frag(
    person = frag(
      name = "John Doe",
      age = "30"
    ),
    person = frag(
      name = "Jane Doe",
      age = "25"
    ),
    "This is a text node"
)
list_as_xml_string(data)
Convert a list to an xml string
Description
list_to_xml_string is fast and efficient way to convert a specific list to an xml string.
The preferred interface is to use xml_fragment() and xml_doc() to create xml fragments.
Usage
list_as_xml_string(x, ...)
Arguments
| x | a list as returned by  | 
| ... | reserved for future use | 
Details
This function is the working horse for turning xml_fragment(), xml_doc() and list
object into character xml strings and xml2::xml_document objects.
The input list format is identical to the format returned by xml2::as_list() function,
but much faster in generating an xml string from it. It writes the xml directly to a string buffer.
This function allows for easy conversion of R data structures
into xml format by creating the list structures in R and then converting them to xml.
The function can be used in tandem with xml2::as_list() to convert R data structures.
Value
a character string with the xml representation of the list
See Also
Other xml2: 
as_xml_nodeset(),
list_as_xml_document()
Examples
data <-
  list(
    study = list(
      person = list(
        name = "John Doe",
        age = "30"
      ),
      person = list(
        name = "Jane Doe",
        age = "25"
      )
    )
  )
list_as_xml_string(data)
if (require("xml2")){
  list_as_xml_document(data)
}
#note the xml_fragment function is more powerful to create lists
data <- xml_doc("study", id = "1") /
  frag(
    person = frag(
      name = "John Doe",
      age = "30"
    ),
    person = frag(
      name = "Jane Doe",
      age = "25"
    ),
    "This is a text node"
)
list_as_xml_string(data)
Read an XML fragment from a string
Description
Reads a xml fragment from a string, a connection or a raw vector using
xml2::read_xml(), and turns it into a xml_fragment().
Usage
read_fragment(x, ...)
Arguments
| x | A string, a connection or a raw vector | 
| ... | passed to  | 
Value
an object of class xml_fragment
Create a tag fragment
Description
Create a tag fragment with optional text and attributes
Usage
tag(tag, text = NULL, ..., .attr = list(...))
Arguments
| tag | character, the name of the tag | 
| text | character, the text to include in the tag | 
| ... | additional attributes to add to the tag | 
| .attr | a list of additional attributes to add to the tag, overrides the  | 
Value
an xml_fragment with the new tag added
Examples
tag("greeting", "hi", id = "hi")
tag("person", id = "1") / (tag("name", "John Doe") + tag("age", 35))
xml_fragment(person = frag(
  .attr = c(id = 1),
  name = "John Doe",
  age = 30
))   / tag("address", "Unknown")
a <- tag("person", id = 1) /
  xml_fragment(
    name ="John Doe",
    age = 30,
    address = frag(
      street = "123 Main St",
      city = "Springfield"
    )
  )
cat(as.character(a))
Create an xml_fragment with a root element, (kind of tag)
Description
Create an xml_fragment with a root element, (kind of tag)
Usage
xml_doc(root, ..., .attr = list(...))
Arguments
| root | the name of the root element | 
| ... | additional attributes to add to the tag | 
| .attr | a list of additional attributes to add to the tag, overrides the  | 
Value
an xml_fragment with the root element
Examples
tag("greeting", "hi", id = "hi")
tag("person", id = "1") / (tag("name", "John Doe") + tag("age", 35))
xml_fragment(person = frag(
  .attr = c(id = 1),
  name = "John Doe",
  age = 30
))   / tag("address", "Unknown")
a <- tag("person", id = 1) /
  xml_fragment(
    name ="John Doe",
    age = 30,
    address = frag(
      street = "123 Main St",
      city = "Springfield"
    )
  )
cat(as.character(a))
Create an XML fragment
Description
Create an XML fragment using readable R syntax, that can be used to create
a string, an xml2::xml_document or as a building block for more complex XML documents.
Usage
xml_fragment(...)
Arguments
| ... | nest named elements and characters to include in the fragment (see example) | 
Details
An xml_fragment is built using:
- named - fragelements, each name is a tag name, and the value is the contents of the tag, e.g.- name = "value"becomes- <name>value</name>. The value can be a nested- fragobject, a character string or a numeric value.
-  .attrattributes, which is set on current element, or on thefragwhere it is specified
- unnamed elements, which are added as text nodes. 
-  data_frag()function that can be used to convert a data.frame to an xml fragment, in which each row is a set of xml elements (columns).
-  tag()function that can be used to create a tag with attributes and (optional) text.
An xml_doc is a special case of an xml_fragment that contains exactly one
root element, and errors when this is not the case.
A resulting xml_fragment object can be converted to an xml2::xml_document with
xml2::as_xml_document() or to a character string with as.character(). Both
methods are fast using a performant c++ implementation.
Value
an xml_fragment, list object that can be converted to an xml2::xml_document
or character string
See Also
Other xml_fragment: 
add_child_fragment(),
as.character.xml_fragment(),
as_frag(),
as_xml_nodeset(),
data_frag(),
frag()
Examples
doc <- xml_fragment(
  study = frag(
    .attr = c(id="1"),
    person = frag(
      .attr = c(id = "p1"),
      name = "John Doe",
      age = 30
    ),
    person = frag(
      name = "Jane Doe",
      age = 25,
      address = frag(street = "123 Main St", city = "Springfield"),
      "This is a text node"
    )
  )
)
print(doc)
if (require("xml2")){
  as_xml_document(doc)
}
# you can create a function to generate an xml fragment:
person_frag <- function(name, age, id){
  tag("person", id = id) / frag(
    name = name,
    age  = age,
    address = frag(
      street = "123 Main St",
      city = "Springfield"
    )
  )
}
# xml_doc is a xml_fragment with the restriction of having one root element
doc2 <- xml_doc("study") / (
  person_frag("John Doe", 30, "p1") +
  person_frag("Jane Doe", 25, "p2")
)
print(doc2)
if (require("xml2")){
  as_xml_document(doc2)
}
# a fragment can have multiple root elements
fgmt <- person_frag("John Doe", 30, id = "p1") +
  person_frag("Jane Doe", 25, id = "p2")
print(fgmt)
if (require("xml2")){
  # as_xml_document won't work because it expects a single root element,
  # so we retrieve a nodeset instead
  as_xml_nodeset(fgmt)
}
iris_xml <- xml_doc("fieldstudy", id = "iris", doi ="10.1111/j.1469-1809.1936.tb02137.x") /
  frag(
    source = "Fisher, R. A. (1936) The use of multiple measurements in
taxonomic problems. Annals of Eugenics, 7, Part II, 179–188.",
    data = data_frag(iris, row_tag = "obs")
  )
print(iris_xml, max_characters = 300)
if (require("xml2")){
  as_xml_document(iris_xml)
}
Create a fast feed-forward XML builder
Description
This function creates an XML builder that allows you to create XML documents in a feed-forward manner.
xmlbuilder returns an object that has methods to create XML elements, text nodes, comments, and more.
Usage
xmlbuilder(
  allow_fragments = TRUE,
  use_prolog = !allow_fragments,
  strict = FALSE
)
Arguments
| allow_fragments | logical. Should a warning be issued if the XML document has multiple root elements?
Set to  | 
| use_prolog | logical. Should the XML prolog be included in the output?
Default is  | 
| strict | logical. Should the builder check for dangling nodes, default is  | 
Details
-  $start(tag, ...)(or$start_element) starts an element with a given tag and attributes.
-  $end()(or$end_element) ends the current element.
-  $element(tag, text, ...)creates an element with a given tag, text, and attributes.
-  $text(text)creates a text node.
-  $fragment(..., .attr)writes an xml fragment to the.
-  $comment(comment)creates a comment node.
-  $to_xml_string()returns the XML document or fragments(s) as a character vector.
Value
An object of class 'xmlbuilder
Examples
b <-xmlbuilder()
b$start("root")
  b$element("child1", "text1", attr1 = "value1")
  b$element("child2", "text2", attr2 = "value2")
  b$start("child3", attr3 = "value3")
    b$text("text3")
    b$element("child4", "text3", attr4 = "value4")
  b$end("child3")
b$end("root")
print(b)
if (require("xml2")) {
  # a builder can be converted to an xml_document using
  doc <- as_xml_document(b)
  # or equivalentlty
  doc <-
    b$to_xml_string() |>
    read_xml()
}
# build some xml fragments
fms <- xmlbuilder(allow_fragments = TRUE)
fms$start("person", id = "1")
  fms$element("name", "John Doe")
  fms$element("age", 30)
fms$end("person")
fms$start("person", id = "2")
  fms$element("name", "Jane Doe")
  fms$element("age", 25)
fms$end("person")
fms$start("person", id = "3")
  fms$element("name", "Jim Doe")
  fms$element("age", 35)
fms$end("person")
s <- fms$to_xml_string()
as.character(fms)
length(s) # three fragments
# print xml string of the second fragment
print(s[2])
if (require("xml2")){
  # convert to xml_nodes
  nodes <- fms$to_xml_node_list()
  length(nodes) # three nodes
  # show the second xml_node
  print(nodes[[2]])
}
# use fragments
xb <- xmlbuilder()
xb$start("study")
xb$fragment(
  person = frag(
    name = "John Doe",
    age = 30
  ),
  person = frag(
    name = "Jane Doe",
    age = 25
  )
)
xb$end("study")
xb