How to create xml from R objects, e.g., is there a 'listToXml' function?

后端 未结 4 941
暗喜
暗喜 2020-11-30 08:52

R\'s XML package has an xmlToList function, but does not have the reverse, is there a function for R that will convert a list to an XML object?

I would like somethin

相关标签:
4条回答
  • 2020-11-30 09:13

    Here is the listToXML function that we ended up creating

    At first I adapted the answer by @Jeff

    listToXml <- function(item, tag){
      if(typeof(item)!='list')
        return(xmlNode(tag, item))
      xml <- xmlNode(tag)
      for(name in names(item)){
        xml <- append.xmlNode(xml, listToXml(item[[name]], name))
      }
      return(xml)
    }
    

    But since the function has benefited from further development:

    ##' Convert List to XML
    ##'
    ##' Can convert list or other object to an xml object using xmlNode
    ##' @title List to XML
    ##' @param item 
    ##' @param tag xml tag
    ##' @return xmlNode
    ##' @export
    ##' @author David LeBauer, Carl Davidson, Rob Kooper
    listToXml <- function(item, tag) {
      # just a textnode, or empty node with attributes
      if(typeof(item) != 'list') {
        if (length(item) > 1) {
          xml <- xmlNode(tag)
          for (name in names(item)) {
            xmlAttrs(xml)[[name]] <- item[[name]]
          }
          return(xml)
        } else {
          return(xmlNode(tag, item))
        }
      }
    
      # create the node
      if (identical(names(item), c("text", ".attrs"))) {
        # special case a node with text and attributes
        xml <- xmlNode(tag, item[['text']])
      } else {
        # node with child nodes
        xml <- xmlNode(tag)
        for(i in 1:length(item)) {
          if (names(item)[i] != ".attrs") {
            xml <- append.xmlNode(xml, listToXml(item[[i]], names(item)[i]))
          }
        }    
      }
    
      # add attributes to node
      attrs <- item[['.attrs']]
      for (name in names(attrs)) {
        xmlAttrs(xml)[[name]] <- attrs[[name]]
      }
      return(xml)
    }
    
    0 讨论(0)
  • 2020-11-30 09:19

    needed to make some changes to the function for cases where there are multiple elements (i.e. lists with no name entry):

    ##' Convert List to XML
    ##'
    ##' Can convert list or other object to an xml object using xmlNode
    ##' @title List to XML
    ##' @param item 
    ##' @param tag xml tag
    ##' @return xmlNode
    ##' @export
    ##' @author David LeBauer, Carl Davidson, Rob Kooper, julien colomb
    listToXml <- function(item, tag) {
      # just a textnode, or empty node with attributes
      if(typeof(item) != 'list') {
        if (length(item) > 1) {
          xml <- xmlNode(tag)
          for (name in names(item)) {
            xmlAttrs(xml)[[name]] <- item[[name]]
          }
          return(xml)
        } else {
          return(xmlNode(tag, item))
        }
      }
    
      # create the node
      if (identical(names(item), c("text", ".attrs"))) {
        # special case a node with text and attributes
        xml <- xmlNode(tag, item[['text']])
      } else {
        # node with child nodes
        xml <- xmlNode(tag)
        for(i in 1:length(item)) {
          if (length (item[[i]]) == 0) {}
          else if (names(item)[i] != ".attrs") {
            print(i)
            if (is.null (names(item[[i]][1])) ){
              print(i)
              for (j in c(1:length (item[[i]]))){
                child <- xmlNode(names(item)[i])
                xmlValue(child) <- item[[i]][j]
                xml <- append.xmlNode(xml,child)
              }
            } else {
              xml <- append.xmlNode(xml, listToXml(item[[i]], names(item)[i]))
            }
    
          }
        }    
      }
    
      # add attributes to node
      attrs <- item[['.attrs']]
      for (name in names(attrs)) {
        xmlAttrs(xml)[[name]] <- attrs[[name]]
      }
      return(xml)
    }
    
    0 讨论(0)
  • 2020-11-30 09:31

    I am surprised that no function already exists for this -- surely there's something already packaged out there.

    Regardless, I use the following script to accomplish this:

    root <- newXMLNode("root")
    li <- list(a = list(aa = 1, ab=2), b=list(ba = 1, bb= 2, bc =3))
    listToXML <- function(node, sublist){
        for(i in 1:length(sublist)){
            child <- newXMLNode(names(sublist)[i], parent=node);
    
            if (typeof(sublist[[i]]) == "list"){
                listToXML(child, sublist[[i]])
            }
            else{
                xmlValue(child) <- sublist[[i]]
            }
        } 
    }
    listToXML(root, li)
    

    You can use the XML::saveXML() function to grab this as a character, if you prefer.

    0 讨论(0)
  • 2020-11-30 09:38

    The function newXMLNode does what you need, i.e., write XML output. See the detailed help and examples in ?newXMLNode for more details. Here is a short extract:

    library(XML)    
    top = newXMLNode("a")
    newXMLNode("b", attrs=c(x=1, y='abc'), parent=top)
    newXMLNode("c", "With some text", parent=top)
    top
    

    Resulting in:

    <a>
      <b x="1" y="abc"/>
      <c>With some text</c>
    </a> 
    
    0 讨论(0)
提交回复
热议问题