How can I remove WMS layers from mxds using arcpy ?

2450
5
10-21-2011 02:48 PM
RachaelYule
New Contributor II
Hi - I'm trying to remove WMS layers from an mxd using arcpy. I can successfully remove "MapServer" type services using the below code, but not WMS?

Any ideas? Is arcpy.mapping.RemoveLayer the best approach ? I have hundreds of mxds to crawl through and want to remove WMS layers from them.

Here's my mxd with two different WMS layers in for reference: here

import arcpy, os

inFName = "wms.mxd"
outFName = "wms_removed.mxd"
pth = r"c:\temp"
inFULLPTH = os.path.join(pth,inFName)
outFULLPTH = os.path.join(pth,outFName)
mxd = arcpy.mapping.MapDocument(inFULLPTH)

for df in arcpy.mapping.ListDataFrames(mxd):
    LyrList = arcpy.mapping.ListLayers(mxd, "", df)
    print LyrList

    for lyr in LyrList:
        if lyr.supports("SERVICEPROPERTIES"):
            if lyr.serviceProperties["ServiceType"] == "WMS":
                print "Removing: " + lyr.name + ": " + lyr.serviceProperties["ServiceType"]
                arcpy.mapping.RemoveLayer(df, lyr)

mxd.saveACopy(outFULLPTH)
del mxd
0 Kudos
5 Replies
JeffBarrette
Esri Regular Contributor
I think I found the issue.  The root WMS service layer does not support "ServiceProperties", it is only the sub layers.  Individual sub layers can't be removed - that is also the case in the UI.

For example, you have:

Europe BGR Geology by Age (Geochronologic)  - as the root layer - this does not support ServiceProperties but it CAN be removed.

Europe BGR 5M Geological Units - Offshore - this is a sub layer under the layer above.  This does support ServiceProperties but CAN NOT be removed (just like in the UI).

One possible workaround is that you identify the sub-layers but remove the parent.  This can be done by using the LYR.longName property which would be:

Europe BGR Geology by Age (Geochronologic)\Europe BGR 5M Geological Units - Offshore

Find the layer with the root name("Europe BGR Geology by Age (Geochronologic)") and remove that layer.

I hope this helps.  In the meantime, I'll mark this as a bug and hopefully get it fixed in the next service pack.

Jeff
0 Kudos
RachaelYule
New Contributor II
Hi Jeff - many thanks for your time. Yep - I think I can work round the remove WMS bug using the top group layer that you suggested.

Unfortunately, a can of worms has now opened!  I've written a script to test for different types of layers in a given mxd to assist with general data management.  However, I have two further queries that have come out of this:

#1 (the main problem):
I'm trying to identify different layers that support services, using the: lyr.supports("SERVICEPROPERTIES") property of the Layer class in the mapping module. It seems that I can identify WMS successfully, but I'm NOT able to test ArcGIS Server map services hosted on the arcgisonline servers. For example the World Imagery layer set fails the  lyr.supports("SERVICEPROPERTIES") test. Please see below code.  Also, as requested, please find the map package to mxd/data that I've been using: here

#2:
Regarding layers that are NOT Feature, Raster or Group Layers, such as CAD annotations, I've been trying to find a way to test what type of layers these are.  I've resorted to the Describe class to test that the lyr.source is a 'FeatureClass' dataType. Then hook on to the featureType to expose what type of feature it is. In this case CAD annotations = "CoverageAnnotation".  Basically, is this the best way to test Layers in mxd that support DATASOURCE, but are that are not Feature Layers ?

Hope this is all clear from the code and the map package...many thanks for your help!

import arcpy, os, string

mxdPTH = "c:\temp\example05_services.mxd"
mxd = arcpy.mapping.MapDocument(mxdPTH)

try:

    #loop through data frames
    for df in arcpy.mapping.ListDataFrames(mxd):

        #get layers list & loop through
        LyrList = arcpy.mapping.ListLayers(mxd, "", df)
        for lyr in LyrList:

            #test for group layer:
            if lyr.isGroupLayer == True:
                print "Group Layer Type:  " + lyr.name

            #test for raster layer:
            elif lyr.isRasterLayer == True:
                print "Raster Layer Type:  " + lyr.name

            #test for feature layer:
            elif lyr.isFeatureLayer == True:
                print "Feature Layer Type:  Layer Name: " + lyr.name

            #test for service layer:
            elif lyr.supports("SERVICEPROPERTIES"):
                    print "Layer Supports 'SERVICEPROPERTIES':  Service Type:  " + lyr.serviceProperties["ServiceType"] + ":  Layer Name: " + lyr.name

            #test for non-Feature Layers that DO support DATASOURCE
            elif lyr.supports("DATASOURCE"):
                #invoke describe class
                desc = arcpy.Describe(lyr.dataSource)
                #test for FeatureClass Type
                if desc.datasetType == "FeatureClass":
                    print "Non Feature-Layer Type:  Using Describe Class: FeatureClass Type:  " + str(desc.featureType) + ":  Layer Name: " + lyr.name
                else:
                    print "Non Feature-Layer Type:  Using Describe Class: Non-FeatureClass Type:  " + str(desc.datasetType) + lyr.name

            #catch other layer types
            else:
                print "Other Layer Type: Layer Name: " + lyr.name

        #get table list & loop
        TabList = arcpy.mapping.ListTableViews(mxd, "", df)
        for tab in TabList:
            print "Table:  " + tab.name

    del mxd
    del TabList
    del LyrList

except Exception, e:
    import traceback
    map(arcpy.AddError, traceback.format_exc().split("\n"))
    arcpy.AddError(str(e))
    print "Exception: " + str(e)
0 Kudos
JeffBarrette
Esri Regular Contributor
Your first issue is very similar to the WMS layer and its sub layers.  For example, your TOC has the following layers:

World_Imagery
     World Imagery
     Low-Resolution (15m) Imagery
     High-Resolution (60cm) Imagery
     High-Resolution (30cm) Imagery


The root layer "World_Imagery" is an AGS Map service and it does support "SERVICEPROPERTIES".  The problem is that you are bypassing it with the "if" lyr.isGroupLayer statement.  After that you are using "elif" statements so you never test to see if it ALSO supports service properties, you only test the sub layers which do not.  I know this is tricky.  The service layer is a group layer AND a a service layer type= MapServer.  Again this can be done with the lyr.longName property.

Concerning your second issue and determining specific data types.  What gets reported from the describe statement does NOT match what you see in the UI when you go into the layers data source properties.  The UI lists one value but the arcpy.describe lists a different value.  I think the two should be the same and it should match the UI.  For example:

UI, Data Type = CAD Annotation Feature Class
Describe.dataType = FeatureLayer

UI, Feature Type = Simple
Describe.featureType = CoverageAnnotation.

This needs to be looked at.  I currently don't have a way to CAD data unless the "CAD" is in the layer name.

Thanks,
Jeff
0 Kudos
RachaelYule
New Contributor II
Hi Jeff - many thanks. Apologies for the delayed response. Thanks for the tip on layers being both group AND service layers, didn't think to check that.

One final question that is puzzling.  In my example mxd. The first set of "World_Imagery" layers is not recognised as a Service Layer. The other two World_Imagery groups can now be identified as supporting service layers after editing my code based on your suggestions.

Any ideas why the first set of service layers fails the if lyr.supports("SERVICEPROPERTIES"): test. I guess I could identify the world imagery layer by name, but I'd have to identify all 'older' Esri service layers by name, which is not ideal.

Cheers
Sam
0 Kudos
JeffBarrette
Esri Regular Contributor
In my first response to this thread, I said I marked this as a bug and submitted it to our developer and it is hopefully something we can address in time for SP4.

You can track it with NIM074823.

Jeff
0 Kudos