Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save StevenMMortimer/f84f6d853ea3c886ebe4 to your computer and use it in GitHub Desktop.
Save StevenMMortimer/f84f6d853ea3c886ebe4 to your computer and use it in GitHub Desktop.
library(RForcecom)
library(XML)
library(RCurl)
username <- "YOURS"
password <- "YOURS"
instanceURL <- "YOURS"
apiVersion <- "34.0"
session <- rforcecom.login(username, password, instanceURL, apiVersion)
# define metadata endpoint
rforcecom.api.getMetadataEndpoint <- function(apiVersion){
return(paste("services/Soap/m/", apiVersion, sep=""))
}
#helper function that converts a list of metadata to XML
metadataListToXML <- function(root, sublist, metatype=NULL){
for(i in 1:length(sublist)){
if (!is.null(metatype)){
this <- newXMLNode("Metadata", attrs = c(`xsi:type`=metatype), parent=root, suppressNamespaceWarning=T)
} else {
this <- newXMLNode(names(sublist)[i], parent=root)
}
if (typeof(sublist[[i]]) == "list"){
listToXML(this, sublist[[i]], metatype=NULL)
}
else{
xmlValue(this) <- sublist[[i]]
}
}
return(root)
}
#let's read just the Account object's metadata
object_names <- c('Account')
object_list <- as.list(object_names)
names(object_list) <- rep('fullNames', length(object_list))
#create XML for readMetadata call
root=newXMLNode("readMetadata",
namespaceDefinitions=c('http://soap.sforce.com/2006/04/metadata'))
root2=newXMLNode("metadataType", "CustomObject", parent=root)
metadataListToXML(root=root, sublist=object_list, metatype=NULL)
#build soapBody
soapBody <- paste0('<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<env:Header>
<SessionHeader xmlns="http://soap.sforce.com/2006/04/metadata">
<sessionId>',
session['sessionID'],
'</sessionId>
</SessionHeader>
</env:Header>
<env:Body>',
as(root, 'character'),
'</env:Body>
</env:Envelope>')
# perform request
# HTTP POST
h <- basicHeaderGatherer()
t <- basicTextGatherer()
httpHeader <- c("SOAPAction"="readMetadata", 'Content-Type'="text/xml")
curlPerform(url=paste0(session['instanceURL'], rforcecom.api.getMetadataEndpoint(apiVersion)),
postfields=soapBody, httpheader=httpHeader, headerfunction = h$update, writefunction = t$update, ssl.verifypeer=F)
x.root <- xmlRoot(xmlInternalTreeParse(t$value(), asText=T))
result_body <- xmlToList(x.root)[['Body']][['readMetadataResponse']]
#result_body should contain a list the metadata for the Account object
# now rename the object metatdata Custom_Account__c to create a new Account object copy
result_body$result$records$fullName <- 'Custom_Account__c'
# we need to change a few metadata configurations that are prevented during creation
d <- result_body$result$records
# remove default actionOverrides
d[which(names(d) %in% c("actionOverrides"))] <- NULL
# remove lingering attribute tag
d$.attrs <- NULL
# specify a plural label
d$pluralLabel <- 'Custom_Accounts'
# specify a name field
d$nameField <- list(displayFormat='AN-{0000}',
label='Custom_Account__c Name',
type='AutoNumber')
# set the deployment status
d$deploymentStatus <- 'Deployed'
# make a description to identify this easily in the UI setup tab
d$description <- 'created by the Metadata API'
#construct XML
root=newXMLNode("createMetadata", namespaceDefinitions=c('http://soap.sforce.com/2006/04/metadata'))
if(typeof(d[[1]]) != "list"){
d <- list(d)
}
metadataListToXML(root=root, sublist=d, metatype='CustomObject')
#construct SOAP
soapBody <- paste0('<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<env:Header>
<SessionHeader xmlns="http://soap.sforce.com/2006/04/metadata">
<sessionId>',
session['sessionID'],
'</sessionId>
</SessionHeader>
</env:Header>
<env:Body>',
as(root, 'character'),
'</env:Body>
</env:Envelope>')
# HTTP POST
h <- basicHeaderGatherer()
t <- basicTextGatherer()
httpHeader <- c("SOAPAction"="createMetadata", 'Content-Type'="text/xml")
curlPerform(url=paste0(session['instanceURL'], rforcecom.api.getMetadataEndpoint(apiVersion)),
postfields=soapBody, httpheader=httpHeader, headerfunction = h$update, writefunction = t$update, ssl.verifypeer=F)
x.root <- xmlRoot(xmlTreeParse(t$value(), asText=T))
result_body <- xmlToList(x.root)[['Body']][['createMetadataResponse']]
# result body look like this
# <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://soap.sforce.com/2006/04/metadata">
# <soapenv:Body>
# <createMetadataResponse>
# <result>
# <fullName>Custom_Account__c</fullName>
# <success>true</success>
# </result>
# </createMetadataResponse>
# </soapenv:Body>
# </soapenv:Envelope>
@Btibert3
Copy link

I am working through the code; this is great. I have worked with JSON in R in the past, but XML is new to me, so I am slowly wrapping my head around this. I am excited for what's possible. What do you think the best place to start is?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment