Get all layer names

6621
16
Jump to solution
10-21-2015 12:19 AM
MuneemHabiba
New Contributor

I have been trying for more then 4 hours but i am cinfused how i should get all layer names from gdb files. I am using latest file goedatabase API but there is no help that i can found to get all layernames in gdb. Then i have to read further each layer items.

Any help will be highly appreciated. I am attaching my gdb file

Tags (2)
0 Kudos
1 Solution

Accepted Solutions
VinceAngelo
Esri Esteemed Contributor

Okay, here's an [updated] standalone example.  The meat of the code is:

/* .. Describe top level contents
 */
        if ((hr = geodatabase.GetChildDatasets(parentPath,datasetType,children)) != S_OK) {
                msg = L"GetChildDatasets failed";
                ErrorInfo::GetErrorDescription(hr,errorText);
                goto bailout;
        }

/* .. List contents (or their children)
 */
        count = children.size();
        for (size_t i = 0; i < count; i++) {

        /* .. Use "OpenTable" to distinguish between FDS and FC
         */
                Table table;
                if ((hr = geodatabase.OpenTable(children.at(i),table)) != S_OK) {
                        numFDS++;
                        std::vector<std::wstring> grands;
                        fprintf(stdout,"  %S:\n",children.at(i).c_str());
                        if ((hr = geodatabase.GetChildDatasets(children.at(i),datasetType,grands)) == S_OK) {
                                size_t kount = grands.size();
                                for (size_t j = 0; j < kount; j++) {
                                        fprintf(stdout,"    %S\n",grands.at(j).c_str());
                                        numFCs++;
                        }       }
                } else {
                        fprintf(stdout,"  %S\n",children.at(i).c_str());
                        numFCs++;
        }       }

Using your dataset I get the folowing output:

norge% ./fgdbList ./WS_Data.gdb "\"
  \WSInfrastructure:
    \WSInfrastructure\ww_Pump
    \WSInfrastructure\sw_Casing
    \WSInfrastructure\sw_Catchbasin
    \WSInfrastructure\sw_CatchbasinLead
    \WSInfrastructure\sw_CleanOut
    \WSInfrastructure\sw_ControlValve
    \WSInfrastructure\sw_Culvert
    \WSInfrastructure\sw_Detention
    \WSInfrastructure\sw_DischargePoint
    \WSInfrastructure\sw_Fitting
    \WSInfrastructure\sw_Inlet
    \WSInfrastructure\sw_ManagementPond
    \WSInfrastructure\sw_Manhole
    \WSInfrastructure\sw_NetworkStructure
    \WSInfrastructure\sw_OpenDrain
    \WSInfrastructure\sw_StormwaterMain
    \WSInfrastructure\sw_SystemValve
    \WSInfrastructure\sw_VirtualDrainline
    \WSInfrastructure\w_ConnectionPoint
    \WSInfrastructure\w_CurbStop
    \WSInfrastructure\w_FacilityFootprint
    \WSInfrastructure\w_Flowmeter
    \WSInfrastructure\w_Hydrant
    \WSInfrastructure\w_Node
    \WSInfrastructure\w_PressureDistrictExisting
    \WSInfrastructure\w_PressureDistrictPlanned
    \WSInfrastructure\w_ProductionWell
    \WSInfrastructure\w_Pump
    \WSInfrastructure\w_PumpingStation
    \WSInfrastructure\w_SamplingStation
    \WSInfrastructure\w_TreatmentPlant
    \WSInfrastructure\w_UndergroundEnclosure
    \WSInfrastructure\w_Valve
    \WSInfrastructure\w_Watermain
    \WSInfrastructure\w_WaterStorage
    \WSInfrastructure\ww_ConnectionPoint
    \WSInfrastructure\ww_EqualizationTank
    \WSInfrastructure\ww_FacilityFootprint
    \WSInfrastructure\ww_FlowControl
    \WSInfrastructure\ww_Flowmeter
    \WSInfrastructure\ww_Manhole
    \WSInfrastructure\ww_PollutionControlPlant
    \WSInfrastructure\ww_PumpingStation
    \WSInfrastructure\ww_PumpYR
    \WSInfrastructure\ww_Sewershed
    \WSInfrastructure\ww_UndergroundEnclosure
    \WSInfrastructure\ww_Valve
    \WSInfrastructure\ww_WastewaterMain
  \IlluminationWS
  \AssumptionArea

 FGDB Path = ./WS_Data.gdb
Containers = 1
   Num FCs = 50

norge% ./fgdbList ./WS_Data.gdb "\" "Feature Class"
  \IlluminationWS
  \AssumptionArea

 FGDB Path = ./WS_Data.gdb
Containers = 0
   Num FCs = 2

If you want to describe the fields of each table, you've got a starting point (just make sure you capture both paths where numFCs is incremented).

- V

UPDATED with a new zipfile and new source name, without timing and with corrected counting 21:24 EDT

View solution in original post

16 Replies
VinceAngelo
Esri Esteemed Contributor

The issue is one of terminology -- File Geodatabases do not store layers.  "Layers" are drawing rules associated  with a feature class (which could come from any number of sources, including File GDB).

In the FGDB API, the list of feature classes is accessed by a call to Geodatabase.GetChildDatasets().  It will generate a list of all standalone feature classes and all feature datasets, which can each be inventoried with another call (specifying the FDS as the parentPath).

- V

RebeccaStrauch__GISP
MVP Emeritus

Muneem,

If interested, the second tool (from left) on my Toolbar addin will do an inventory of various types of feature classes (including shapes and coverages, and within FGDBs) and give you a .csv, .xls and a .txt report as output.

Python addin for data inventory and “broken-link” repair.

It uses da.walk so will go thru all the subdirectories too, so if you need to isolate one FGDB within a directory, copy it to a new folder --- that would be the easiest.  However, the reports will list the path, so you can determine where it came from.  Sample from one of my FCInventoryYYYYMMDD_HHMM.txt output files

0 Kudos
VinceAngelo
Esri Esteemed Contributor

This is the File Geodatabase API "place", so C++ and C# code is the way to solve questions, but ArcPy can be used to validate the FGDBAPI code.

- V

0 Kudos
RebeccaStrauch__GISP
MVP Emeritus

Oops, sorry about that Vince.  I saw the code by Luke above was ArcPy, so just added mine.  I didn't realized that FGDBAPI was C (and didn't notice anything on the "place" overview page....not that I had looked there before your note.  Want me to delete my comment about the arcpy addin above?

0 Kudos
VinceAngelo
Esri Esteemed Contributor

If it were 'C', I'd have my solution posted already ("The impossible we do immediately, C++ takes a bit longer").  No need to delete, since it does form a check of the FGDBAPI solution.

- V

VinceAngelo
Esri Esteemed Contributor

Here's the core of the code I whipped up (that is, unfortunately, failing on Linux):

        if ((hr = OpenGeodatabase(gdbPath,geodatabase)) != S_OK) {

                msg = L"Geodatabase not found";

                goto bailout;

        }

        if ((hr = geodatabase.GetChildDatasets(parentPath,datasetType,children)) != S_OK) {

                msg = L"GetChildDatasets failed";

                goto bailout;

        }

You'd need to issue a second.GetChildDatasets on each of the first vector of children to pick up grandchildren.

The "items" you want to extract are called "fields"; you can use Table::GetFieldInformation then FieldInfo getters. In fact, you could probably use GetFieldInformation to determine if you needed to drill deeper...

If I get my code working I'll add it here.

[Update: Important coding tip: backslashes don't need to be trapped when in quotes on Linux.  The root parentPath is "\" (not "/" or ""),

so a search on "\\" is correct in C++/C#, but should be "\" as a command line parameter]

- V

0 Kudos
HarmenKampinga
New Contributor III

Do you have the FME tool from SAFE software?

Than have a look at this: FME Community Answers

0 Kudos
VinceAngelo
Esri Esteemed Contributor

Okay, here's an [updated] standalone example.  The meat of the code is:

/* .. Describe top level contents
 */
        if ((hr = geodatabase.GetChildDatasets(parentPath,datasetType,children)) != S_OK) {
                msg = L"GetChildDatasets failed";
                ErrorInfo::GetErrorDescription(hr,errorText);
                goto bailout;
        }

/* .. List contents (or their children)
 */
        count = children.size();
        for (size_t i = 0; i < count; i++) {

        /* .. Use "OpenTable" to distinguish between FDS and FC
         */
                Table table;
                if ((hr = geodatabase.OpenTable(children.at(i),table)) != S_OK) {
                        numFDS++;
                        std::vector<std::wstring> grands;
                        fprintf(stdout,"  %S:\n",children.at(i).c_str());
                        if ((hr = geodatabase.GetChildDatasets(children.at(i),datasetType,grands)) == S_OK) {
                                size_t kount = grands.size();
                                for (size_t j = 0; j < kount; j++) {
                                        fprintf(stdout,"    %S\n",grands.at(j).c_str());
                                        numFCs++;
                        }       }
                } else {
                        fprintf(stdout,"  %S\n",children.at(i).c_str());
                        numFCs++;
        }       }

Using your dataset I get the folowing output:

norge% ./fgdbList ./WS_Data.gdb "\"
  \WSInfrastructure:
    \WSInfrastructure\ww_Pump
    \WSInfrastructure\sw_Casing
    \WSInfrastructure\sw_Catchbasin
    \WSInfrastructure\sw_CatchbasinLead
    \WSInfrastructure\sw_CleanOut
    \WSInfrastructure\sw_ControlValve
    \WSInfrastructure\sw_Culvert
    \WSInfrastructure\sw_Detention
    \WSInfrastructure\sw_DischargePoint
    \WSInfrastructure\sw_Fitting
    \WSInfrastructure\sw_Inlet
    \WSInfrastructure\sw_ManagementPond
    \WSInfrastructure\sw_Manhole
    \WSInfrastructure\sw_NetworkStructure
    \WSInfrastructure\sw_OpenDrain
    \WSInfrastructure\sw_StormwaterMain
    \WSInfrastructure\sw_SystemValve
    \WSInfrastructure\sw_VirtualDrainline
    \WSInfrastructure\w_ConnectionPoint
    \WSInfrastructure\w_CurbStop
    \WSInfrastructure\w_FacilityFootprint
    \WSInfrastructure\w_Flowmeter
    \WSInfrastructure\w_Hydrant
    \WSInfrastructure\w_Node
    \WSInfrastructure\w_PressureDistrictExisting
    \WSInfrastructure\w_PressureDistrictPlanned
    \WSInfrastructure\w_ProductionWell
    \WSInfrastructure\w_Pump
    \WSInfrastructure\w_PumpingStation
    \WSInfrastructure\w_SamplingStation
    \WSInfrastructure\w_TreatmentPlant
    \WSInfrastructure\w_UndergroundEnclosure
    \WSInfrastructure\w_Valve
    \WSInfrastructure\w_Watermain
    \WSInfrastructure\w_WaterStorage
    \WSInfrastructure\ww_ConnectionPoint
    \WSInfrastructure\ww_EqualizationTank
    \WSInfrastructure\ww_FacilityFootprint
    \WSInfrastructure\ww_FlowControl
    \WSInfrastructure\ww_Flowmeter
    \WSInfrastructure\ww_Manhole
    \WSInfrastructure\ww_PollutionControlPlant
    \WSInfrastructure\ww_PumpingStation
    \WSInfrastructure\ww_PumpYR
    \WSInfrastructure\ww_Sewershed
    \WSInfrastructure\ww_UndergroundEnclosure
    \WSInfrastructure\ww_Valve
    \WSInfrastructure\ww_WastewaterMain
  \IlluminationWS
  \AssumptionArea

 FGDB Path = ./WS_Data.gdb
Containers = 1
   Num FCs = 50

norge% ./fgdbList ./WS_Data.gdb "\" "Feature Class"
  \IlluminationWS
  \AssumptionArea

 FGDB Path = ./WS_Data.gdb
Containers = 0
   Num FCs = 2

If you want to describe the fields of each table, you've got a starting point (just make sure you capture both paths where numFCs is incremented).

- V

UPDATED with a new zipfile and new source name, without timing and with corrected counting 21:24 EDT

MuneemHabiba
New Contributor

yes sir, this is exactly what i want. Sir i am confused in one thing we will get this always on second level? like we will first call getchilddataset() and then loop through each class and call again getchilddatasets() then we will get these names?

0 Kudos