List metadata with Python

15278
36
06-20-2011 01:00 PM
JoshThompson
New Contributor III
I have a list of feature classes from a geodatabase I created from a Python script and would like to add their respective metadata or a portion of (such as the description portion of the ArcGIS metadata style) to this list by feature class. Is this possible with Python or am I asking too much?

Thanks,
Josh
Tags (2)
36 Replies
JoshThompson
New Contributor III
Beautiful! That did it. Thanks Curtis for all your help and everyone else who contributed. Also, the indention to distinguish datasets from feature classes was a nice touch. Hadn't thought of that...

Josh
0 Kudos
JoshThompson
New Contributor III
All,

I just wanted to address two small issues with this script I have encountered:

First, the script works great in the Python window in ArcMap/ArcCatalog, but produces errors in Pythonwin:
(ExecuteError: Failed to execute. Parameters are not valid.
ERROR 000816: The tool is not valid.
Failed to execute (ExportMetadata).

Second, if the name of your feature class has the same name as the feature dataset it resides in, it will cause the script to fail. (ex. - Data.gbd>Contours>Contours) Will also terminate if no text is found in the metadata component it is looking for.

I just wanted to let anyone who may use this script to be aware of these issues.


Josh
David_JAnderson
New Contributor III
I banged my head against the 000816 error for a while until reading this thread.  I could not get the exportmetadata to work in a Python IDLE window or even as a script file run from IDLE.  I could get the command to work from the Python window in ArcCatalog and I could run the script so long as it was a script tool in a toolbox.
Definitely something odd about how the parameters are being handled internally versus externally.
0 Kudos
KyleChouinard
New Contributor
For those who cant get metadata conversions to work outside of the python window in arcgis check this thread post #5,  you may have to adjust your commands if you are running 64bit windows

http://forums.arcgis.com/threads/15433-Python-Errors-in-IDLE-but-Works-in-ArcCatalog
0 Kudos
stevepeedell
New Contributor
Hi

I have written some python code that goes recursively through a filesystem, lists all datasets and either a) generates a stub metadata file if none exists (ISO19139), or b) converts the existing MD file to ISO19139. I then put all the 19139 metadata into GeoNetwork.

So far, so good. Only now I have encountered some old metadata that is in the pre ArcGIS10 format and needs to be upgraded. How can I test for this in code and perform the upgrade?



       existing_xml = os.path.join(dirname, dataset + '.xml') #this checks that a dataset has an xml file, not very elegant, as it could be any xml and not necessarily a metadata file, and I have no way of distinguishing between ESRI-ISO, FGDC and other schema
       if arcpy.Exists(existing_xml):
             # do the conversion
             arcpy.ESRITranslator_conversion (existing_xml, translator, r'\\export\outputfile.xml') # this fails if the MD is pre ArcGIS10

Thanks

Steve
0 Kudos
curtvprice
MVP Esteemed Contributor

if arcpy.Exists(existing_xml):
    # do the conversion
    arcpy.ESRITranslator_conversion (existing_xml, translator, r'\\export\outputfile.xml') # this fails if the MD is pre ArcGIS10


The Python Way is to save yourself trouble by taking the approach of instead of asking for permission, asking for forgiveness later. It sounds messy, but the approach has an elegance that (I think) is really remarkable.

For example (note, totally untested code):
import os
import arcpy
from arcpy import conversion as CV
# get translator path
InstallDir = arcpy.GetInstallInfo("Desktop")["InstallDir"]
translator = os.path.join(InstallDir,r"\Metadata\Translator",
                 "ESRI_ISO2ISO19139.xml")

# input and output
docThing = r"C:\work\myfile.gdb\featureclass"
outXML = os.path.join(r"\\export",os.path.basename(docThing)) + ".xml"
try:
    CV.ESRITranslator(docThing, translator, outXML) 
except:
    # export failed
    try:
        # perhaps this metadata just needs upgrade?
        print "upgrading %s to 10..." % docThing
        CV.UpgradeMetadata(docThing,"ESRIISO_TO_ARCGIS")
    finally:
        # in any case, if upgrade fails or not, create or update 
        # metadata off the dataset properties
        CV.SynchronizeMetadata(docThing,"ALWAYS")
    try:
        # one more time try to export
        CV.ESRITranslator(docThing, translator, outXML)
    except:
        print "Metadata export failed for " + docThing
MattTenold
New Contributor III
I have your script working Curtis, but how do you write an if then statement for feature classes without a purpose(description) filled in?

Thanks
0 Kudos
curtvprice
MVP Esteemed Contributor
You'd need to parse the metadata  [post=121311]as shown above[/post] and work with what you find

        tree = ElementTree()
        tree.parse(xmlfile)
        spot = tree.find("idinfo/descript/purpose")
[/post]
0 Kudos
MattTenold
New Contributor III
The thing is I keep getting an error since about half of the feature classes do not have text in the description field, if I add a description then the script continues.   Here is the error I receive when it finds a feature class with no text in the description of the metadata.   Runtime error <type 'exceptions.AttributeError'>: 'NoneType' object has no attribute 'text'   Isn't there a way to add an if else statement?
0 Kudos
curtvprice
MVP Esteemed Contributor
The thing is I keep getting an error since about half of the feature classes do not have text in the description field, if I add a description then the script continues.   Here is the error I receive when it finds a feature class with no text in the description of the metadata.   Runtime error <type 'exceptions.AttributeError'>: 'NoneType' object has no attribute 'text'   Isn't there a way to add an if else statement?


Here's an approach that may help:

spot = tree.find("idinfo/descript/abstract") 
if spot: # if spot is True (not None)
    print spot.text 
else:
    print "No abstract"


A more pythonesque approach tries and asks forgiveness:
try:
    Abstract = tree.find("idinfo/descript/abstract").text
except:
    Abstract = "No abstract"
0 Kudos