If case anyone else is interested, Duncan Temple Lang answered my
question on the ggobi-help mailing list. The code he provided is pasted
into the body of this email, below. It requires the the XML package
(from http://www.stats.ox.ac.uk/pub/RWin/ for Windows and
www.omegahat.org/RSXML/ for everything else). It works with data.frames
with factor and numeric columns. Character columns need to be coverted
to factor.
It sounds like this code will be available in the next build of Rggobi
for Windows, which Duncan informs me is in the not too distant future.
Thanks, Duncan!
Jim
> Jim Rogers wrote:
> >
> > Hi,
> >
> > Has anyone out there written a function to take an R data.frame as
> > input and generate XML that conforms to the DTD for ggobi
> > ("ggobi.dtd")? In other words, like a simple version of the
> writeSDML
> > function in the StatDataML package, but using ggobi.dtd instead of
> > StatDataML.dtd.
> >
> > It looks easy to write such a function to handle
> data.frames with only
> > numeric data, but a bit of work with character and factor data.
> >
> > Thanks,
> > Jim Rogers
#
# This can be used to write out an XML description of one or more
# data frames into GGobi's data format.
#
# Could use another output tree mechanism such as xmlTree(),
xmlOutputBuffer(), etc.
# e.g.
# dom <- xmlTree("ggobidata", attrs = c(count = length(args)))
writeDataXML <-
function(..., dom = xmlOutputDOM("ggobidata", attrs = c(count
length(args))))
{
library(XML)
args <- list(...)
for(i in 1:length(args)) {
name <- names(args)[i]
# if this is "", use the deparse() version
addXMLDataset(args[[i]], name, dom)
}
dom
}
addXMLDataset <-
function(data, name, dom, description = NULL, asElements = TRUE)
{
dom$addTag("data", attrs=c(name=name), close = FALSE)
dom$addTag("description", description)
dom$addTag("variables", attrs=c(count = ncol(data)), close=FALSE)
for(i in names(data)) {
if(inherits(data[[i]], "factor")) {
dom$addTag("categorical", attrs = c(name = i), close = FALSE)
levs <- levels(data[[i]])
dom$addTag("levels", attrs = c(count=length(levs)), close
FALSE)
for(j in 1:length(levs)) {
dom$addTag("level", levs[j], attrs= c(value=j))
}
dom$closeTag("levels")
dom$closeTag("categorical")
} else
dom$addTag("realvariable", attrs = c(name = i))
}
dom$addTag("records", attrs =c(count = nrow(data)), close = FALSE)
rownames <- dimnames(data)[[1]]
for(i in 1:nrow(data)) {
# If we want to put <el>value</el><el>value</el>
within the
<record>
# we'll have to do it one at a time!
if(asElements) {
dom$addTag("record", close = FALSE)
for(r in data[i,]) {
tag <- switch(typeof(r), double="real",
integer="int")
dom$addTag(tag, r)
}
dom$closeTag("record")
} else
dom$addTag("record", paste(data[i,], collapse=" "),
attrs = c(label
= rownames[i]), close = TRUE)
}
dom$closeTag("records")
dom$closeTag("data")
}
###
# Example:
###
data(mtcars)
b = writeDataXML(mtcars)
sink("mtcars.xml")
cat("<?xml version='1.0'?>\n")
b$value()
sink()