Vous utilisez ArcPy pour obtenir la symbologie des couches?

16

Étant donné qu'ArcGIS 10 est fourni avec le package ArcPy, je me demande s'il est possible d'utiliser les fonctions ArcPy pour obtenir la symbologie (c'est-à-dire la couleur, la largeur ...) d'une couche?

VietThanh Le
la source

Réponses:

15

Pour ArcGIS 10.0, si vous pouvez utiliser une approche en lecture seule, l'exemple de code suivant révèle le champ (et la table jointe) qui constitue la base de la symbologie d'une couche. Il exporte un msd temporaire (un zip contenant des fichiers xml) et charge les attributs spécifiques dans un objet. Ces classes peuvent être étendues pour accéder à des attributs de couche supplémentaires.

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 

Exemple de sortie de test:

Layer Name:  Amphibian Species Richness Average of 30m Cells
Layer Symbology Field Name:  biodiversity.AmphAve
MJ
la source
Utilisez un gestionnaire de contexte pour ce fichier zip: with zipfile.ZipFile(msdPath) as zz:.
jpmc26
@MichaelJackson Dans votre code, je n'ai remplacé que le chemin mxd. Mais j'ai eu une erreur sur la ligne `lyr.symbologyFieldName = symbologyElement.getElementsByTagName (self.LYR_FIELD_NODE) ​​[0] .childNodes [0] .nodeValue`, disant list index out of range. c'est parce que le symbologyElement.getElementsByTagName(self.LYR_FIELD_NODE)est vide. Mais pourquoi est-il vide? J'ai supposé qu'il s'agit d'une alternative à la méthode lyr.symbology, mais cela ne fonctionne toujours pas.
panda
@panda C'est une vieille réponse. Utilisez-vous une version supérieure à 10.0? Si oui, voir la réponse ci-dessous à propos de la propriété de symbologie de l'objet de couche.
MJ
@MichaelJackson J'utilise la propriété de symbologie mais il semble qu'elle ne soit pas prise en charge dans tous les cas, comme lorsque la couche utilise plus d'un champ pour la symbologie. J'ai besoin d'obtenir les noms des champs utilisés, mais je ne trouve pas de méthode.
panda
10

ArcPy cherche à vous permettre de modifier la symbologie, mais uniquement avec les fichiers .lyr existants , et non à spécifier les symboles directement dans votre code en fonction de ma lecture du module.

scw
la source
6

Dans ArcGIS 10.1 et versions ultérieures, il existe un accès direct à la symbologie via la propriété de symbologie de l'objet de couche .

Pour ArcGIS 10.0, les solutions de contournement mentionnées ont fonctionné pour moi.

Bernd
la source
malheureusement, la symbologie d'une couche est en lecture seule (selon la cinquième instance de "symbologie" sur cette page , ainsi que celle que vous avez citée).
Roland
1
Cependant "Tous les types de classe de symbologie de couche ne sont pas pris en charge; pour ceux qui ne le sont pas, le mot clé OTHER est renvoyé." . Les types non pris en charge incluent les valeurs uniques raster, les valeurs uniques de nombreux champs et la densité de points. Cela est toujours vrai dans ArcGIS 10.5. Si vous avez la chance d'avoir un SymbologyType pris en charge, voir le script dans gis.stackexchange.com/questions/184133/…
matt wilkie