Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Here is a more generic approach. Every node is classified as one of three cases:</p> <ul> <li>If the node name is of kind <code>rows</code>, then the data frames from child nodes will result in different rows of the result.</li> <li>If the node name is of kind <code>cols</code>, then the data frames from child nodes will result in different columns of the result.</li> <li>If the node name is of kind <code>value</code>, then a data frame with a single value will be constructed, using the node name as the column name and the node value as the column value.</li> <li>For all three cases, attributes of the node will be added to the data frame.</li> </ul> <p>The call for your application is given towards the bottom.</p> <pre class="lang-r prettyprint-override"><code>library(XML) zeroColSingleRow &lt;- function() { res &lt;- data.frame(dummy=NA) res$dummy &lt;- NULL stopifnot(nrow(res) == 1, ncol(res) == 0) return (res) } xml2df &lt;- function(node, classifier) { if (! inherits(node, c("XMLInternalElementNode", "XMLElementNode"))) { return (zeroColSingleRow()) } kind &lt;- classifier(node) if (kind == "rows") { cdf &lt;- lapply(xmlChildren(node), xml2df, classifier) if (length(cdf) == 0) { res &lt;- zeroColSingleRow() } else { names &lt;- unique(unlist(lapply(cdf, colnames))) cdf &lt;- lapply(cdf, function(i) { missing &lt;- setdiff(names, colnames(i)) if (length(missing) &gt; 0) { i[missing] &lt;- NA } return (i) }) res &lt;- do.call(rbind, cdf) } } else if (kind == "cols") { cdf &lt;- lapply(xmlChildren(node), xml2df, classifier) if (length(cdf) == 0) { res &lt;- zeroColSingleRow() } else { res &lt;- cdf[[1]] if (length(cdf) &gt; 1) { for (i in 2:length(cdf)) { res &lt;- merge(res, cdf[[i]], by=NULL) } } } } else { stopifnot(kind == "value") res &lt;- data.frame(xmlValue(node)) names(res) &lt;- xmlName(node) } if (ncol(res) == 0) { res &lt;- zeroColSingleRow() } attr &lt;- xmlAttrs(node) if (length(attr) &gt; 0) { attr &lt;- do.call(data.frame, as.list(attr)) res &lt;- merge(attr, res, by=NULL) } rownames(res) &lt;- NULL return(res) } doc&lt;-xmlParse("test.xml") xml2df(xmlRoot(doc), function(node) { name &lt;- xmlName(node) if (name %in% c("watchers", "results")) return("rows") # make sure to treat results/result different from watcher/result if (name %in% c("watcher", "result") &amp;&amp; xmlName(xmlParent(node)) == paste0(name, "s")) return("cols") return("value") }) </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload