I'm poking around, writing a Python script to fetch ".reportType" XML files for all ReportTypes in an org and then do various things to those files.

First up is figuring out what tables they include.

By parsing the raw XML file, I'm able to easily get output that looks like this:

4 table(s)
['School__c', 'School__c.FancyPackage__Contacts__r.FancyPackage__Applications__r.Transcripts__r', 'School__c.FancyPackage__Contacts__r.FancyPackage__Applications__r', 'School__c.FancyPackage__Contacts__r']

And I can see from poking around the web user interface that there is indeed:

  • a lookup field to the "FancyPackage__Appli__c" object on the "Trscpt__c" object with a Namespace Prefix of FancyPackage and a Child Relationship Name of Transcripts
  • a lookup field to the "Contact" object on the "FancyPackage__Appli__c" object with a Namespace Prefix of FancyPackage and a Child Relationship Name of Applications
  • a lookup field to the "School__c" object on the "Contact" object with a Namespace Prefix of FancyPackage and a Child Relationship Name of Contacts

What I actually want as output is:

4 table(s)
['School__c', 'Trscpt__c', 'FancyPackage__Appli__c', 'Contact']

That way, it'll be easy to quickly figure out all reports that use the"FancyPackage__Appli__c" so that when we need to quickly add/remove fields from all such reports, it's not such guesswork. (Not to mention, I can probably script editing the XML from there.)

Question is, what's the simplest way, over various APIs Salesforce provides, to get the data I need to do this translation?

I'm sure I could download the XML for every single object in my org, then parse it, setting aside relevant details from lookup & master-detail fields I find therein. But that seems like a lot of overhead.

Is there a less messy interface I'm not familiar with?


The easiest way to do this is going to be tracing the relationship fields through Describe API results. Fortunately, this is very easy to do using the Python simple_salesforce module. Once you establish a Salesforce object (the connection) you can do

 describe = sf.Contact.describe()

That result object contains all the field data that you'd normally get from the Describe API. There's a list of fields in fields, each field being a Python dict.

Each field entry has a type, which is reference for a lookup relationship, and a list referenceTo, which contains the API names of the one or several objects (several in the case of polymorphic lookups) to which the field looks up.

You could take those relationship paths and break them up by the period separator and use those to walk the Describe data and obtain the target Sobject names.

There's also a global describe() method you can use to get a list of all the Sobjects in the system for fully dynamic access, and you can instantiate the module's named Sobject proxies dynamically via the SFType class.

Experimenting with the describe methods in a Python console can be really helpful because it is a fairly deep data structure.

simple_salesforce: https://github.com/simple-salesforce/simple-salesforce

  • Thanks; that sounds promising. I did the whole "download every object and parse its XML files" route, and it worked, but that download is SLOW compared to just downloading ReportType XML files, so I'll definitely look into it. – k.. Apr 10 '18 at 15:48
  • 1
    Describe API is definitely a lot faster than the Metadata API + tons of XML parsing and walking! – David Reed Apr 10 '18 at 15:50
  • 1
    If you cache the describes for each object in a dict keyed on object name, it'll be fast. I wouldn't worry too much about optimizing that part of the solution beyond caching. – David Reed Apr 12 '18 at 2:07
  • 1
    As for the reports, I would probably just use the Metadata API. You might be able to use the Analytics API via REST, but I am less familiar with that route and not sure it's any easier - report metadata is always pretty complex. – David Reed Apr 12 '18 at 2:36
  • 1
    You may want to open a new question on that - there are some fun complexities around report sharing. – David Reed Apr 16 '18 at 13:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.