Usi ArcPy per ottenere la simbologia dei livelli?


16

Poiché ArcGIS 10 viene fornito con il pacchetto ArcPy, mi chiedo che sia possibile utilizzare le funzioni ArcPy per ottenere Symbology (ovvero colore, larghezza ...) di un livello?

Risposte:


15

Per ArcGIS 10.0, se è possibile utilizzare un approccio di sola lettura, il seguente esempio di codice rivela il campo (e la tabella unita) che costituisce la base per la simbologia di un livello. Esporta un msd temporaneo (un file zip contenente file XML) e carica gli attributi specifici in un oggetto. Queste classi potrebbero essere estese per ottenere l'accesso ad attributi di livello aggiuntivi.

import zipfile
from arcpy import mapping
import os
from xml.dom.minidom import parse


class LayerExtras(object):
    """ An object to hold attributes loaded from xml inside the msd."""

    name = ""
    symbologyFieldName = ""


class MxdExtras(dict):
    """ Exposes extra MXD details by raiding an exported msd

        Treat this object as a dictionary with layer name as the key and a custom object
        with desired attributes as the value.
        You must have write access to MXD directory (creates temporary msd file).
        Only layers in the first dataframe are accessed.

    """    

    LYR_NAME_NODE = "Name"
    LYR_SYMBOL_NODE = "Symbolizer"
    LYR_FIELD_NODE = "Field"
    MSD_SUFFIX = "_MxdExtrasTemp.msd"
    MXD_SUFFIX = ".mxd"
    EXCLUDED_FILE_NAMES = ["DocumentInfo.xml", "layers/layers.xml"]
    mxdPath = ""

    def __init__(self, mxdPath):

        self.loadMxdPath(mxdPath)


    def loadMxdPath(self, mxdPath):
        """ Load mxd from file path """

        self.mxdPath = mxdPath.lower()
        mxd = mapping.MapDocument(self.mxdPath)

        msdPath = self.mxdPath.replace(self.MXD_SUFFIX, self.MSD_SUFFIX) 

        # Delete temporary msd if it exists
        if os.path.exists(msdPath):
            os.remove(msdPath)

        mapping.ConvertToMSD(mxd,msdPath)

        zz = zipfile.ZipFile(msdPath)

        for fileName in (fileName for fileName in zz.namelist() if not fileName in self.EXCLUDED_FILE_NAMES):
            dom = parse(zz.open(fileName))
            name, lyr = self.loadMsdLayerDom(dom)
            self[name] = lyr
        del zz
        os.remove(msdPath)

    def loadMsdLayerDom(self, dom):
        """ Load dom created from xml file inside the msd. """

        lyr = LayerExtras()  

        # Layer name
        lyr.name = dom.getElementsByTagName(self.LYR_NAME_NODE)[0].childNodes[0].nodeValue

        # Symbology field name
        symbologyElement = dom.getElementsByTagName(self.LYR_SYMBOL_NODE)[0]
        lyr.symbologyFieldName = symbologyElement.getElementsByTagName(self.LYR_FIELD_NODE)[0].childNodes[0].nodeValue

        return lyr.name, lyr


############
# Test

if __name__ == "__main__":

    mxdPath = r"c:\temp\AmphibianSpeciesRichnessAverageOf30mCells.mxd"

    mxde = MxdExtras(mxdPath)

    for lyr in mxde.itervalues():
        print "Layer Name: ", lyr.name 
        print "Layer Symbology Field Name: ", lyr.symbologyFieldName
        print 

Esempio di output del test:

Layer Name:  Amphibian Species Richness Average of 30m Cells
Layer Symbology Field Name:  biodiversity.AmphAve

Utilizzare un gestore di contesto per quel file zip: with zipfile.ZipFile(msdPath) as zz:.
jpmc26,

@MichaelJackson Nel tuo codice, ho solo sostituito il percorso mxd. Ma ho ricevuto un errore sulla linea `lyr.symbologyFieldName = symbologyElement.getElementsByTagName (self.LYR_FIELD_NODE) ​​[0] .childNodes [0] .nodeValue`, dicendo list index out of range. questo perché symbologyElement.getElementsByTagName(self.LYR_FIELD_NODE)è vuoto. Ma perché è vuoto? Ho pensato che questa fosse un'alternativa al metodo lyr.symbology, ma non funziona ancora.
Panda,

@panda Questa è una vecchia risposta. Stai utilizzando una versione successiva alla 10.0? In caso affermativo, vedere la risposta di seguito relativa alla proprietà simbologia dell'oggetto layer.
MJ,

@MichaelJackson Uso la proprietà della simbologia ma sembra che non sia supportata in tutti i casi, come quando il layer utilizza più di un campo per la simbologia. Devo ottenere i nomi dei campi utilizzati, ma non riesco a trovare un metodo.
panda,

10

ArcPy sembra consentire di modificare la simbologia, ma solo con i file .lyr esistenti e non specificare i simboli direttamente nel codice in base alla mia lettura del modulo.


6

In ArcGIS 10.1 e versioni successive è possibile accedere direttamente alla simbologia tramite la proprietà simbologia dell'oggetto layer .

Per ArcGIS 10.0 le soluzioni alternative menzionate hanno funzionato per me.


sfortunatamente, la simbologia di un livello è di sola lettura (secondo la quinta istanza di "simbologia" in questa pagina , così come quella che hai citato).
Roland

1
Tuttavia "Non sono supportati tutti i tipi di classe di simbologia di livello; per quelli che non lo sono, viene restituita la parola chiave OTHER". . I tipi non supportati includono valori univoci raster, valori univoci per molti campi e densità dei punti. Questo è ancora vero in ArcGIS 10.5. Se sei abbastanza fortunato da avere un SymbologyType
matt wilkie,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.