xmlwriter
is an R package that provides a fast and simple interface for
creating XML documents and fragments from R. It has a simple elegant
syntax for creating xml_fragment
s.
xmlwriter
's XML generation from R lists is fast, implemented in C++
using Rcpp
.
Details
xmlwriter
can be used as a companion to R packages
XML
or
xml2
which are both
wonderful packages optimized for parsing, querying and manipulating XML
documents. Both XML
and xml2
provide several ways for creating XML
documents, but they are not optimized for generating and writing XML.
Creating XML documents with XML
and xml2
can be a bit cumbersome,
mostly because it
forces the author to manipulate the XML document tree, obscuring the XML
structure of the document, and making it hard to read the XML that is
being generated. xml2
does provide a way to create XML documents from
R data structures using nested lists which is a powerful feature, but it
is not optimized for speed or readability.
xmlwriter
provides an intuitive interface for creating XML documents,
that mimics how XML is written in a text editor.
It has two different ways to create XML documents:
a light weight R syntax using
tag()
,frag()
,+
,/
anddata_frag()
, creating anxml_fragment()
, that can be easily translated into acharacter
orxml2::xml_document
object, or be used as a flexible building block for generating a larger XML document.an
xmlbuilder()
object that allows you to create XML documents in a feed-forward manner, withstart
andend
methods, giving you more control on the XML document structure, including XML comment, prolog etc.
It implements several xml2
methods:
as_xml_document.xml_fragment()
as_list.xml_fragment()
write_xml.xml_fragment()
Author
Maintainer: Edwin de Jonge edwindjonge@gmail.com (ORCID)
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)
#> {xml_fragment}
#> <study id="1">
#> <person id="p1">
#> <name>John Doe</name>
#> <age>30</age>
#> ...
if (require("xml2")){
as_xml_document(doc)
}
#> {xml_document}
#> <study id="1">
#> [1] <person id="p1">\n <name>John Doe</name>\n <age>30</age>\n</person>
#> [2] <person><name>Jane Doe</name><age>25</age><address><street>123 Main St</s ...
# 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)
#> {xml_doc,xml_fragment}
#> <?xml version='1.0' encoding='UTF-8'?>
#> <study>
#> <person id="p1">
#> <name>Joh...
if (require("xml2")){
as_xml_document(doc2)
}
#> {xml_document}
#> <study>
#> [1] <person id="p1">\n <name>John Doe</name>\n <age>30</age>\n <address>\n ...
#> [2] <person id="p2">\n <name>Jane Doe</name>\n <age>25</age>\n <address>\n ...
# a fragment can have multiple root elements
fgmt <- person_frag("John Doe", 30, id = "p1") +
person_frag("Jane Doe", 25, id = "p2")
print(fgmt)
#> {xml_fragment (2)}
#> [1]<person id="p1">
#> <name>John Doe</name>
#> <age>30</age>
#> <address>
#> <street...
#> [2]<person id="p2">
#> <name>Jane Doe</name>
#> <age>25</age>
#> <address>
#> <street...
#> ...
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)
}
#> {xml_nodeset (2)}
#> [1] <person id="p1">\n <name>John Doe</name>\n <age>30</age>\n <address>\n ...
#> [2] <person id="p2">\n <name>Jane Doe</name>\n <age>25</age>\n <address>\n ...
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)
#> {xml_doc,xml_fragment}
#> <?xml version='1.0' encoding='UTF-8'?>
#> <fieldstudy id="iris" doi="10.1111/j.1469-1809.1936.tb02137.x">
#> <source>Fisher, R. A. (1936) The use of multiple measurements in
#> taxonomic problems. Annals of Eugenics, 7, Part II, 179–188.</source>
#> <data>
#> <obs>
#> <Sepal.Length>5.1</Sepal.Length>
#> ...
if (require("xml2")){
as_xml_document(iris_xml)
}
#> {xml_document}
#> <fieldstudy id="iris" doi="10.1111/j.1469-1809.1936.tb02137.x">
#> [1] <source>Fisher, R. A. (1936) The use of multiple measurements in\ntaxonom ...
#> [2] <data>\n <obs>\n <Sepal.Length>5.1</Sepal.Length>\n <Sepal.Width>3 ...