Solved

Extract domain value from GDB file?


Hello everyone,

I'm looking for an easy way to extract domain value from a gdb for validation.

I know that you can use ArcGIS Pro to export a XML schema from a GDB, but I want to skip that step.

I tried to use Schema Reader, but it doesn't give me the full domain values in the attributs.

Anyone have an idea ?

 

Thanks

icon

Best answer by ebygomm 16 August 2022, 13:20

View original

10 replies

Userlevel 5
Badge +29

You'll need to use some python to extract the domain values - https://pro.arcgis.com/en/pro-app/2.8/arcpy/data-access/listdomains.htm

Userlevel 6
Badge +33

This could be done using FME in 2019 but this does not work anymore so Python is the way to go. I'm by no means an expert but this works for me.

import fme
import fmeobjects
import arcpy
                
def processFeature(feature):
    pass
 
class FeatureProcessor(object):
    def __init__(self):
        pass
        
    def input(self,feature):
        print("TEST TEST")
        domains = arcpy.da.ListDomains("C:/Temp/test.gdb")
        for domain in domains:
            print('Domain name: {0}'.format(domain.name))
            if domain.domainType == 'CodedValue':
                coded_values = domain.codedValues
                for val, desc in coded_values.items():
                    #create a feature for each coded value
                    newFeature = fmeobjects.FMEFeature()
                    #create attribute DomainName
                    newFeature.setAttribute('DomainName',domain.name)
                    #create attribute DomainType
                    newFeature.setAttribute('DomainType',"CodedValue")
                    #create attribute DomainCode
                    newFeature.setAttribute('DomainCode',val)
                    #create attribute DomainDescription
                    newFeature.setAttribute('DomainDescription',desc)
                    #output each feature
                    self.pyoutput(newFeature)
            elif domain.domainType == 'Range':
                #create a feature for each minimum range value
                newFeature = fmeobjects.FMEFeature()
                #create attribute DomainName
                newFeature.setAttribute('DomainName',domain.name)
                #create attribute DomainType
                newFeature.setAttribute('DomainType',"Range")
                print(domain.range[0])
                #create attribute RangeMin
                newFeature.setAttribute('RangeMin',domain.range[0])
                #create attribute RangeMax
                newFeature.setAttribute('RangeMax',domain.range[1])
                #output each feature
                self.pyoutput(newFeature)
                
    def close(self):
        pass
        

 

This could be done using FME in 2019 but this does not work anymore so Python is the way to go. I'm by no means an expert but this works for me.

import fme
import fmeobjects
import arcpy
                
def processFeature(feature):
    pass
 
class FeatureProcessor(object):
    def __init__(self):
        pass
        
    def input(self,feature):
        print("TEST TEST")
        domains = arcpy.da.ListDomains("C:/Temp/test.gdb")
        for domain in domains:
            print('Domain name: {0}'.format(domain.name))
            if domain.domainType == 'CodedValue':
                coded_values = domain.codedValues
                for val, desc in coded_values.items():
                    #create a feature for each coded value
                    newFeature = fmeobjects.FMEFeature()
                    #create attribute DomainName
                    newFeature.setAttribute('DomainName',domain.name)
                    #create attribute DomainType
                    newFeature.setAttribute('DomainType',"CodedValue")
                    #create attribute DomainCode
                    newFeature.setAttribute('DomainCode',val)
                    #create attribute DomainDescription
                    newFeature.setAttribute('DomainDescription',desc)
                    #output each feature
                    self.pyoutput(newFeature)
            elif domain.domainType == 'Range':
                #create a feature for each minimum range value
                newFeature = fmeobjects.FMEFeature()
                #create attribute DomainName
                newFeature.setAttribute('DomainName',domain.name)
                #create attribute DomainType
                newFeature.setAttribute('DomainType',"Range")
                print(domain.range[0])
                #create attribute RangeMin
                newFeature.setAttribute('RangeMin',domain.range[0])
                #create attribute RangeMax
                newFeature.setAttribute('RangeMax',domain.range[1])
                #output each feature
                self.pyoutput(newFeature)
                
    def close(self):
        pass
        

 

Thank you very much @nielsgerrits​  I'll try it. You are being very helpful.

You'll need to use some python to extract the domain values - https://pro.arcgis.com/en/pro-app/2.8/arcpy/data-access/listdomains.htm

Thank you @hkingsbury​  I'll have a look at the article.

Badge +2

@Anh Phuong Tran​ If you can tolerate step of exporting the Esri Geodatabase XML Workspace document (Schema Only) using Esri ArcCatalog, as described here ,then this article has the FME workspace configured with the XML reader

Userlevel 1
Badge +21

@Anh Phuong Tran​ If you can tolerate step of exporting the Esri Geodatabase XML Workspace document (Schema Only) using Esri ArcCatalog, as described here ,then this article has the FME workspace configured with the XML reader

It's also possible to use arcpy in a python caller to generate the xml if you don't want that step.

I can probably find a working example if interested

It's also possible to use arcpy in a python caller to generate the xml if you don't want that step.

I can probably find a working example if interested

Yes, I would like to know about that example as well. Will make better automation.

Thanks in advance @ebygomm​ 

Userlevel 1
Badge +21

It's also possible to use arcpy in a python caller to generate the xml if you don't want that step.

I can probably find a working example if interested

So this is the sort of workflow I've used previouslyimageIt takes a GDB location, generates an xml file saved in a temp location then reads in the domain values in that file and processes them into features

import fme
import fmeobjects
import arcpy
 
class FeatureProcessor(object):
 
    def __init__(self):
        pass
 
    def input(self, feature):
        in_data = feature.getAttribute('input_GDB')
        out_file = feature.getAttribute('temppath')
        export_option = 'SCHEMA_ONLY'
        storage_type = 'NORMALIZED'
        export_metadata = 'NO_METADATA'
        # Execute ExportXMLWorkspaceDocument
        arcpy.ExportXMLWorkspaceDocument_management(in_data, out_file, export_option, storage_type, export_metadata)
        self.pyoutput(feature)
    def close(self):
        pass

 The FeatureReader is a bit of a pain to setup, as you need to point it to an already created xml file first, before you can swap to use the temp path name.

Userlevel 1
Badge +21

Thank you @hkingsbury​  I'll have a look at the article.

Python to extract domain values for use in FME - (I've always used the xml method as often when performing validation there are a number of other things I check from the xml as well so not sure whether this code will cover everything)

import fme
import fmeobjects
import arcpy
 
class FeatureProcessor(object):
    def __init__(self):
        pass
    def input(self,feature):
        self.domains = arcpy.da.ListDomains(feature.getAttribute('input_GDB'))
        
    def close(self):
        for domain in self.domains:
          
            if domain.domainType == 'CodedValue':
                coded_values = domain.codedValues
                for val, desc in coded_values.items():
                    feature = fmeobjects.FMEFeature()
                    feature.setAttribute("DomainName",domain.name)
                    feature.setAttribute("DomainType",'CodedValue')
                    feature.setAttribute("val",val)
                    feature.setAttribute("desc",desc)
                    self.pyoutput(feature)
            
            elif domain.domainType == 'Range':
                    feature = fmeobjects.FMEFeature()
                    feature.setAttribute("DomainName",domain.name)
                    feature.setAttribute("DomainType",'Range')
                    feature.setAttribute("minrange",domain.range[0])
                    feature.setAttribute("maxrange",domain.range[1])
                    self.pyoutput(feature)

 

It's also possible to use arcpy in a python caller to generate the xml if you don't want that step.

I can probably find a working example if interested

Perfect, this should work nicely.

Thank you @ebygomm​ for helping me. It is much appreciated.

Reply